简体   繁体   English

使用Protractor定位元素指令中的元素

[英]Targeting elements within an element directive with Protractor

Consider the following view model: 考虑以下视图模型:

$scope.data = {};
$scope.data.person = {};
$scope.data.person.firstname = "";
$scope.data.person.lastname = "";
$scope.data.person.username = "";

and the following element directive: 以及以下元素指令:

<custom-form-directive ng-model="data.person"></custom-form-directive>

which contains three input tags to display the data. 其中包含三个输入标签来显示数据。 How do I use protractor to populate the input fields by targeting ng-model="data.person" ? 如何通过定位ng-model="data.person"来使用量角器填充输入字段?

It depends on how you're getting data in/out of the inputs in the directive. 这取决于您如何在指令中输入/输出数据。 However, in all cases you can chain together element(<locator>) calls to search for sub-elements of the directive: 但是,在所有情况下,您可以将element(<locator>)调用链接在一起以搜索指令的子元素

var directive = element(by.model('data.person'));
var subElement = directive.element(by.<something>);

If you're using ng-model in the directive itself on each of the inputs, you can do something like: 如果您在每个输入的指令中使用ng-model ,您可以执行以下操作:

var directive = element(by.model('data.person'));

// Assuming the inputs have attributes like `ng-model="firstname"` in the directive template
var firstnameInput = directive.element(by.model('firstname'));
var lastnameInput = directive.element(by.model('lastname'));
var usernameInput = directive.element(by.model('surnamname'));

and then on each call sendKeys 然后在每次调用sendKeys

firstnameInput.sendKeys('Peter');
secondnameInput.sendKeys('Piper');
usernameInput.sendKeys('PickledPumpernickle');

If you're not using ng-model in the directive template, you can use other locators to find the sub elements, together with get if needs be, and depend on the order they're in the DOM 如果你没有在指令模板中使用ng-model ,你可以使用其他定位器来查找子元素,如果需要则可以使用get ,并且取决于它们在DOM中的顺序

var inputs = directive.element(by.css('input'));
var firstnameInput = inputs.get(0);
var secondnameInput = inputs.get(1);
var usernameInput = inputs.get(2);

However, I suspect none of the above will work if you have replace: true specified in the directive, as it depends on the original element, with the ng-model attribute, being in the DOM. 但是,我怀疑如果您在指令中指定了replace: true ,则上述任何一个都不会起作用,因为它依赖于原始元素,其中ng-model属性位于DOM中。

This is exactly what the evaluate method is for: http://angular.github.io/protractor/#/api?view=ElementFinder.prototype.evaluate 这正是evaluate方法的用途: http//angular.github.io/protractor/#/api?view = ElementFinder.prototype.evaluate

element(by.model('data.person')).evaluate('data.person.firstname = "yourvaluehere"');

I assume by "targeting the model" you want to change the controller's value and have the ng-model directive update the view, rather than the other way around. 我假设通过“瞄准模型”你想要改变控制器的值并让ng-model指令更新视图,而不是相反。

I think you want to build something like a "pageObject" (see https://github.com/angular/protractor/blob/master/docs/page-objects.md ) for your custom-form-directive directive. 我想你想为你的custom-form-directive指令构建类似“pageObject”的东西(参见https://github.com/angular/protractor/blob/master/docs/page-objects.md )。 This object will understand how the directive maps to primitives that Protractor will understand (eg, specific input fields). 该对象将理解指令如何映射到Protractor将理解的基元(例如,特定输入字段)。 It should take a locator so its callers can pass in the how to find the directive on the page, but the object should handle everything after that. 它应该采用一个定位器,以便其调用者可以传递如何在页面上查找指令,但该对象应该在此之后处理所有内容。

var object = new customFormDirectiveObject(by.model('data.person'));

depending on how your directive works you'd do something like: 根据您的指令的工作原理,您可以执行以下操作:

object.setName(first, last, user);

or if its more dyanmic maybe something like this: 或者如果它更像一个dyanmic可能是这样的:

object.setName({firstname: first, lastname: last, username: user });

With a few helper function you could do it rather easily. 有了一些辅助功能,你可以很容易地做到这一点。 The helper object just wraps protractor and makes it a little more sane and safe to use. 辅助对象只需包裹量角器,使其更加安全可靠。 Especially when running on remote systems. 特别是在远程系统上运行时。

var helper = {
  getElement: function (selector) {
    return element(by.css(selector));
  },

  resolveSelector: function (selector) {
    var el;
    if (typeof selector === 'string') {
      el = self.getElement(selector);
    } else {
      el = selector;
    }
    return el;
  },

  waitForElementClickable: function (selector) {
    var el = self.resolveSelector(selector);
    var condition = function () {
      return self.waitForElement(el).then(function () {
        return self.isElementEnabled(el);
      });
    };
    return self.wait(condition, 15000, 'Element not clickable. (' + selector + ')');
  },

  setElementValue: function (selector, value) {
    var el = self.resolveSelector(selector);
    return self.waitForElementClickable(el).then(function () {
      el.click().clear().sendKeys(value);
    });
  },

  getElementValue: function (selector) {
    var el = self.resolveSelector(selector);
    return el ? el.getAttribute('value') : '';
  }

}

Then you can just use regular CSS selectors to set your values: 然后你可以使用常规的CSS选择器来设置你的值:

helper.setElementValue('[ng-model="data.person"] input:nth-child(1)', '1st Input Value');
helper.setElementValue('[ng-model="data.person"] input:nth-child(2)', '2nd Input Value');
helper.setElementValue('[ng-model="data.person"] input:nth-child(3)', '3rd Input Value');

And you can check for expected values with something like this: 您可以使用以下内容检查预期值:

expect(helper.getElementValue('[ng-model="data.person"] input:nth-child(1)')).toEqual('something')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM