Bazı JS çalıştırıldıktan sonra Capybara'nın görünürlük kontrolü nasıl yapılır?


82

Bir sayfayı yükledikten sonra, xhr tarafından döndürülen verilere göre çeşitli öğeleri çalıştıran, gizleyen ve gösteren kodum var.

Entegrasyon testim şuna benzer:

it "should not show the blah" do
    page.find('#blah').visible?.should be_true
end 

El ile bağlamda sayfanıza test seferlerine gittiğinizde, #blah olduğunu değil beklediğim olarak görülebilir. Capybara'nın sayfanın ilk durumuna baktığından (bu durumda görünmez), DOM'un durumunu değerlendirdiğinden ve JS çalışmadan önce testte başarısız olduğundan şüpheleniyorum.

Evet, :js => trueiçeren açıklama bloğunu ayarladım :)

Herhangi bir fikir çok takdir edilecektir! Buraya kasıtlı bir gecikme koymak zorunda kalmamamı umuyorum, bu rahatsızlık hissi veriyor ve işleri yavaşlatacak.


1
Sürücü nedir? XHR bittiğinde beklenen HTML nedir?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Yanıtlar:


132

findBuradaki ifadenin örtük bekleme ile olduğunu düşünüyorum , bu nedenle Capybara öğe sayfada olana kadar bekleyecek, ancak görünür olmasını beklemeyecek.

Burada, Capybara'nın görünür öğenin görünmesini beklemesini istersiniz; bu, visibleseçeneği belirleyerek elde edilebilir olmalıdır :

expect(page).to have_selector('#blah', visible: true)

Denemedim, ancak her zaman görünür öğeleri beklemek ignore_hidden_elementsistiyorsanız , yapılandırma seçeneği burada da yararlı olabilir find.


6
@ Kevin'in notunu (benim gibi) birisinin başlangıçta gözden kaçırması durumunda, js:truebunun işe yaraması için kapsayıcı bloğa sahip olmalısınız .
Chris Beck

3
Bu harika. expect(page).to have_selector('#flash-message', visible: false, text: "Signed in Successfully")
Chuck Bergeron

Bir jquery aşağı kayma öğesinin görünürlüğünü test ederken görünür seçeneğinin benim için hiçbir etkisi olmadı. Beklemek (find ('# blah'). Görünür mü?). Be_falsey kullanmak zorunda kaldım.
trueinViso

İs_visible gibi bir şey istiyorum? o zaman başka bir şey yap
user1735921

37

Bu, benim için mükemmel çalışan başka bir yol:

find(:css, "#some_element").should be_visible

Özellikle daha karmaşık buluntular için

find(:css, "#comment_stream_list li[data-id='#{@id3}']").should_not be_visible

bu, bir öğenin gizlendiğini iddia eder.


1
should_not be_visibleCapybara yayınlandıkça bana iyi görünmüyor wait_until { base.visible? }zaman Eleman # görünür? çağrılıyor.
Phương Nguyenễn

1
@ phng-nguyn, #wait_until, Capybara'nın son sürümlerinden kaldırıldı.
solidcell

3
Bu aslında "page.should have_selector ..." seçeneğinden daha iyi bir varyanttır, çünkü başarısız bir metin olması durumunda, öğenin aslında açıkça görünmez olduğu söylenirken, bahsedilen varyant sadece 'eşleşme yok' hatasını çağrıştırır. bu biraz sinir bozucu.
installero

Bu, kabul edilen çözümle aynı değildir. Bu kod için, Capybara yalnızca öğe DOM'a girene kadar bekleyecek ve ardından görünürlüğü hemen kontrol edecektir. Görünürlüğün değişmesini bekliyorsanız, bu teknik özelliklere bir yarış koşulu ekleyebilir.
johncip

1
.should_not be_visibleKapakların display: nonejQuery tarafından ayarlanıp ayarlanmadığını bilen var mı ? Benim için işe yaramıyor gibi görünüyor.
Antrikshy

20

Sayfada bir öğenin görünüp görünmediğini kontrol etmek visible: falseistiyorsanız, beklediğiniz gibi çalışmayacaktır. Beni biraz şaşırttı.

İşte nasıl yapılacağı:

# assert element is present, regardless of visibility
page.should have_css('#some_element', :visible => false)
# assert visible element is not present
page.should have_no_css('#some_element', :visible => true)

1
Sen kullanamazsınız should_notçünkü ajax, Kapibara ile
Marc-André LaFortune

@ Marc-AndréLafortune, ajax'ı capibara ile test etmek için Capybara.javascript_driver kullanın.
Zubin

1
javascript_drive ile, have_cssöğeyi bulmayı beklediği için vazgeçmeden önce tüm zaman aşımı sürenizi bekler. Örneğin should have_no_contentbunun yerine kullanmanız gerekiyor should_not have_content.
Marc-André Lafortune

1
expect(page).not_to have_selector("#some_element", visible: true)javascript_drivertüm zaman aşımı süresini beklemeden kullandığım için iyi çalıştı .
Jason Swett

1
Aslında, yorumumdan bu yana, bu değiştirildi ve should_notşimdi kullanabilirsiniz (ve kullanmalısınız) , üzgünüm!
Marc-André Lafortune

9

Kullanarak:

 Ruby:     ruby 1.9.3dev (2011-09-23 revision 33323) [i686-linux]
 Rails:    3.2.9
 Capybara: 2.0.3

Tıklandığında bir AJAX gönderi isteği göndermesi ve bir JS yanıtı döndürmesi gereken bir bağlantının olduğu bir Rails uygulamam var.

Bağlantı kodu:

 link_to("Send Notification", notification_path(user_id: user_id), remote: true, method: :post)

JS yanıtı (.js.haml dosyası), bağlantının bulunduğu sayfada aşağıdaki gizli div'i değiştirmelidir:

 #notification_status(style='display:none')

js.haml dosyasının içeriği:

:plain
  var notificationStatusContainer = $('#notification_status');
  notificationStatusContainer.val("#{@notification_status_msg}");
  notificationStatusContainer.show();

Cucumber kullanarak kullanıcıya bildirim gönderme ve bildirim durumu mesajını görüntüleme senaryomu test ediyordum ( yerleşik Capybara destekli salatalık-rayları mücevher )

İd: notification_status öğesine sahip öğenin adım tanımımda başarılı yanıtta görünür olup olmadığını test etmeye çalışıyordum.Bunun için aşağıdaki ifadeleri denedim:

page.find('#notification_status').should be_visible
page.should have_selector('#notification_status', visible: true)
page.should have_css('#notification_status', visible: true)
page.find('#notification_status', visible: true)
page.find(:css, 'div#notification_status', visible: true)

Yukarıdakilerin hiçbiri benim için işe yaramadı ve adımımı başaramadı. Yukarıda listelenen 5 parçadan son 4 tanesi aşağıdaki hatayla başarısız oldu:

'expected to find css "#notification_status" but there were no matches. Also found "", which matched the selector but not all filters. (Capybara::ExpectationNotMet)'

bu garipti çünkü aşağıdaki ifade doğru şekilde geçiyordu:

page.has_selector?('#notification_status')

Aslında, sayfa kaynağını kullanarak inceledim.

  print page.html

hangisi geldi

<div style='' id='notification_status'></div>

beklenen oldu.

Sonunda bu bağlantı capybara'nın, bir elemanın özniteliğinin ham şekilde nasıl inceleneceğini gösteren bir elemanın niteliklerini öne sürdüğünü buldum .

Ayrıca Capybara belgelerinde görünür mü buldum? yöntem ( http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Element#visible%3F-instance_method ) aşağıdaki bilgiler:

 Not all drivers support CSS, so the result may be inaccurate.

Böylece, bir elementin görünürlüğünü test ederken Capybara'nın görünür sonuçlarına dayanmadığı sonucuna vardım. bir CSS seçici kullanırken ve bağlantı capybara'da önerilen çözümü kullanırken bir öğenin niteliklerini ileri sürerken yöntem

Aşağıdakileri buldum:

 module CustomMatchers
   def should_be_visible(css_selector)
    find(css_selector)['style'].should_not include('display:none', 'display: none')
   end
 end

 World(CustomMatchers)

Kullanım:

should_be_visible('#notification_status')

8

Görünür ne anlama geliyor açık değil

Başarısızlık, görünür olmadığı, sürücünün taşınabilir olmadığı ve belgelenmemiş olduğu için neyin görünür olduğu veya olmadığı konusundaki yanlış anlaşılmadan kaynaklanabilir. Bazı testler:

HTML:

<div id="visible-empty"                                                                   ></div>
<div id="visible-empty-background"      style="width:10px; height:10px; background:black;"></div>
<div id="visible-empty-background-same" style="width:10px; height:10px; background:white;"></div>
<div id="visible-visibility-hidden"     style="visibility:hidden;"                        >a</div>
<div id="visible-display-none"          style="display:none;"                             >a</div>

Rack testinin görünmez olduğunu düşündüğü tek şey satır içi display: none( inline) (seçiciler yapmadığı için dahili CSS değil):

!all('#visible-empty',                 visible: true).empty? or raise
!all('#visible-empty-background',      visible: true).empty? or raise
!all('#visible-empty-background-same', visible: true).empty? or raise
!all('#visible-visibiility-hidden',    visible: true).empty? or raise
 all('#visible-display-none',          visible: true).empty? or raise

Poltergeist'in benzer bir davranışı vardır, ancak dahili CSS ve Js style.displaymanipülasyonu ile başa çıkabilir :

Capybara.current_driver = :poltergeist
!all('#visible-empty',                 visible: true).empty? or raise
!all('#visible-empty-background',      visible: true).empty? or raise
!all('#visible-empty-background-same', visible: true).empty? or raise
!all('#visible-visibiility-hidden',    visible: true).empty? or raise
 all('#visible-display-none',          visible: true).empty? or raise

Selenyum oldukça farklı davranır: boş bir öğeyi görünmez visibility-hiddenolarak kabul ederse ve ayrıca display: none:

Capybara.current_driver = :selenium
 all('#visible-empty',                 visible: true).empty? or raise
!all('#visible-empty-background',      visible: true).empty? or raise
!all('#visible-empty-background-same', visible: true).empty? or raise
 all('#visible-visibiility-hidden',    visible: true).empty? or raise
 all('#visible-display-none',          visible: true).empty? or raise

Diğer bir yaygın yakalama, varsayılan değerdir visible:

  • eskiden false(görür hem görünür hem de görünmez öğeleri ),
  • şu anda true
  • Capybara.ignore_hidden_elementsseçenek tarafından kontrol edilir .

Referans .

Tam çalıştırılabilir testi benim GitHub'dan .


1
Harika cevap - buna harcadığınız çaba için teşekkürler. Birden çok sürücü kullanarak bir paketteki öğelerin görünürlüğünü test etmek önemsiz bir şey değildir.
Andy Triggs

1
"eskiden yanlıştı (hem görünür hem de görünmez öğeleri görür), şu anda doğrudur ve Capybara.ignore_hidden_elements seçeneğiyle kontrol edilir." Daha fazla bilgi için bu blog gönderisine bakın: elabs.se/blog/60-introducing-capybara-2-1
rizidoro

5

Tüm ajax istekleri tamamlanana kadar beklemek için örnek bir yöntem sunan bu gönderiye bakmak isteyebilirsiniz :

def wait_for_ajax(timeout = Capybara.default_wait_time)
  page.wait_until(timeout) do
    page.evaluate_script 'jQuery.active == 0'
  end
end

5
Bu çözüm, uyumlu bir gelecek değil wait_untiledilmiş Capybara 2 kaldırıldı .
parhamr

1
KullanTimeout.timeout
Ian Vaughan

Daha iyi kullanımSelenium::WebDriver::Wait
Nakilon

sadece selenyum kullanıyorsanız
Nickolay Kondratenko

2

Kabul edilen yanıt artık biraz geçerliliğini yitirmiştir, çünkü 'gerektiği' sözdizimi kaldırılmıştır. Bu günlerde şu çizgide bir şeyler yapmaktan daha iyi olursunexpect(page).not_to have_css('#blah', visible: :hidden)


1

Buradaki diğer cevaplar, elementi "beklemenin" en iyi yoludur. Ancak bunun üzerinde çalıştığım site için işe yaramadığını buldum. Temel olarak, tıklanması gereken öğe, arkasındaki işlev tam olarak yüklenmeden önce görülüyordu. Bu bir saniyenin kesirleri içinde, ancak testimin o kadar hızlı yapıldığını gördüm ki, düğmeye tıkladı ve hiçbir şey olmadı. Bu değişimli boole ifadesini yaparak bunun etrafında çalışmayı başardım:

if page.has_selector?('<css-that-appears-after-click>')
  puts ('<Some-message-you-want-printed-in-the-output>')
else
  find('<css-for-the-button-to-click-again>', :match == :first).trigger('click')
end

Temel olarak, görünmesi gereken bir şeyi aramak için capibara varsayılan bekleme süresini kullanır, eğer orada değilse, tıklamanızı yeniden deneyecektir.

Yine önce should have_selectoryöntemin denenmesi gerektiğini söyleyeceğim ama işe yaramazsa şunu deneyin

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.