【问题标题】:Asserting an element is focused断言元素被聚焦
【发布时间】:2015-02-23 17:12:48
【问题描述】:

根据How do I assert an element is focused? 线程,您可以通过切换到activeElement() 来检查元素是否获得焦点,并断言这是您期望获得焦点的同一元素:

expect(page.element.getAttribute('id')).toEqual(browser.driver.switchTo().activeElement().getAttribute('id'));

在我的例子中,当前聚焦的元素没有id 属性

我应该怎么做而不是检查id

奖励问题:此外,正如您从我尝试解决它的尝试中看到的那样,看起来我不能期望/断言一个元素(或 Web 元素)作为一个完整的对象。为什么?


我试过了:

expect(page.element).toEqual(browser.driver.switchTo().activeElement());

但是由于我什至无法理解的错误而失败 - 有一个巨大的回溯(在控制台中滚动大约需要 10 分钟),但内部没有用户友好的错误。

我也尝试过使用getWebElement()

expect(page.element.getWebElement()).toEqual(browser.driver.switchTo().activeElement());

但这导致了以下错误:

错误:期望使用 WebElement 参数调用,期望一个 Promise。做过 你的意思是使用 .getText()?

使用最新的量角器开发版本。

【问题讨论】:

  • 你的page.element是什么,你在哪里分配的?
  • @BettySt 我不想谈论一个实际的元素,而是将其视为一个抽象,假设没有可依赖的属性..但如果你问它是 <input name="username"> 元素,我可以,严格来说由name 属性标识..但我想避免这种情况..
  • 嗯我真的不明白你为什么不指定元素.. 有某种用户操作比这个元素应该被关注?当您描述一个用例时,也许对我们来说更容易......?
  • @BettySt 我只是在页面完成加载时检查元素是否处于焦点。正如您所建议的,我可以检查其中一个属性或文本,而不是 id,但我想留在元素级别并断言元素或 web 元素 - 这变得非常特定于量角器。希望你明白我的意思。我认为我们已经非常接近用 glepretre 解决它了。感谢您的参与!

标签: javascript angularjs testing protractor end-to-end


【解决方案1】:

在我的回答中,我将假设 activeElempageElem 都是量角器元素查找器,并且指向同一个网络元素。

首先回答你关于为什么的问题

expect(activeElem).toEqual(pageElem);

进入无限循环,这是因为量角器在断言之前修补了茉莉花的expect以解决promise,因此expect(activeElem.getText()).toEqual('text');之类的东西无需做就可以工作

activeElem.getText().then(function(text) {
  expect(text).toEqual('text');
})

你可以说,为什么不只解决一次承诺呢?但是还有嵌套的 Promise。

所以现在您可能会认为这是一个问题,但实际上并不是因为您永远不会在实际用例中比较两个 elementFinder。 Jasmine 的 toEqual 进行参考检查,而不是深度比较,所以expect(activeElem).toEqual(pageElem) 与简单的参考比较相同:(activeElem === pageElem).toToTruthy(),这样做真的没有意义。 (注意element(by.css('html')) === element(by.css('html')) 是错误的,因为它不是同一个引用。)

所以,回答这个线程的真正问题:如何查看两个 elementFinder 是否具有相同的底层 webelements:

expect(activeElem.getId()).toEqual(pageElem.getId());

【讨论】:

  • 正是我想要的。再次感谢您的帮助!
【解决方案2】:

奇怪的是,它只期待一个承诺并且无法处理 webdriver 元素......我和你有同样巨大的堆栈跟踪。

不管怎样,你会接受这种解决方案吗:发送一个“愚蠢的”承诺并附上一个很好的评论来证明你为什么必须这样做。这更像是一种解决方法,而不是我承认的语义解决方案。

expect(page.element.getInnerHtml())
  .toEqual(browser.driver.switchTo().activeElement().getInnerHtml());

它对我有用;)

编辑:奖励答案

您不能使用 WebElement 调用 expect 的原因来自 Webdriver Control Flow Principle(我相信您已经知道)和 this line in jasminewd,这是 Protractor 开发和使用的 jasmine 到 Webdriver 的适配器;)

【讨论】:

  • 是的,这当然是一个有趣的解决方法! (今天没有赞成票 - 明天会做)。感谢您的调查!
  • @alecxe 超过了赞成票,让我知道它是否有效 :) 不客气!
  • @alecxe 谢谢!我今天早上编辑尝试回答你的奖金问题,如果你想看看;)
  • 我认为hankduan完美地描述了这个问题,检查一下。再次感谢您的帮助!
  • @glepretre 我们现在怎么能做到这个量角器removed the getInnerHtml method?
【解决方案3】:

对于未来的读者,我创建了一个 custom matcher 来断言元素是否处于活动/聚焦状态:

beforeEach(function() {
    jasmine.addMatchers({
        toBeActive: function() {
            return {
                compare: function(elm) {
                    return {
                        pass: elm.getId().then(function (activeElementID) {
                            return browser.driver.switchTo().activeElement().getId().then(function (currentElementID) {
                                return jasmine.matchersUtil.equals(currentElementID, activeElementID);
                            });
                        })
                    };
                }
            };
        }
    });
});

用法:

expect(element(by.css("#myid")).toBeActive();

【讨论】:

  • 这不是也假设元素有id吗?
  • @eLRuLL 不,每个元素都有一个内部“id”——它不同于常规的 id 属性。谢谢。
【解决方案4】:

如何使用 CSS 选择器和 :focus

expect(element.all(by.css('#myid:focus')).count()).toBe(1);

【讨论】:

    【解决方案5】:

    我使用量角器解决了这个问题: ElementFinder.prototype.equals

    const activeElement = await browser.driver.switchTo().activeElement();
    const potentialyFocusedElement = await component.$('your-locator');
    const isFocused = await potentialyFocusedElement.equals(activeElement);
    

    我不确定equals 究竟是如何工作的,它是进行深度比较,还是以某种方式比较实例。但它有效。

    请注意,您不能调用 activeElement.equals(...),因为它不是 ElementFinder,而是 WebElement

    【讨论】:

      【解决方案6】:

      您需要想出一种方法来告诉 Protractor/webdriver 如何在页面上找到您的元素。 Protractor 使用 JavaScript 来查找元素,因此可以使用任何可用于检查 DOM 的工具。 Protractor 和 webdriver 将这些 API 包装在各种 by 风格中:

      http://angular.github.io/protractor/#/api?view=ProtractorBy

      除了基本风格之外,Protractor 还添加了 Angular 感知风格(因此您可以通过 Angular 绑定等进行搜索)。

      如果您的元素没有任何显着特征,那么可能值得添加一些内容以使其更易于测试。或者,(尽管这经常因为它太脆弱而不受欢迎),您可以使用 xpath。见https://github.com/angular/protractor/blob/master/docs/locators.md

      【讨论】:

      • 这是一个完全正确的观点。我仍然不确定为什么我不能将一个元素(或 Web 元素)本身断言为一个对象,而是必须检查它的一个属性。我将开放赏金并将这个问题保持一段时间。谢谢!
      • 啊,我想我看错了你的问题。你能包括“page.element”的定义吗?我认为这会让事情变得更清楚。
      • 抱歉不清楚。我想将page.element 视为一个抽象元素,就主题而言,它不能用属性可靠且唯一地标识。不管怎样,page.element 指的是一个输入元素:<input name="username">。在实践中,是的,我可以通过名称来识别它,但现在我更关注为什么我们需要深入到元素属性而不是仅仅检查一个活动元素是否是我们已经找到的那个 - 留在元素的级别。希望你明白我的意思。无论如何,你的观点仍然有效,我希望它在这里。谢谢!
      【解决方案7】:

      您可以简单地检查元素的文本(或其他任何内容):

      var currentElement = browser.switchTo().activeElement();
      expect(currentElement.getText()).toEqual(page.element.getText());
      

      【讨论】:

      • 这接近于@P.T.建议,这一点是完全有效的。现在我更专注于额外的问题 - 换句话说 - 为什么我不能检查完整的元素并且必须深入到属性或文本。感谢您的参与!
      猜你喜欢
      • 2016-07-19
      • 1970-01-01
      • 1970-01-01
      • 2014-04-09
      • 2023-04-02
      • 2015-04-30
      • 2012-02-27
      • 2017-01-03
      • 1970-01-01
      相关资源
      最近更新 更多