Можно ли высмеять document.cookie в JavaScript?
document.cookie
- это как строка, но это не строка. Чтобы привести пример из документа Mozilla:
document.cookie = "name=oeschger";
document.cookie = "favorite_food=tripe";
alert(document.cookie);
// displays: name=oeschger;favorite_food=tripe
Если вы попытались сделать mock cookie с использованием только строки, вы не получите одинаковых результатов:
var mockCookie = "";
mockCookie = "name=oeschger";
mockCookie = "favorite_food=tripe";
alert(mockCookie);
// displays: favorite_food=tripe
Итак, если вы хотите unit test модуль, который работает в cookie, и если вы хотите использовать mock cookie для этих тестов, не могли бы вы? Как?
Ответы
Ответ 1
Вы можете создать объект с помощью setter и getter cookie
. Вот очень простая реализация:
var mock = {
value_: '',
get cookie() {
return this.value_;
},
set cookie(value) {
this.value_ += value + ';';
}
};
Возможно, не работает во всех браузерах (особенно IE). Обновление: Он работает только в браузерах, поддерживающих ECMAScript 5!
Подробнее о getter и сеттерах.
mock.cookie = "name=oeschger";
mock.cookie = "favorite_food=tripe";
alert(mock.cookie);
// displays: name=oeschger;favorite_food=tripe;
DEMO
Ответ 2
@Felix King отвечает правильно, я просто хотел указать, что существует альтернативный синтаксис для определения сеттеров и геттеров в ECMAScript 5:
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 5th Edition), но не MSIE (или JScript).
Ответ 3
Эта реализация позволяет перезаписывать файлы 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);
Ответ 4
Лично я не смог захватить объект документа.
Простое решение, которое, кажется, работает для меня, было следующим...
В верхней части моего теста script я определяю объект 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. Я буквально вставлял это, и все это работало прямо с места в карьер.
Надеюсь, это поможет!