Je teste un peu de JavaScript avec Jasmine et je souhaite espionner (mock) un élément du DOM accessible par un sélecteur jQuery.
Ma spécification est:
it("should be able to mock DOM call", function() {
spyOn($("#Something"), 'val').andReturn("bar");
result = $("#Something").val();
expect(result).toEqual("bar");
});
Dans mon specrunner.html j'ai:
<input type="hidden" id="Something" value="foo" />
Malheureusement, la spécification échoue avec:
devrait être capable de se moquer de l'appel DOM Attendu "foo" pour égaler "bar".
Cette ligne est fausse:
spyOn($("#Something"), 'val').andReturn("bar");
La fonction spyOn de Jasmine attend deux paramètres. Le premier est un objet existant. Le second est un nom de fonction sous forme de chaîne. Vous passez correctement le nom de la fonction sous forme de chaîne ("val") mais vous ne passez pas dans un objet existant en tant que premier paramètre.
$("#Something")
... n'est pas un objet existant. C'est le résultat (la valeur de retour) d'un sélecteur jQuery. Plus spécifiquement, il retournera un objet jQuery représentant les nœuds correspondants - un peu comme un tableau de résultats.
$
... est un objet existant.
$.fn
... est un objet existant.
$("#Something")
... est pas un objet existant - c'est le résultat d'un sélecteur jQuery .
Cela fonctionnera:
it("should be able to mock DOM call", function () {
//spyOn($.fn, "val").andReturn("bar"); //pre-jasmine 2.0 syntax
spyOn($.fn, "val").and.returnValue("bar"); //Jasmine 2.0 Syntax
var result = $("#Something").val();
expect(result).toEqual("bar");
});
On dirait que j'ai trouvé une bonne solution
it "should open past statuses", ->
# We can't use $('.past') here cause each time $('.past') called it returns different objects
# so we need to store spy in variable
showSpy = spyOn($.fn, 'show')
# do the stuff
$('.show-past').click()
# then check if 'show' action was called
expect($.fn.show).toHaveBeenCalled()
# and if it realy our object
expect(showSpy.mostRecentCall.object.selector).toEqual('.past')
Ce n'est pas basé sur votre code mais j'espère que cela peut aider quelqu'un. Et, oui, exemple dans CoffeScript.
Le problème est que les deux appels à $ renvoient deux nœuds enveloppés jQuery différents.
Cela devrait fonctionner:
it("should be able to mock DOM call", function(){
// var node = $("Something");
// spyOn(node, 'val').andReturn('bar');
// expect(node.val()).toEqual('bar');
var node = $("Something");
spyOn(node, 'val').and.returnValue('bar');
expect(node.val()).toEqual('bar');
});
La prochaine fois, l'aide sera plus répandue sur la liste de diffusion Jasmine: [email protected].
Vous pouvez créer votre propre faux élément DOM, puis utiliser $ ('# elementid') [0] comme d'habitude
addFakeElementWithId = function (elementId) {
var fake = document.createElement("div");
fake.setAttribute("id", elementId);
document.body.appendChild(fake);
};
J'ai écrit une fonction d'assistance, qui accepte un tableau de paires id/valeur.
var jasminTestHelper = {
spyOnValAndFake : function(obj) {
var i, j;
spyOn($.fn, 'val').andCallFake(function() {
for ( i = 0, j = obj.length; i < j; i++) {
if (this.selector === '#' + obj[i][0]) {
return obj[i][1];
}
}
})
}
}
Chaque paire indique à la fonction faker pour quel id, quelle valeur doit être renvoyée si la fonction jQuery-val () - est appelée avec le sélecteur d'id. Il est utilisé comme ceci:
jasminTestHelper.spyOnValAndFake([["id1", "value1"], ["id2", "value2"]]);
Si $('#id1').val()
est appelée dans votre fonction en cours de test, la fausse fonction retourne value1
, Si $('#id2').val()
est appelée, elle retourne value2
. Vous n'avez donc pas besoin de jouer avec le DOM, vous vous moquez simplement de la fonction jQuery-val () - et simulez les valeurs de retour. D'autres fonctions jQuery pourraient probablement se moquer de la même manière.
Je pense qu'il y a un changement dans ma version jasmin (2.0.3), donc la solution d'Alex York n'a pas fonctionné telle quelle, mais m'a définitivement donné un chemin. Voici donc le code de travail de spécification qui doit être testé
$('someSelector').data('someAttribute').enable();
voici la partie spec jasmin de celui-ci
var mockJqueryObject = { enable:function(){},disable:function(){}};
//this mocks the .data('someAttribute') in above code.
spyOn($.fn, "data").and.returnValue(mockSelectBoxObject);
Une spécification plus granulaire pourrait utiliser un autre niveau de simulation comme
spyOn(mockJqueryObject,"enable")
spyOn(mockJqueryObject,"disable")