是否可以在 JavaScript 中模拟 document.cookie?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6456429/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is it possible to mock document.cookie in JavaScript?
提问by thisgeek
document.cookie
is like a string, but it is not a string. To quote the example from the Mozilla doc:
document.cookie
就像一个字符串,但它不是一个字符串。引用Mozilla 文档中的示例:
document.cookie = "name=oeschger";
document.cookie = "favorite_food=tripe";
alert(document.cookie);
// displays: name=oeschger;favorite_food=tripe
If you tried to make a mock cookie using only a string, you would notget the same results:
如果您尝试仅使用字符串制作模拟 cookie,则不会得到相同的结果:
var mockCookie = "";
mockCookie = "name=oeschger";
mockCookie = "favorite_food=tripe";
alert(mockCookie);
// displays: favorite_food=tripe
So, if you wanted to unit test a module that operates on the cookie, and if you wanted to use a mock cookie for those tests, could you? How?
因此,如果您想对一个对 cookie 进行操作的模块进行单元测试,并且如果您想对这些测试使用模拟 cookie,您可以吗?如何?
采纳答案by Felix Kling
You could create an object with a cookie
setter and getter. Here is a very simple implementation:
您可以使用cookie
setter 和 getter创建一个对象。这是一个非常简单的实现:
var mock = {
value_: '',
get cookie() {
return this.value_;
},
set cookie(value) {
this.value_ += value + ';';
}
};
Might not work in all browsers though (especially IE). Update:It only works in browsers supporting ECMAScript 5!
虽然可能不适用于所有浏览器(尤其是 IE)。更新:它仅适用于支持 ECMAScript 5 的浏览器!
More about getter and setters.
mock.cookie = "name=oeschger";
mock.cookie = "favorite_food=tripe";
alert(mock.cookie);
// displays: name=oeschger;favorite_food=tripe;
回答by mcintyre321
This implementation allows overwriting cookies, and adds document.clearCookies()
此实现允许覆盖 cookie,并添加 document.clearCookies()
(function (document) {
var cookies = {};
document.__defineGetter__('cookie', function () {
var output = [];
for (var cookieName in cookies) {
output.push(cookieName + "=" + cookies[cookieName]);
}
return output.join(";");
});
document.__defineSetter__('cookie', function (s) {
var indexOfSeparator = s.indexOf("=");
var key = s.substr(0, indexOfSeparator);
var value = s.substring(indexOfSeparator + 1);
cookies[key] = value;
return key + "=" + value;
});
document.clearCookies = function () {
cookies = {};
};
})(document);
回答by maerics
@Felix Kling's answer is right on, I just wanted to point out that there is an alternate syntax for defining setters and getters in ECMAScript 5:
@Felix Kling 的回答是正确的,我只是想指出在 ECMAScript 5 中定义 setter 和 getter 有另一种语法:
function MockCookie() {
this.str = '';
this.__defineGetter__('cookie', function() {
return this.str;
});
this.__defineSetter__('cookie', function(s) {
this.str += (this.str ? ';' : '') + s;
return this.str;
});
}
var mock = new MockCookie();
mock.cookie = 'name=oeschger';
mock.cookie = 'favorite_food=tripe';
mock.cookie; // => "name=oeschger;favorite_food=tripe"
And again, most browsers support ECMAScript 5 (defined by ECMA-262 5th Edition) but notMSIE (or JScript).
同样,大多数浏览器支持 ECMAScript 5(由 ECMA-262 第 5 版定义),但不支持MSIE(或 JScript)。
回答by user2125726
I figured out that jasmine has spyOnProperty
which can be used for when you want to spy on getter and setters of objects. So I solved my issue with this:
我发现 jasminespyOnProperty
可以用于当你想监视对象的 getter 和 setter 时。所以我用这个解决了我的问题:
const cookie: string = 'my-cookie=cookievalue;';
spyOnProperty(document, 'cookie', 'get').and.returnValue(cookie);
回答by omarjebari
Personally i was unable to hiHyman the document object. A simple solution which seems to work for me was the following...
我个人无法劫持文档对象。一个似乎对我有用的简单解决方案如下......
At the top of my test script i define a fakeCookie object:
在我的测试脚本的顶部,我定义了一个 fakeCookie 对象:
var fakeCookie = {
cookies: [],
set: function (k, v) {
this.cookies[k] = v;
},
get: function (k) {
return this.cookies[k];
},
reset: function () {
this.cookies = [];
}
};
Then in my beforeEach() i define my cookie stub. This basically intercepts calls to jQuery.cookie and (instead!) call the callback function that i have defined (see below):
然后在我的 beforeEach() 中定义我的 cookie 存根。这基本上会拦截对 jQuery.cookie 的调用,并(相反!)调用我定义的回调函数(见下文):
beforeEach(function() {
var cookieStub = sinon.stub(jQuery, "cookie", function() {
if (arguments.length > 1) {
fakeCookie.set(arguments[0], arguments[1]);
}
else {
return fakeCookie.get(arguments[0]);
}
});
});
Any time that i get or set a cookie value it uses my fakeCookie instead of the real jQuery.cookie. It does this by looking at the number of parameters passed and deduces whether its a get/set. I literally pasted this in and it all worked straight off the bat. Hope this helps!!
每当我获取或设置 cookie 值时,它都会使用我的 fakeCookie 而不是真正的 jQuery.cookie。它通过查看传递的参数数量并推断其是否为 get/set 来做到这一点。我从字面上粘贴了这个,一切都直接起作用了。希望这可以帮助!!
回答by Samuel Elh
I know this is an old topic, but in my case expiring cookies was necessary so here's a solution that combines the above answers and a setTimeout
call to expire cookies after X
seconds:
我知道这是一个老话题,但在我的情况下,使 cookie 过期是必要的,所以这里有一个解决方案,它结合了上述答案和setTimeout
在X
几秒钟后调用使 cookie 过期的方法:
const fakeCookies = {
// cookie jar
all: {},
// timeouts
timeout: {},
// get a cookie
get: function(name)
{
return this.all[ name ]
},
// set a cookie
set: function(name, value, expires_seconds)
{
this.all[ name ] = value;
if ( expires_seconds ) {
! this.timeout[ name ] || clearTimeout( this.timeout[ name ] )
this.timeout[ name ] = setTimeout(() => this.unset(name), parseFloat(expires_seconds) * 1000)
}
},
// delete a cookie
unset: function(name)
{
delete this.all[ name ]
}
}