일부 JS가 실행 된 후 Capybara가 가시성을 확인하도록하는 방법은 무엇입니까?


82

페이지를로드 한 후 xhr에서 반환 한 데이터를 기반으로 다양한 항목을 실행하고 숨기고 표시하는 코드가 있습니다.

내 통합 테스트는 다음과 같습니다.

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

이 테스트가 실행되는 컨텍스트의 페이지로 수동으로 이동하면 #blah가 예상대로 표시 되지 않습니다 . Capybara가 페이지의 초기 상태 (이 경우에는 보이지 않음)를보고 DOM의 상태를 평가하고 JS가 실행되기 전에 테스트에 실패했다고 생각합니다.

예, :js => true포함 설명 블록에 설정했습니다 . :)

어떤 아이디어라도 대단히 감사하겠습니다! 나는 여기에 고의적 인 지연을 넣을 필요가 없기를 바라고 있습니다.


1
운전자는 무엇입니까? XHR이 완료되면 예상되는 HTML은 무엇입니까?
치로 틸리는郝海东冠状病六四事件法轮功

답변:


132

find여기에 있는 진술은 묵시적 ​​대기가 있는 진술 이라고 생각 하므로 Capybara는 요소가 페이지에있을 때까지 기다리지 만 표시 될 때까지 기다리지 않습니다.

여기에서 Capybara가 보이는 요소가 나타날 때까지 기다리기를 원할 것입니다. 이는 visible옵션 을 지정하여 달성 할 수 있어야합니다 .

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

나는 그것을 시도하지 않았지만 항상 보이는 요소를 기다리고 ignore_hidden_elements싶다면 구성 옵션이 여기에서도 유용 할 수 있습니다 find.


6
누군가가 처음에 @Kevin의 메모 (나와 같은)를 놓친 경우, js:true이것이 작동하려면 컨테이너 블록에 있어야합니다 .
Chris Beck

3
굉장합니다. : 그것은 나를에 도착 도움 expect(page).to have_selector('#flash-message', visible: false, text: "Signed in Successfully")이 답변을 게시 주셔서 감사합니다 -
척 Bergeron의

보이는 옵션은 jquery 슬라이드 다운 요소의 가시성을 테스트 할 때 나에게 영향을 미치지 않았습니다. 나는 expect (find ( '# blah'). visible?). to be_falsey를 사용해야했다.
trueinViso

is_visible 같은 걸 원해? 다음 다른 사람이 다른 어떻게 좀 할
user1735921

37

이것은 나를 위해 완벽하게 작동하는 또 다른 방법입니다.

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

특히 다음과 같은 더 복잡한 발견의 경우

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

요소가 숨겨져 있다고 주장합니다.


1
should_not be_visible카피 바라 실행으로 나에게 잘 보이지 않는 wait_until { base.visible? }경우가 요소 # 보이지? 호출됩니다.
푸옹 응웬

1
@ phng-nguyn, #wait_until이 최신 버전의 카피 바라에서 제거되었습니다.
solidcell 2013

3
이것은 실제로 "page.should have_selector ..."보다 더 나은 변형입니다. 텍스트가 실패하는 경우 요소가 실제로는 명시 적으로 보이지 않는다고 말하는 반면 언급 된 변형은 '일치하는 항목이 없습니다'오류를 유발하기 때문입니다. , 조금 실망 스럽습니다.
installero

이것은 허용 된 솔루션과 동일하지 않습니다. 이 코드의 경우 Capybara는 요소가 DOM에있을 때까지만 기다린 다음 즉시 가시성을 확인합니다. 가시성이 변경 될 것으로 예상하는 경우 사양에 경쟁 조건을 추가 할 수 있습니다.
johncip

1
아무도 jQuery에 의해 설정된 .should_not be_visible커버 인지 알고 display: none있습니까? 나를 위해 작동하지 않는 것 같습니다.
Antrikshy 2011 년

20

요소가 페이지에 있지만 표시 visible: false되지 않는지 확인하려면 예상대로 작동하지 않습니다. 내가 약간 당황했다.

방법은 다음과 같습니다.

# 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
should_notajax 때문에 capybara와 함께 사용할 수 없습니다
Marc-André Lafortune 2013

@ Marc-AndréLafortune은 capybara로 ajax를 테스트하려면 Capybara.javascript_driver를 사용합니다.
Zubin 2013

1
javascript_drive를 사용 have_css하면 요소를 찾을 것으로 예상하기 때문에 포기하기 전에 전체 시간 초과 기간을 기다립니다. 예를 들어 당신이 사용해야하는 should have_no_content대신 should_not have_content.
Marc-André Lafortune 2013

1
expect(page).not_to have_selector("#some_element", visible: true)javascript_driver전체 시간 초과 기간을 기다리지 않고을 사용하여 잘 작동했습니다 .
Jason Swett

1
사실, 내 의견 이후로 이것은 변경되었으며 should_not지금 사용할 수 있습니다. 죄송합니다!
Marc-André Lafortune 2015

9

사용 :

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

클릭하면 AJAX 게시 요청을 제출하고 JS 응답을 반환해야하는 링크가있는 Rails 애플리케이션이 있습니다.

링크 코드 :

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

JS 응답 (.js.haml 파일)은 링크가있는 페이지에서 다음과 같은 숨겨진 div를 토글해야합니다.

 #notification_status(style='display:none')

js.haml 파일 내용 :

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

내가 통지를 보내와 오이를 사용하여 사용자에게 알림 상태 메시지를 표시 내 시나리오를 테스트했다 ( 카피 바라 지원에 내장 된 보석 오이 레일 )

id : notification_status 가 있는 요소가 단계 정의에서 성공적인 응답에 표시 되는지 테스트하려고했습니다. 이를 위해 다음 문을 시도했습니다.

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)

위의 어느 것도 나를 위해 일하지 않았고 내 단계에 실패했습니다. 위에 나열된 5 개의 스 니펫 중 마지막 4 개가 다음 오류로 실패했습니다.

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

다음 문이 올바르게 전달 되었기 때문에 이상했습니다.

page.has_selector?('#notification_status')

그리고 사실 저는 페이지 소스를

  print page.html

나타난

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

예상했습니다.

마지막으로이 링크 카피 바라는 요소의 속성을 원시 방식으로 검사하는 방법을 보여주는 요소의 속성을 주장합니다 .

또한 Capybara 문서에서 볼 수 있습니까? 메소드 ( http://rubydoc.info/github/jnicklas/capybara/master/Capybara/Node/Element#visible%3F-instance_method ) 다음 정보 :

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

따라서 요소의 가시성을 테스트 할 때 Capybara의 가시성 결과에 의존하지 않는다는 결론에 도달했습니다. CSS 선택기를 사용하고 링크 카피 바라 에서 제안 된 솔루션을 사용할 때 요소의 속성을 주장하는 방법

나는 다음을 생각 해냈다.

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

 World(CustomMatchers)

용법:

should_be_visible('#notification_status')

8

보이는 것은 분명하지 않다

이 오류는 눈에 띄는 것으로 간주되는 것이 명확하지 않고, 드라이버가 휴대 가능하지 않으며, 문서화되지 않은 것으로 간주되는 오해로 인해 발생할 수 있습니다. 일부 테스트 :

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 테스트가 보이지 않는 것으로 간주하는 유일한 것은 인라인입니다 display: none(선택자를 수행하지 않기 때문에 내부 CSS가 아님).

!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는 비슷한 동작을하지만 내부 CSS 및 Js style.display조작을 처리 할 수 ​​있습니다 .

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

셀레늄은 매우 다르게 동작 : 빈 요소가 보이지 판단하는 경우 visibility-hidden뿐만 아니라 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

또 다른 일반적인 캐치는 다음의 기본값입니다 visible.

  • 예전에는 false( 보이는 요소와 보이지 않는 요소 모두 참조)
  • 현재는 true
  • Capybara.ignore_hidden_elements옵션에 의해 제어됩니다 .

참조 .

내 GitHub에서 전체 실행 가능한 테스트 .


1
훌륭한 답변입니다. 노력해 주셔서 감사합니다. 여러 드라이버를 사용하여 제품군에서 요소의 가시성을 테스트하는 것은 간단합니다.
Andy Triggs 2015 년

1
"이전에는 거짓 (보이는 요소와 보이지 않는 요소 모두 표시) 이었지만 현재는 참이며 Capybara.ignore_hidden_elements 옵션에 의해 제어됩니다." 자세한 내용은이 블로그 게시물을 참조하십시오. elabs.se/blog/60-introducing-capybara-2-1
rizidoro 2015

5

모든 ajax 요청이 완료 될 때까지 대기하는 샘플 메소드를 제공하는 이 게시물 을보고 싶을 수 있습니다 .

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

5
로이 솔루션은, 호환 향후없는 wait_until카피 바라 2에서 제거 .
parhamr

1
사용Timeout.timeout
이안 본입

더 나은 사용Selenium::WebDriver::Wait
Nakilon

당신은 셀레늄만을 사용하는 경우
Nickolay Kondratenko

2

허용되는 대답은 'should'가 더 이상 사용되지 않는 구문이므로 약간 구식입니다. 요즘 당신은 라인을 따라 뭔가를하는 것이 더 나을 것입니다expect(page).not_to have_css('#blah', visible: :hidden)


1

여기에있는 다른 답변은 요소를 "대기"하는 가장 좋은 방법입니다. 그러나 나는 이것이 내가 작업중 인 사이트에서 작동하지 않는다는 것을 발견했습니다. 기본적으로 클릭이 필요한 요소는 완전히로드 된 뒤에있는 기능 이전에 표시되었습니다. 이것은 몇 분의 1 초이지만 때때로 내 테스트가 너무 빨리 실행되어 버튼을 클릭했지만 아무 일도 일어나지 않았습니다. 이 임시 부울 표현식을 수행하여 문제를 해결했습니다.

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

기본적으로 카피 바라 기본 대기 시간을 사용하여 표시되어야하는 항목을 찾고, 없으면 클릭을 다시 시도합니다.

다시 한 번 should have_selector방법을 먼저 시도해야 한다고 말하지만 작동하지 않으면 시도해보십시오.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.