2016-03-22 106 views
1

我知道wait_until由於某種原因從水豚中刪除。水豚擅長等待,使用find時它會等待很好,但在處理AJAX應用程序時,有時候我必須使用all方法。例如,我正在處理可以通過單擊列名進行排序的HTML表格。當我對列名應用排序,然後調用all(td, text: column_name)時,它會返回排序前存在的值,因爲all方法不會像find方法那樣等待。我目前正在使用一個定製的幫手wait_for_ajax來處理這種情況。我不想傳遞額外的:wait的說法。有更好的方法來處理它嗎?如何在使用水豚時在水豚中等待

回答

1

如果您正在測試的應用程序,那麼這是比較容易的,因爲你知道的測試數據,所以你可以做這樣的事情

expect(page).to have_css('table tr:first-child', text 'text first in order when sorted') 

這將等待表的第一行有文本應該在排序發生後按排序順序排在第一位。

如果您在屏幕上抓取或測試某個應用程序,而您在某種程度上不知道測試數據,則會變得更加困難。在對列進行排序時,除了行的順序以外,頁面上的任何事情都會發生變化嗎?是否有排序指示符,排序列標題突出顯示等?如果是這樣,你可以等待,假設它在更新列之前並不實際更新(如果一旦它被點擊就更新,那麼這將不起作用,並且可能實際上是一個糟糕的UI,因爲你可以結束與數據不一致)。例如,如果列標題獲得一類'排序',您可以執行類似於

expect(page).to have_css('table th td.sorted', text: 'text of the column header you sorted by') 

這將等待正確的標題以指示它已排序。

如果確實沒有任何指示排序完成的更改,那麼您的運氣不佳,而且您已經遇到了類似wait_for_ajax應用程序的極少數情況之一。

注意:在這種情況下,傳遞:wait選項根本無濟於事。這是因爲它是最大將等待匹配元素被發現的時間量,並且#all有效地匹配0個元素 - 它仍然會立即返回(沒有任何其他答案中提到的計數選項,正如您指出的那樣反正在這裏幫不了你)

+0

謝謝湯姆。列標題確實會得到一個類'.sorted',一旦點擊。其實,我已經在這種情況下使用了'wait_for_ajax'幫手。我可以等待'.sorted'我想,但考慮到在使用水豚的時候,在大多數情況下幾乎不需要等待,因爲你的建議可能會增加等待時間,當'wait_for_ajax'可以完成這項工作嗎?可能這是不好的做法,但考慮到有很多情況下它是必要的,我發現它通常起作用。當我們不得不在一頁上使用'all' – Rahul

1

我使用它在觸發事件之前加載所有的HTML內容。只要你想指定等待

def wait_for_ajax 
    Timeout.timeout(Capybara.default_wait_time) do 
    loop do 
     active = page.evaluate_script('jQuery.active') 
     break if active == 0 
    end 
    end 
end 
+0

時,使我不必處理等待情況。default_wait_time在較新版本的Capybara中已棄用,默認情況下爲default_max_wait_time。最重要的是 - 使用這樣的超時可能會導致一些Capybara驅動程序中斷,因爲它可能會在evaluate_script中間中斷,並使驅動程序通信堆棧保持未知狀態 - 查看Capybara中的「#synchronize」for如果你真的需要wait_for_ajax,這是一個更安全的方法 - 通常不需要99%的時間(OP可能有1%的情況) –

+1

謝謝,我已經在使用它了。我想知道是否有更好的方法。 – Rahul

0

這是邊緣情況下,一個wait_for_ajax方法實際上是正確的選擇一個你可以調用此方法。繼承人我的執行不使用Timeout湯姆建議可能會導致錯誤。

def wait_for_ajax 
    start = Time.now.tv_sec 
    stop = false 
    until stop do 
    active = page.evaluate_script('jQuery.active') 
    if active == 0 
     stop = true 
    elsif (Time.now.tv_sec - start) > Capybara.default_max_wait_time 
     stop = true 
     raise Exception.new("WaitForUrlError: Timed out waiting for url: #{url}") 
    end 
    end 
end