Código que estoy tratando de probar:
$(".toggle_item").on("change", function() { console.log("change triggered") item_name = $(this).data("name"); value = $(this).prop("checked"); if (Item.isValid(item_name) && cartModule.isUnique(item_name)) { cartModule.toggleItem(item_name, value); } })
Especificaciones de jasmine:
describe("changing toggle item", function() { beforeEach(function() { console.log("in spec") affix(".toggle_item[data-name='ladder']") spyOn(cartModule, "isUnique") spyOn(Item, "isValid") $(".toggle_item").trigger("change") }) it("should check item for validity & cart for uniqueness", function() { expect(Item.isValid).toHaveBeenCalledWith("ladder") expect(cartModule.isUnique).toHaveBeenCalledWith("ladder") }) })
La salida del registro de la consola indica que el disparador no se disparó. Salida de registro:
> "in spec"
FWIW:
loadFixtures
como loadFixtures
$(".toggle_item").on("change"...
y $(".toggle_item").change...
Lista de gems:
jasmine (2.7.0) jasmine-core (2.8.0, 2.7.0) jasmine-jquery-rails (2.0.3) jasmine-rails (0.14.1)
** Respuesta actualizada: 2018-02-03 **
El problema fundamental aquí es que su código se está ejecutando demasiado pronto, antes de que se hayan configurado sus dispositivos. Esto es diferente a cargar su código antes de todas sus pruebas. Debe poder controlar cuándo se ejecuta su código una vez que se ha cargado .
Esto tiene más que ver con la forma en que escribe su código para que pueda probarse, y es en gran medida independiente de las herramientas y bibliotecas que realmente se utilizan para las pruebas.
Aquí hay un ejemplo:
// There is no way to test this expression - it runs as soon as it is loaded 1 + 2 // This is similar to the line above - it tries to add the event listener as soon // as the line of code is encountered. If you haven't set up fixtures before this line is run // then you can't test it. $('.toggle_item').on('change', ...); // Here is an example of code that is testable // It is testable because we have separated out the loading of the code // from the **invocation** of the code. function add(){ // ie This expression will only run when `add()` is invoked. return 1 + 2; } // Here is an example that adds a bit more control over when the event listeners are added. $(function(){ // This expression runs when `$.ready` is fired (aka `DOMContentLoaded`) // If you can delay `$.ready` until your fixtures are set up then this will work. $('.toggle_item').on('change', ...); })
La explicación en su respuesta vinculada no es del todo correcta. $('.selector').click(...)
es solo un alias o short-hand para $('.selector').on('click', ...)
así que cambiar a eso no hará que diferencia – son funcionalmente exactamente iguales.
La razón por la que la respuesta realmente funciona en ese caso es porque el detector de eventos se agrega al evento $.ready()
lugar de hacerlo inmediatamente tan pronto como se carga el código.
Es la diferencia entre ejecutar esto:
console.log('1 before'); console.log('2 middle'); console.log('3 after');
Resultado:
> 1 before > 2 middle > 3 after
Y ejecutando esto:
console.log('1 before'); $(function(){ console.log('2 middle'); }); console.log('3 after');
Resultado:
> 1 before > 3 after > 2 middle
Otra herramienta que podría ayudarlo aquí son los oyentes de eventos delegates .
Básicamente, agrega un único detector de eventos a un elemento más arriba en el árbol DOM que escucha eventos de selectores secundarios particulares.
p.ej:
$(function(){ $(document).on('change', '.toggle_item', function(){ }); })
El beneficio de esto es que el detector de eventos se puede agregar antes, evento antes de que exista .toggle_item
, pero los escuchas se activarán una vez que se hayan agregado los elementos.
Hay algunas advertencias sobre el uso de delegates de eventos (por ejemplo, cuando se usa event.preventDefault()
o event.stopPropagation()
) pero aún son una herramienta muy útil.
Respuesta original
En su código bajo prueba, ¿puede controlar / retrasar cuando se agrega el detector de eventos?
Sospecho que su código está intentando agregar el detector de eventos a .toggle_item
antes de que se .toggle_item
la .toggle_item
del affix(".toggle_item[data-name='ladder']")
en sus pruebas.
console.log('Adding listener') $(".toggle_item").on("change", function() { console.log("change triggered") ... });
Sabrás que está fuera de orden si obtienes:
> "Adding listener" > "in spec"
En lugar de lo que queremos:
> "in spec" > "Adding listener"