2011-06-23 24 views
17

document.cookie es como una cadena, pero no es una cadena. Para citar el ejemplo de la Mozilla doc:¿Es posible burlarse de document.cookie en JavaScript?

document.cookie = "name=oeschger"; 
document.cookie = "favorite_food=tripe"; 
alert(document.cookie); 
// displays: name=oeschger;favorite_food=tripe 

Si ha intentado hacer una galleta simulada utilizando sólo una cadena, que le no obtener los mismos resultados:

var mockCookie = ""; 
mockCookie = "name=oeschger"; 
mockCookie = "favorite_food=tripe"; 
alert(mockCookie); 
// displays: favorite_food=tripe 

Por lo tanto, si desea para probar en unidad un módulo que opera en la cookie, y si desea utilizar una cookie simulada para esas pruebas, ¿podría hacerlo? ¿Cómo?

+0

getters & setters en navegadores web más recientes. – zzzzBov

+0

Puede probar un objeto simulado simple que escribí para este propósito: https://github.com/RichardKnop/CookieMock –

Respuesta

14

Puede crear un objeto con un setter 0 getter cookie. Aquí hay una implementación muy simple:

var mock = { 
    value_: '', 

    get cookie() { 
     return this.value_; 
    }, 

    set cookie(value) { 
     this.value_ += value + ';'; 
    } 
}; 

Puede que no funcione en todos los navegadores (especialmente IE). Actualización: ¡Solo funciona en navegadores compatibles con 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; 

DEMO

+0

Entonces, lo que implica es que puede, por supuesto, imitar el comportamiento, pero la interfaz _no puede ser la misma . ¿Está bien? – thisgeek

+0

@thisgeek: No estoy seguro de lo que quiere decir ... es la misma interfaz o me falta algo? –

+0

Leí mal lo que escribiste.No hubo ':' entre 'get' y' cookie', pero mi mente lo puso allí de todos modos. Eso significa que su solución depende del soporte de ECMAScript 5 en el motor JS, con el que puedo vivir. – thisgeek

8
respuesta de

@Felix Rey es correcto, yo sólo quería señalar que existe una sintaxis alternativa para la definición de las incubadoras y captadores de 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" 

Y de nuevo , la mayoría de los navegadores son compatibles con ECMAScript 5 (definido por ECMA-262 5th Edition) pero no MSIE (o JScript).

6

Esta aplicación permite sobrescribir las cookies, y añade 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); 
+0

La unión debe hacerse con un separador ";" para seguir la implementación real: 'return output.join ("; ");' – Alvis

0

Personalmente he podido secuestrar el objeto de documento. Una solución sencilla que parece funcionar para mí fue la siguiente ...

En la parte superior de mi escritura de la prueba i definir un objeto fakeCookie:

var fakeCookie = { 
    cookies: [], 
    set: function (k, v) { 
     this.cookies[k] = v; 
    }, 
    get: function (k) { 
     return this.cookies[k]; 
    }, 
    reset: function() { 
     this.cookies = []; 
    } 
}; 

Luego, en mi beforeeach() i defino mi galleta talón. (! En su lugar) Este intercepta llamadas básicamente a jQuery.cookie y llamar a la función de devolución de llamada que he definido (véase más adelante):

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]); 
     } 
    }); 
}); 

Cada vez que i obtener o establecer un valor de cookie que utiliza mi fakeCookie en lugar de la real jQuery.cookie. Hace esto mirando el número de parámetros pasados ​​y deduce si es un get/set. Literalmente pegué esto y todo funcionó de inmediato. Espero que esto ayude !!

Cuestiones relacionadas