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

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

本文关键字:水平 位置 元素 垂直 何获得 Capybara RSpec      更新时间:2023-09-26

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

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

所以我想我必须检查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">

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

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

offset()方法允许我们检索元素相对于文档的当前位置。与.position()相比,后者检索相对于偏移父的当前位置

只需注意

虽然可以获得具有可见性的元素的坐标:隐藏集,但display:none从渲染树中排除,因此其位置未定义。

使用capybara的page.evaluate_script可以执行一些JavaScript并根据返回值创建断言:

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

根据这个SO答案,使用JavaScript查找元素位置的最佳方法是使用getBoundingClientRect();,因为它返回相对于视口的值。

我觉得用Capybara而不是JavaScript找到元素更容易阅读,然后找到它的位置。我用的是硒和铬。

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

根据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