[英]Is it possible to mock document.cookie in JavaScript?
document.cookie
就像一個字符串,但又不是字符串。 引用Mozilla 文檔中的示例:
document.cookie = "name=oeschger";
document.cookie = "favorite_food=tripe";
alert(document.cookie);
// displays: name=oeschger;favorite_food=tripe
如果您嘗試僅使用字符串制作模擬 cookie,您將不會得到相同的結果:
var mockCookie = "";
mockCookie = "name=oeschger";
mockCookie = "favorite_food=tripe";
alert(mockCookie);
// displays: favorite_food=tripe
所以,如果你想對操作 cookie 的模塊進行單元測試,並且如果你想對這些測試使用模擬 cookie,可以嗎? 如何?
您可以使用cookie
setter和getter創建一個對象。 這是一個非常簡單的實現:
var mock = {
value_: '',
get cookie() {
return this.value_;
},
set cookie(value) {
this.value_ += value + ';';
}
};
可能不適用於所有瀏覽器(特別是IE)。 更新:它僅適用於支持ECMAScript 5的瀏覽器!
mock.cookie = "name=oeschger";
mock.cookie = "favorite_food=tripe";
alert(mock.cookie);
// displays: name=oeschger;favorite_food=tripe;
此實現允許覆蓋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);
@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"
同樣,大多數瀏覽器都支持ECMAScript 5(由ECMA-262第5版定義),但不支持 MSIE(或JScript)。
以下是我最終在 Jest 中的做法:
添加Secure
屬性后,我的 cookie 不再添加到document.cookie
(因為document.location
是不安全的http://localhost
)。
所以經過大量的試驗和錯誤(試圖攔截document.cookie
的 setter 並刪除它的;Secure
從它,但是然后再次調用document.cookie =
新值觸發了一個無限循環,因為它再次進入 setter ... ) ,我最終得到了這個非常簡單的解決方案:
beforeEach(function() {
let cookieJar = document.cookie;
jest.spyOn(document, 'cookie', 'set').mockImplementation(cookie => {
cookieJar += cookie;
});
jest.spyOn(document, 'cookie', 'get').mockImplementation(() => cookieJar);
})
我個人無法劫持文檔對象。 一個似乎對我有用的簡單解決方案如下......
在我的測試腳本的頂部,我定義了一個fakeCookie對象:
var fakeCookie = {
cookies: [],
set: function (k, v) {
this.cookies[k] = v;
},
get: function (k) {
return this.cookies[k];
},
reset: function () {
this.cookies = [];
}
};
然后在我的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]);
}
});
});
任何時候我獲得或設置cookie值它使用我的fakeCookie而不是真正的jQuery.cookie。 它通過查看傳遞的參數數量並推斷它是否為get / set來完成此操作。 我直接粘貼了這個,它都直接蝙蝠。 希望這可以幫助!!
我知道這是一個古老的話題,但在我的情況下,過期的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 ]
}
}
我發現茉莉有spyOnProperty
,當你想窺探對象的getter和setter時可以使用它。 所以我解決了我的問題:
const cookie: string = 'my-cookie=cookievalue;';
spyOnProperty(document, 'cookie', 'get').and.returnValue(cookie);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.