2015-01-02 14 views
8

Sto cercando di automatizzare il form di login di Instagram web app:modulo creato con Reagire non aggiorna l'oggetto stato di supporto

https://instagram.com/accounts/login/

Con questo codice (è possibile eseguirlo su console Chrome) :

var frm = window.frames[1].document.forms[0]; 
frm.elements[0].value = 'qacitester'; 
frm.elements[1].value = 'qatester'; 
frm.elements[2].click(); 

Anche se gli ingressi sono popolate, quando a monitorare la richiesta XHR, vedo questo è pubblicato:

username = & password = & intento =

piuttosto che questo:

username = qacitester & password = qatester & intento =

e provoca web app di non autenticare. Hai idea del motivo per cui i valori di input non vengono trasferiti allo stato di backing (model?) Oggetto di React?

risposta

1

Il modulo di accesso è in realtà all'interno di un iFrame, il che rende le cose un po 'più complicate. Sono stato in grado di inviare correttamente un login con il seguente codice dalla console cromata. Sto usando TestUtils di reagire, ma si può essere bene con AutoType:

// run in Chrome console 
var frame = document.querySelector('iframe[src*="login"]'); 
var s = document.createElement('script'); 
var username = frame.contentDocument.querySelector('input[name="username"]'); 
var password = frame.contentDocument.querySelector('input[name="password"]'); 
s.src = "https://fb.me/react-with-addons-0.12.0.js"; 
frame.contentDocument.body.appendChild(s); 

// wait for the script request to resolve and use: 
change = frame.contentWindow.React.addons.TestUtils.Simulate.change; 
change(username, {target: {value: 'My Great Username'}}); 
change(password, {target: {value: 'securepassword'}}); 

Sfondo

Reagire utilizza un proprio sistema di evento virtuale, e in genere utilizza controlled components, il che significa essenzialmente l'ingresso value è impostato reagendo e scendendo verso l'elemento DOM.

Con questo in mente, credo che il problema riscontrato sia perché reagisce alla ricerca di un evento chiave sull'input e utilizza il valore dell'ingresso al momento dell'evento per impostare il valore dell'elemento DOM. Dato che stai semplicemente impostando la proprietà value dell'elemento DOM, stai interrompendo il ciclo dei componenti controllati.

Ho fatto un picco veloce tentando di inviare un KeyboardEvent sull'input, ma è stato, purtroppo, non riuscito. Aggiornerò la mia risposta se davvero riuscirò.

soluzione non soddisfacente:

Usa Casper/phantomjs per automatizzare la compilazione. Ciò significa che non devi preoccuparti degli eventi di spedizione e puoi semplicemente lasciare che sia il "browser" a farlo per te. È anche meglio che lavorare manualmente nella console.

+0

Come ho commentato la risposta di altri, ho usato jquery.autotype che spara praticamente tutto il eventi necessari e cerca di simulare il comportamento dell'utente che digita le lettere ma non riesco ancora a farlo funzionare. Ho bisogno di risolvere questo problema nel contesto di JS mentre sto automatizzando un wrapper di Chrome di terze parti che posso controllare solo tramite codice JS. – huseyint

+0

@huseyint quindi sembra che il modulo sia in un iFrame. Ho aggiornato il mio codice con un hack molto hacky che sono riuscito a inviare il modulo con successo; probabilmente non realizzerà ciò che vuoi fare programmaticamente, ma è un inizio :) –

+0

lol, grazie per lo sforzo, ma sto cercando una soluzione JS pura :) – huseyint

5

Instagram sta usando il metodo linkState da ReactLink:

http://facebook.github.io/react/docs/two-way-binding-helpers.html

I collegamenti pagina di login per un bundles/Login.js che contiene il codice compresso in questo modo:

o.createElement("input", { 
    className:"lfFieldInput", 
    type:"text", 
    name:"username", 
    maxLength:30, 
    autoCapitalize:!1, 
    autoCorrect:!1, 
    valueLink:this.linkState("username") 
})) 

Se si guarda la documentazione per ReactLink, questo significa che il valore del campo di input viene inviato nuovamente allo stato quando l'evento change viene attivato sui campi di input. Tuttavia, non è così semplice come l'attivazione dell'evento di modifica sul nodo in questione - penso a causa del modo in cui React normalizza gli eventi del browser. La documentazione reagiscono specificamente dicono che onChange in Reagire non è esattamente la stessa di onChange nel browser per vari motivi:

http://facebook.github.io/react/docs/dom-differences.html

fortuna nel vostro caso si utilizza Instagram reagire con Programmi relazionati incluso che consente di accedere a reagire TestUtils, in modo da poter fare:

var frm = window.frames[1].document.forms[0]; 
var fReact = window.frames[1].React; 
fReact.addons.TestUtils.Simulate.change(frm.elements[0], {target: {value: 'qacitester' }}); 
fReact.addons.TestUtils.Simulate.change(frm.elements[1], {target: {value: 'qatester' }}); 
frm.elements[2].click(); 

Più documentazione qui:

http://facebook.github.io/react/docs/test-utils.html

Si noti che poiché il modulo di login stesso è in un iframe, è necessario utilizzare l'istanza di React da tale iframe altrimenti i TestUtils non saranno in grado di trovare i nodi correttamente.

Questo sarà solo funziona in situazioni in cui React Addons sono inclusi nella pagina. La normale build di Add-on di React richiederà un'altra soluzione. Tuttavia, se stai parlando specificamente di ReactLink, è comunque un addon, quindi non è un problema.

+0

In realtà ho usato jquery.autotype (https://github.com/mmonteleone/jquery.autotype) per popolare gli input ma ancora nessun dado. http://screencast.com/t/gfhWW4rD3R – huseyint

+0

L'evento 'change' si attiva solo se il campo guadagna, quindi perde lo stato attivo (sfocatura) * e * il valore viene modificato in mezzo. Pertanto, se esegui un riempimento automatico dei moduli che non esegue la messa a fuoco e la sfocatura, non funzionerà comunque. –

+0

Ho modificato il mio commento con una soluzione che funziona senza librerie aggiuntive. –

4

Rispondendo alla mia domanda, l'evento richiesto è ingresso evento che sembra e questo codice funziona:

var doc = window.frames[1].document; 
var frm = doc.forms[0]; 
frm.elements[0].value = 'qacitester'; 
var evt = doc.createEvent('UIEvent'); 
evt.initUIEvent('input', true, false); 
frm.elements[0].dispatchEvent(evt); 
frm.elements[1].value = 'qatester'; 
frm.elements[1].dispatchEvent(evt); 
frm.elements[2].click(); 
Problemi correlati