2012-11-02 15 views
7

Sto usando Rails 3.2.8 conrails3-jquery-autocomplete: come testare con RSpec e Capybara?

  • gioiello 'jquery-rails', '2.1.2'
  • gemma 'Rails3-jquery-completamento automatico', '1.0.9'
  • gioiello 'RSpec-rails', '' 2.11.4
  • gioiello 'Capybara', '1.1.3'
  • gemma 'capibara-WebKit', '' 0.12.1

ho recentemente convertito un elenco a discesa di selezione per un completamento automatico (noi ing rails3-jquery-autocomplete) e sto cercando di aggiornare le specifiche della mia richiesta per compilare il completamento automatico.

Il mio approccio è stato quello di creare un aiutante come mostrato nella this gist:

def fill_autocomplete(field, options = {}) 
    fill_in field, :with => options[:with] 

    selector = "ul.ui-autocomplete a:contains('#{options[:select]}')" 

    page.should have_selector selector 
    page.execute_script "$(\"#{selector}\").mouseenter().click()" 
end 

Se risulto che con Webkit, il test non riesce con questo messaggio:

expected css "ul.ui-autocomplete a:contains('Firstname Lastname')" to return something. 

Se provo con selenio , mentre guardo il test procedere in Firefox, faccio non vedere l'elenco a discesa che appare. Aggiungere un sleep 3 per attendere che il menu a discesa non sia di aiuto.

Vedo here che c'è un problema correlato ma un po 'vecchio con capybara-webkit, qualcosa su quando un campo è compilato, è immediatamente sfocato, che ovviamente impedirebbe la visualizzazione dell'elenco di selezione automatico. Ma questo non sembra strambare con gli altri che hanno ottenuto questo lavoro.

È attualmente possibile testare un modulo che include un campo rails-jquery-autocomplete con RSpec e Capybara? Come? In caso contrario, esiste un modo per compilare manualmente il campo id nascosto in modo da poter verificare che il modulo crei i dati corretti?

risposta

9

Finalmente i test di completamento automatico funzionano almeno con il driver Selenium.

La soluzione è mettere a fuoco il campo ed emettere un evento keydown.

Ho confermato questo prima con il test manuale in un browser. Se utilizzo il mouse (non Ctrl-V) per incollare un termine di ricerca in un campo di completamento automatico, non accade nulla: non viene visualizzato alcun elenco a discesa. Questo è apparentemente l'equivalente di ciò che accade quando Capybara invia un comando fill_in. Tuttavia, dopo che il termine è nel campo, mentre lo stato attivo è ancora sul campo, se tocco un tasto qualsiasi, ad es. il tasto Maiusc, appare la lista di selezione. Quindi apparentemente la lista di selezione appare solo quando viene premuto un tasto.

Opzione 1

Una soluzione è quella di estendere la funzione dalla domanda originale come segue:

def fill_autocomplete(field, options = {}) 
    fill_in field, :with => options[:with] 

    page.execute_script %Q{ $('##{field}').trigger("focus") } 
    page.execute_script %Q{ $('##{field}').trigger("keydown") } 
    selector = "ul.ui-autocomplete a:contains('#{options[:select]}')" 

    page.should have_selector selector 
    page.execute_script "$(\"#{selector}\").mouseenter().click()" 
end 

e quindi chiamare in questo modo:

fill_autocomplete "to_contact_name", with: "Jone", select: "Bob Jones" 

Opzione 2

Un approccio simile, adattato dal Steak test nella principale gemma rails3-jquery-completamento automatico, utilizza il FILL_IN norma, seguita da questo choose_autocomplete_result:

def choose_autocomplete_result(item_text, input_selector="input[data-autocomplete]") 
    page.execute_script %Q{ $('#{input_selector}').trigger("focus") } 
    page.execute_script %Q{ $('#{input_selector}').trigger("keydown") } 
    # Set up a selector, wait for it to appear on the page, then use it. 
    item_selector = "ul.ui-autocomplete li.ui-menu-item a:contains('#{item_text}')" 
    page.should have_selector item_selector 
    page.execute_script %Q{ $("#{item_selector}").trigger("mouseenter").trigger("click"); } 
end 

che si chiama così:

fill_in "to_contact_name", :with => "Jone" 
choose_autocomplete_result "Bob Jones", "#to_contact_name" 

Ho adottato il secondo approccio per i miei test. Sembra piuttosto affidabile con Selenium ma non funziona con il webkit, il che è un problema, dato che i test del selenio sono piuttosto lenti al confronto. Una soluzione che funziona sotto il webkit sarebbe il benvenuto!

+1

sì, non ha funzionato con Webkit. L'ho testato su capybara + poltergeist (webkit env), si è bloccato sulla convalida di have_selector. quando eseguo il debug con uno screencast, ho trovato che l'elemento di completamento automatico è stato generato, ma l'oggetto pagina non lo riconosce. – raykin

+2

La soluzione dell'opzione 1 non funziona perché 'contains' non è valido selettori CSS W3C (questo è solo jQuery). L'ho risolto con la soluzione elencata in http: // StackOverflow.it/questions/6355586/testing-jquery-autocomplete-ui-with-cetriolo con il mio nome –

0

Invece di utilizzare page.execute_script, ho inserito l'input vuoto con il mio input in modo che l'evento si attivasse.

fill_in("query", :with => "ma") 
fill_in("query", :with => "") 
# autocomplete suggestions will come up 
all('.autocomplete div').first.should have_content("mango") 
# other assertions 
3

Anch'io mi sono imbattuto nello stesso dolore. Dopo aver trascorso alcune ore su questo, ho un valido aiuto che funziona sia con il selenio che con il polstergeist, più nessun uso di sleep(). Il seguente codice è stato testato con Capybara 2.1.0:

def fill_autocomplete(field, options = {}) 
    fill_in field, with: options[:with] 

    page.execute_script %Q{ $('##{field}').trigger('focus') } 
    page.execute_script %Q{ $('##{field}').trigger('keydown') } 
    selector = %Q{ul.ui-autocomplete li.ui-menu-item a:contains("#{options[:select]}")} 

    page.should have_selector('ul.ui-autocomplete li.ui-menu-item a') 
    page.execute_script %Q{ $('#{selector}').trigger('mouseenter').click() } 
    end 

In sostanza, dico Capybara a compilare il campo di input poi usare JS per attivare l'evento keydown per attivare completamento automatico. Tuttavia, al posto di sleep(), approfitto dello page.should have_selector('ul.ui-autocomplete li.ui-menu-item a') che aspetta finché non viene visualizzato l'elenco a discesa. Quindi utilizzo JS per attivare l'evento mouseenter, quindi fare clic. Mi auguro che ci sia un modo migliore di fare cose con JS eval, ma questa è la soluzione più affidabile che potrei trovare.

+1

Keydown non sta attivando il codice di completamento automatico con Poltergeist. Ho verificato ciò aggiungendo una finestra di input fittizio sullo schermo e allegando un listener di keydown che rende solo un oggetto di test visibile o invisibile. Quindi faccio uno screenshot prima e dopo nel test. Quindi so che l'evento keydown sta funzionando, ma per qualche ragione NON sta attivando il codice di autocompletamento che funziona così bene nel browser. Hai qualche idea? Ho trascorso quasi 48 ore di lavoro su questo e non riesco proprio a superarlo. – AKWF

2

Se qualcuno ha bisogno di un po 'di codice per ispirazione (ho messo un po anche dopo aver letto questa discussione), questo funziona:

 context "with 5 items results" do 
     before do 
      5.times { FactoryGirl.create(:item, title: "chinese " + random_string(5)) } 
      page.execute_script("$('input#search_param').val('chinese')") 
      page.execute_script("$('input#search_param').trigger('focus')") 
      page.execute_script("$('input#search_param').trigger('keydown')") 
     end 
     specify { page.evaluate_script("$('input#search_param').val()").should == 'chinese' } 
     specify { page.should have_css "#autocomplete-menu li", count: 5 } 
     end 

Grazie Mark Berry per l'ispirazione.

1

Un'altra opzione è il capibara send_keys metodo:

find('#my_object_id').send_keys 'bob'

Io preferisco questa opzione sopra l'iniezione di javascript per sparare keydown eventi/focus/MouseEnter.

Problemi correlati