2013-07-30 10 views
9

Sto scrivendo alcuni test per una direttiva Angular e ho bisogno di simulare l'input dell'utente in un campo di input. Ho provato a fare questo:Attivare manualmente il binding di dati angolari per un campo di input (solo a scopo di test unitario)

element.find('input').val('some value').trigger('input'); 

ma non ha funzionato. Triggering change non ha funzionato neanche. So che posso accedere direttamente allo scope dell'elemento con element.scope() e modificarlo, ma sembra più naturale modificare il valore dell'input e lasciare che Angular esegua il binding dei dati.

Per quello che vale, ho verificato input(name).enter(value) da angolare ngScenario, e sembra di fare lo stesso come ho fatto io:

... 
input.val(value); 
input.trigger(event || (supportInputEvent ? 'input' : 'change')); 
... 

Che cosa mi manca? C'è un modo migliore per testare l'input dell'utente in questo caso?

(ho fatto a jsFiddler script per illustrare la questione)

UPDATE

Penso che è necessario qualche chiarimento. Non sto provando a cambiare il DOM né l'ambito al di fuori del regno angolare di per sé. Ho una direttiva che esegue il rendering di una casella di input associata a una proprietà dell'ambito della direttiva. Sto scrivendo test automatizzati per garantire che la direttiva faccia ciò che deve fare, e ciò che un test dovrebbe fare è simulare alcuni input in modo che l'ambito della direttiva venga aggiornato e posso affermare che alcuni comportamenti vengono eseguiti su quell'input. Come ho detto prima, posso modificare lo scope della direttiva dal codice di test usando element.scope(), ma preferirei cambiare il valore dell'input e lasciare che Angular faccia il suo esempio.

+0

Come testare la direttiva? Il modo in cui fai scattare un evento di input mi sembra giusto. Lo stai facendo in un file di prova, giusto? – ghiden

+0

@ghiden Ho già avuto risposta alla mia domanda - vedi sotto. Grazie per il tuo interesse, però. :) –

risposta

7

Dopo aver trascorso un po 'di tempo alla ricerca e sperimentazione, ho capito cosa non andava: jqLite registra gestori di eventi utilizzando addEventHandler e che non vengano innescato dalla funzione jQuery trigger. Il mio script jsFiddle non funzionava perché lo script di Angular veniva caricato prima di jQuery (e quindi stava usando jqLite). Ho aggiornato the script per caricare tutto nell'ordine corretto in modo che Angular utilizzi la funzione jQuery on per registrare i gestori di eventi e ora simula le modifiche sulla casella di input e dice ad Angular di eseguire il binding dei dati.

Il mio codice di test non funzionava per lo stesso motivo. L'ho risolto cambiando anche l'ordine degli script. Se non mi è capitato di utilizzare jQuery, dovrei attivare l'evento chiamando dispatchEvent anziché trigger.

+2

Il 'trigger' di jQuery ** fa ** i gestori di fuoco collegati tramite' addEventListener': http://jsbin.com/APEwimu/1 (fonte: http://jsbin.com/APEwimu/1/edit). Questo è vero per un tempo [lungo] (http://jsbin.com/APEwimu/2), [** lungo **] (http://jsbin.com/APEwimu/3) (1.2.6 era come molto indietro come ho deciso di andare). Testato su Chrome, Firefox e [IE8] (http://jsbin.com/APEwimu/4) - ha dovuto modificare lo script per quest'ultimo, ovviamente, perché vuole 'attachEvent'. –

+0

@ T.J.Crowder È strano. Potresti aiutarmi a capire perché [il mio primo script] (http://jsfiddle.net/2ZLuW/1/) non funziona? –

+0

Ricevo un errore $ apply già in corso: ti sei mai imbattuto in questo quando si attiva manualmente un evento 'input'? – bennlich

-2

Questo non è l'approccio giusto per farlo in modo angolare. Dovresti fare così.

Working DEMO

Creare funzione all'interno della $ portata e cambiare il tuo valore variabile in modo che angolare si aggiornerà il vostro campo di input, così come in tutti i luoghi in cui è stato utilizzato (bind) questa variabile.

Angular Function

$scope.changeInput = function() { 
    $scope.value="barfoo"; 
} 
+0

Ho paura che non risponda alla mia domanda.Aggiornerò il post per chiarire le cose. –

Problemi correlati