카피 바라 모호성 해결
카피 바라의 모호성을 어떻게 해결합니까? 어떤 이유로 페이지에 동일한 값을 가진 링크가 필요하지만 오류가 발생하여 테스트를 만들 수 없습니다.
Failure/Error: click_link("#tag1")
Capybara::Ambiguous:
Ambiguous match, found 2 elements matching link "#tag1"
이것을 피할 수없는 이유는 디자인 때문입니다. 트윗 / 태그가 오른쪽에, 태그가 페이지 왼쪽에있는 트위터 페이지를 다시 만들려고합니다. 따라서 동일한 페이지에 동일한 링크 페이지가 표시되는 것은 불가피합니다.
내 해결책은
first(:link, link).click
대신에
click_link(link)
Capybara의 이러한 행동은 의도적이며 다른 대부분의 답변에서 제안한대로 수정해서는 안된다고 생각합니다.
2.0 이전 버전의 Capybara는 예외를 발생시키는 대신 첫 번째 요소를 반환했지만 나중에 Capybara의 관리자는 이것이 나쁜 생각이며이를 발생시키는 것이 더 낫다고 결정했습니다. 많은 상황에서 첫 번째 요소를 반환하면 개발자가 반환하고자하는 요소가 반환되지 않는 것으로 결정되었습니다.
여기에서 가장 많이 찬성 된 답변은 first
또는 all
대신 사용하는 것이 좋습니다 find
.
all
그리고first
비록 페이지에 표시됩니다 같은 로케이터와 요소까지 기다리지 않는다find
대기 않습니다all(...).first
그리고first
앞으로 이러한 로케이터와 다른 요소가 페이지에 표시 될 수 있다는 상황에서 당신을 보호하지 않으며 결과로 당신은 잘못된 요소를 찾을 수 있습니다
따라서 덜 모호한 다른 로케이터 를 선택하는 것이 좋습니다. 예를 들어 하나의 요소 만 일치하도록 ID, 클래스 또는 기타 css / xpath 로케이터별로 요소를 선택합니다.
모호성을 해결할 때 일반적으로 유용하다고 생각하는 몇 가지 로케이터는 다음과 같습니다.
find('ul > li:first-child')
페이지에
first('ul > li')
처음li
나타날 때까지 기다리는 것보다 더 유용 합니다.click_link('Create Account', match: :first)
first(:link, 'Create Account').click
페이지에 하나 이상의 계정 만들기 링크가 나타날 때까지 기다리는 것보다 낫습니다 . 그러나 페이지에 두 번 나타나지 않는 고유 한 로케이터를 선택하는 것이 좋습니다.fill_in('Password', with: 'secret', exact: true)
exact: true
Capybara에게 정확히 일치하는 항목 만 찾도록 지시합니다. 즉, "암호 확인"을 찾지 못합니다.
위의 솔루션은 훌륭하게 작동하지만 궁금한 사람들을 위해 다음 구문을 사용할 수도 있습니다.
click_link(link_name, match: :first)
여기에서 자세한 정보를 찾을 수 있습니다.
새로운 답변 :
다음과 같은 것을 시도 할 수 있습니다.
all('a').select {|elt| elt.text == "#tag1" }.first.click
사용 가능한 Capybara 구문을 더 잘 사용할 수있는 방법이있을 수 있습니다.-라인을 따라 가지만 all("a[text='#tag1']").first.click
올바른 구문을 직접 생각할 수 없으며 적절한 문서를 찾을 수 없습니다. 즉, 이상한 상황의 약간이 개 필요로 시작하는 말했습니다 <a>
같은과 태그 id
, class
및 텍스트. find
within
DOM의 적절한 세그먼트 를 수행 할 수 있으므로 다른 div의 자식 일 가능성이 있습니까? (HTML 소스를 보면 도움이 될 것입니다).
이전 답변 : (여기서 '# tag1'은 요소 id
에 "tag1" 이 있음을 의미한다고 생각했습니다. )
어떤 링크를 클릭 하시겠습니까? 첫 번째 (또는 중요하지 않음)라면 할 수 있습니다.
find('#tag1').click
그렇지 않으면 할 수 있습니다
all('#tag1')[1].click
두 번째를 클릭합니다.
다음을 사용하여 첫 번째 것을 찾을 수 있습니다 match
.
find('.selector', match: :first).click
그러나 중요한 것은 중복 출력 코드 냄새를 무시하는 깨지기 쉬운 테스트 로 이어지고 실패해야 할 때 계속 작동 하는 오 탐지 로 이어질 것입니다. 일치하는 하나를 제거했기 때문에이 작업 을 수행하고 싶지 않을 것입니다. 요소이지만 테스트는 행복하게 다른 것을 찾았습니다.
더 나은 방법은 다음을 사용하는 것입니다 within
.
within('#sidebar') do
find('.selector).click
end
This ensures that you're finding the element you expect to find, while still leveraging the auto-wait and auto-retry capabilities of Capybara (which you lose if you use find('.selector').click
), and it makes it much clearer what the intent is.
To add to the existing body of knowledge here:
For JS tests, Capybara has to keep two threads (one for RSpec, one for Rails) and a second process (the browser) in sync. It does this by waiting (up to the configured maximum wait time) in most matchers and node-finding methods.
Capybara also has methods that don't wait, primarily Node#all
. Using them is like telling your specs that you'd like them to fail intermittently.
The accepted answer suggests page.first('selector')
. This is undesirable, at least for JS specs, because Node#first
uses Node#all
.
That said, Node#first
will wait if you configure Capybara like so:
# rails_helper.rb
Capybara.wait_on_first_by_default = true
This option was added in Capybara 2.5.0 and is false by default.
As Andrei mentioned, you should instead use
find('selector', match: :first)
or change your selector. Either will work well regardless of config or driver.
To further complicate things, in old versions of Capybara (or with a config option enabled), #find
will happily ignore ambiguity and just return the first matching selector. This isn't great either, as it makes your specs less explicit, which I imagine is why no longer the default behavior. I'll leave out the specifics because they've been discussed above already.
More resources:
- https://robots.thoughtbot.com/write-reliable-asynchronous-integration-tests-with-capybara
- http://makandracards.com/makandra/20829-threads-and-processes-in-a-capybara-selenium-session
Due to this post, you can fix it via "match" option:
Capybara.configure do |config|
config.match = :prefer_exact
end
As considering all the above options, you can try this too
find("a", text: text, match: :prefer_exact).click
If you are using cucumber, you can follow this too
You can pass the text as a parameter from the scenario steps which can be generic step to reuse again
Something like When a user clicks on "text" link
And in step definition When(/^(?:user) clicks on "([^"]*)" (?:link)$/) do |text|
This way, you can reuse the same step by minimizing the lines of code and would be easy to write new cucumber scenarios
To avoid ambiguous error in cucumber.
Solution 1
first("#tag1").click
Solution 2
Cucumber features/filename.feature --guess
참고URL : https://stackoverflow.com/questions/13132506/capybara-ambiguity-resolution
'development' 카테고리의 다른 글
파이썬 파일에서 문자 읽기 (0) | 2020.08.28 |
---|---|
안드로이드는 Uri.getPath ()로 실제 경로를 얻습니다. (0) | 2020.08.27 |
일반 목록 DESC 및 ASC를 어떻게 정렬 할 수 있습니까? (0) | 2020.08.27 |
Angular 2 라우터로 현재 경로를 다시로드하는 방법 (0) | 2020.08.27 |
캐스트 목록 (0) | 2020.08.27 |