RSpec and Capybara: 如何获取元素的水平和垂直位置

RSpec and Capybara: How to get the horizontal and vertical position of an element

我在我的网站上添加了视觉上隐藏的跳转链接,当它们被聚焦时就会出现(类似于 GitHub,只需在主页上按一次 Tab)。

我想用水豚测试这种行为。我无法检查例如'visibility: true/false',因为链接并没有真正隐藏(否则屏幕阅读器将看不到它们),而只是通过绝对定位从视口中移出。当它们聚焦时,它们将放置在视口中的原始位置。

所以我想我必须检查 X 和 Y 坐标,但 Capybara 似乎没有提供获取它们的本机方法?这是真的?如果是这样,我将如何获得它们,例如一个元素'#jump_to_content'?通过执行一些 JavaScript?

更新

我在这里找到了一些灵​​感:https://content.pivotal.io/blog/testing-accessibility-with-rspec-and-capybara

但这似乎不适用于我的配置:

link.native.location
NoMethodError: undefined method `location' for #<Capybara::Poltergeist::Node tag="a">

使用水豚的 page.evaluate_script 将允许您执行一些 JavaScript 并根据 return 值创建断言:

expect(page.evaluate_script("document.querySelectorAll('a#jump-to-content')[0].style.top;")).to eq('-8000px')

根据 Nuri 的回答,最好的方法是直接询问浏览器(无头浏览器不会读取 css 文件,afaik)。

但是,与其询问元素的样式,不如使用 offsetTop 直接检查其位置。所以像

expect(page.evaluate_script("document.querySelector('a#jump-to-content').offsetTop;")).to eq('-8000px')

如果您需要更多控制,您也可以 运行 在 javascript:

expect(page.evaluate_script("document.querySelector('a#jump-to-content').offsetTop < document.querySelector('body').offsetTop;").to be_true

你是对的,Capybara 没有提供获取页面中元素位置的本机方法,但如果你可以访问 jQuery,你可以使用 Capybara's page.evaluate_script 方法轻松确定元素的位置。它看起来像这样:

page.evaluate_script("$('.menu > div:nth-child(1)').offset().top")

The .offset() method allows us to retrieve the current position of an element relative to the document. Contrast this with .position(), which retrieves the current position relative to the offset parent

请注意

While it is possible to get the coordinates of elements with visibility:hidden set, display:none is excluded from the rendering tree and thus has a position that is undefined.

根据 this SO answer,使用 JavaScript 查找元素位置的最佳方法是使用 getBoundingClientRect(); 因为它的 returns 值是相对于视口。

我觉得用 Capybara 而不是 JavaScript 找到元素更具可读性,然后 找到它的位置。我正在使用硒和 Chrome.

link = find("a", text: "content")

link.evaluate_script("this.getBoundingClientRect().left;")
link.evaluate_script("this.getBoundingClientRect().right;")
link.evaluate_script("this.getBoundingClientRect().top;")
link.evaluate_script("this.getBoundingClientRect().bottom;")

一些浏览器(如 Chrome)也有:

link.evaluate_script("this.getBoundingClientRect().x;")
link.evaluate_script("this.getBoundingClientRect().y;")
link.evaluate_script("this.getBoundingClientRect().height;")
link.evaluate_script("this.getBoundingClientRect().width;")

你也可以

link.rect.y
link.rect.height
link.rect.x
link.rect.width