使用Angular-UI Select2元素进行Angularjs E2E测试

时间:2021-01-02 01:20:19

I have a partial with a select2 element utilizing Angular UI http://angular-ui.github.io/

我有一个使用Angular UI的select2元素的部分http://angular-ui.github.io/

The issue I am running into is that the element is required and although i have successfully set the field through the following code, the required attribute is not removed as Angular's model must not be updating due to the outside change and I am not sure how to either provide a $scope.apply() or utilize another function of Angular to continue the test.

我遇到的问题是该元素是必需的,虽然我已成功通过以下代码设置字段,但由于外部更改而不确定Angular的模型不能更新,因此不会删除所需的属性,我不知道如何要么提供$ scope.apply(),要么使用Angular的另一个函数来继续测试。

First to allow for direct jQuery functions to run: (taken from How to execute jQuery from Angular e2e test scope?)

首先允许运行直接jQuery函数:(取自如何从Angular e2e测试范围执行jQuery?)

angular.scenario.dsl('jQueryFunction', function() {
return function(selector, functionName /*, args */) {
    var args = Array.prototype.slice.call(arguments, 2);
    return this.addFutureAction(functionName, function($window, $document, done) {
        var $ = $window.$; // jQuery inside the iframe
        var elem = $(selector);
        if (!elem.length) {
            return done('Selector ' + selector + ' did not match any elements.');
        }
        done(null, elem[functionName].apply(elem, args));
    });
};
});

Then to change the field value:

然后更改字段值:

jQueryFunction('#s2id_autogen1', 'select2', 'open');
    jQueryFunction('#s2id_autogen1', 'select2', "val", "US");
    jQueryFunction('#s2id_autogen1', 'select2', 'data', {id: "US", text: "United States"});
    jQueryFunction('.select2-results li:eq(3)', 'click');
    jQueryFunction('#s2id_autogen1', 'trigger', 'change');
    jQueryFunction('#s2id_autogen1', 'select2', 'close');
    input('request._countrySelection').enter('US');

Note that not all of those functions are needed to reflect the changes to the ui, merely all that I have utilized to try and get this working...

请注意,并不是所有这些函数都需要反映ui的变化,而只是我用来尝试使其工作的所有功能......

5 个解决方案

#1


5  

To get this to work I consulted both Brian's answer and sinelaw, but it still failed in my case for two reasons:

为了实现这个目的,我咨询了布莱恩的答案和正弦律,但在我的案例中仍然失败了两个原因:

  1. clicking on 'div#s2id_autogen1' does not open the select2 input for me, the selector I used was 'div#s2id_autogen1 a'
  2. 点击'div#s2id_autogen1'不会为我打开select2输入,我使用的选择器是'div#s2id_autogen1 a'

  3. getting the select2 element I would get the ElementNotVisibleError, probably because my select2 is inside a bootstrap modal, so I explicitly wait for the element to be visible before clicking it (you can read the original hint I read to use this here).
  4. 得到select2元素我会得到ElementNotVisibleError,可能是因为我的select2在一个bootstrap模式中,所以我明确地等待元素在点击它之前可见(你可以阅读我读过的原始提示在这里使用它)。

The resulting code is:

结果代码是:

function select2ClickFirstItem(select2Id) {
        var select2Input;

        // Wait for select2 element to be visible
        browser.driver.wait(function() {
            select2Input =  element(by.css('#s2id_' + select2Id + ' a'));
            return select2Input;
        }).then(function() {
            select2Input.click();

            var items = element.all(by.css('.select2-results-dept-0'));
            browser.driver.wait(function () {
                return items.count().then(function (count) {
                    return 0 < count;
                });
            });
            items.get(0).click();
        });
    }

Hope it helps.

希望能帮助到你。

#2


2  

I was unable to get this to work within the Karma test runner, however this became significantly easier within the protractor test suite.

我无法在Karma测试运行器中使用它,但是在量角器测试套件中这变得非常容易。

To accomplish this within the protractor test suite I used the following to select the first select2 box on the page and select the first option within that box:

为了在量角器测试套件中实现这一点,我使用以下内容选择页面上的第一个select2框并选择该框中的第一个选项:

var select2 = element(by.css('div#s2id_autogen1'));
select2.click();
var lis = element.all(by.css('li.select2-results-dept-0'));
lis.then(function(li) {
    li[0].click();
});

The next select2 on the page has an id of s2id_autogen3

页面上的下一个select2的id为s2id_autogen3

#3


2  

I'll second what @Brian said if you use protractor and the new karma this has worked for me:

如果你使用量角器以及这对我有用的新业力,我会说@Brian说的话:

function uiSelect(model, hasText) {
    var selector = element(by.model('query.cohort')),
        toggle = selector.element(by.css('.ui-select-toggle'));

    toggle.click();

    browser.driver.wait(function(){
        return selector.all(by.css('.ui-select-choices-row')).count().then(function(count){
            return count > 0;
        });
    }, 2000);

    var choice = selector.element(by.cssContainingText('.ui-select-choices-row',hasText));
    choice.click();
};

use it like:

使用它像:

if the value of the item you want to select is "Q3 2013" you can provide it the model of the selector and an exact or partial text match of the item you want to select.

如果您要选择的项目的值为“Q3 2013”​​,则可以为其提供选择器的模型以及要选择的项目的精确或部分文本匹配。

uiSelect('query.cohort','Q3 2013');

or

uiSelect('query.cohort','Q3');

will both work

都会奏效

#4


0  

I made it work under Karma with following changes.

我通过以下更改在Karma下工作。

Add following DSL to the top of your e2e test file:

将以下DSL添加到e2e测试文件的顶部:

angular.scenario.dsl('jQueryFunction', function() {
  return function(selector, functionName /*, args */) {
    var args = Array.prototype.slice.call(arguments, 2);
    return this.addFutureAction(functionName, function($window, $document, done) {
      var $ = $window.$; // jQuery inside the iframe
      var elem = $(selector);
      if (!elem.length) {
        return done('Selector ' + selector + ' did not match any elements.');
      }
      done(null, elem[functionName].apply(elem, args));
    });
  };
});

Then to change select2 value in your scenario use

然后在场景使用中更改select2值

it('should narrow down organizations by likeness of name entered', function() {
  jQueryFunction('#s2id_physicianOrganization', 'select2', 'open');
  jQueryFunction('#s2id_physicianOrganization', 'select2', 'search', 'usa');
  expect(element('div.select2-result-label').count()).toBe(2);
});

#5


0  

Sometimes the select2 may take time to load, especially when working with ajax-loaded data. So when using protractor, and expanding on Brian's answer, here's a method I've found to be reliable:

有时候select2可能需要一些时间来加载,特别是在使用加载了jax的数据时。因此,当使用量角器并扩展Brian的答案时,我发现这是一种可靠的方法:

function select2ClickFirstItem(select2Id) {
    var select2 = element(by.css('div#s2id_' + select2Id));
    select2.click();
    var items = element.all(by.css('.select2-results-dept-0'));
    browser.driver.wait(function () {
        return items.count().then(function (count) {
            return 0 < count;
        })
    });
    items.get(0).click();
}

This uses the fact that driver.wait can take a promise as a result.

这使用了driver.wait可以作为结果的事实。

#1


5  

To get this to work I consulted both Brian's answer and sinelaw, but it still failed in my case for two reasons:

为了实现这个目的,我咨询了布莱恩的答案和正弦律,但在我的案例中仍然失败了两个原因:

  1. clicking on 'div#s2id_autogen1' does not open the select2 input for me, the selector I used was 'div#s2id_autogen1 a'
  2. 点击'div#s2id_autogen1'不会为我打开select2输入,我使用的选择器是'div#s2id_autogen1 a'

  3. getting the select2 element I would get the ElementNotVisibleError, probably because my select2 is inside a bootstrap modal, so I explicitly wait for the element to be visible before clicking it (you can read the original hint I read to use this here).
  4. 得到select2元素我会得到ElementNotVisibleError,可能是因为我的select2在一个bootstrap模式中,所以我明确地等待元素在点击它之前可见(你可以阅读我读过的原始提示在这里使用它)。

The resulting code is:

结果代码是:

function select2ClickFirstItem(select2Id) {
        var select2Input;

        // Wait for select2 element to be visible
        browser.driver.wait(function() {
            select2Input =  element(by.css('#s2id_' + select2Id + ' a'));
            return select2Input;
        }).then(function() {
            select2Input.click();

            var items = element.all(by.css('.select2-results-dept-0'));
            browser.driver.wait(function () {
                return items.count().then(function (count) {
                    return 0 < count;
                });
            });
            items.get(0).click();
        });
    }

Hope it helps.

希望能帮助到你。

#2


2  

I was unable to get this to work within the Karma test runner, however this became significantly easier within the protractor test suite.

我无法在Karma测试运行器中使用它,但是在量角器测试套件中这变得非常容易。

To accomplish this within the protractor test suite I used the following to select the first select2 box on the page and select the first option within that box:

为了在量角器测试套件中实现这一点,我使用以下内容选择页面上的第一个select2框并选择该框中的第一个选项:

var select2 = element(by.css('div#s2id_autogen1'));
select2.click();
var lis = element.all(by.css('li.select2-results-dept-0'));
lis.then(function(li) {
    li[0].click();
});

The next select2 on the page has an id of s2id_autogen3

页面上的下一个select2的id为s2id_autogen3

#3


2  

I'll second what @Brian said if you use protractor and the new karma this has worked for me:

如果你使用量角器以及这对我有用的新业力,我会说@Brian说的话:

function uiSelect(model, hasText) {
    var selector = element(by.model('query.cohort')),
        toggle = selector.element(by.css('.ui-select-toggle'));

    toggle.click();

    browser.driver.wait(function(){
        return selector.all(by.css('.ui-select-choices-row')).count().then(function(count){
            return count > 0;
        });
    }, 2000);

    var choice = selector.element(by.cssContainingText('.ui-select-choices-row',hasText));
    choice.click();
};

use it like:

使用它像:

if the value of the item you want to select is "Q3 2013" you can provide it the model of the selector and an exact or partial text match of the item you want to select.

如果您要选择的项目的值为“Q3 2013”​​,则可以为其提供选择器的模型以及要选择的项目的精确或部分文本匹配。

uiSelect('query.cohort','Q3 2013');

or

uiSelect('query.cohort','Q3');

will both work

都会奏效

#4


0  

I made it work under Karma with following changes.

我通过以下更改在Karma下工作。

Add following DSL to the top of your e2e test file:

将以下DSL添加到e2e测试文件的顶部:

angular.scenario.dsl('jQueryFunction', function() {
  return function(selector, functionName /*, args */) {
    var args = Array.prototype.slice.call(arguments, 2);
    return this.addFutureAction(functionName, function($window, $document, done) {
      var $ = $window.$; // jQuery inside the iframe
      var elem = $(selector);
      if (!elem.length) {
        return done('Selector ' + selector + ' did not match any elements.');
      }
      done(null, elem[functionName].apply(elem, args));
    });
  };
});

Then to change select2 value in your scenario use

然后在场景使用中更改select2值

it('should narrow down organizations by likeness of name entered', function() {
  jQueryFunction('#s2id_physicianOrganization', 'select2', 'open');
  jQueryFunction('#s2id_physicianOrganization', 'select2', 'search', 'usa');
  expect(element('div.select2-result-label').count()).toBe(2);
});

#5


0  

Sometimes the select2 may take time to load, especially when working with ajax-loaded data. So when using protractor, and expanding on Brian's answer, here's a method I've found to be reliable:

有时候select2可能需要一些时间来加载,特别是在使用加载了jax的数据时。因此,当使用量角器并扩展Brian的答案时,我发现这是一种可靠的方法:

function select2ClickFirstItem(select2Id) {
    var select2 = element(by.css('div#s2id_' + select2Id));
    select2.click();
    var items = element.all(by.css('.select2-results-dept-0'));
    browser.driver.wait(function () {
        return items.count().then(function (count) {
            return 0 < count;
        })
    });
    items.get(0).click();
}

This uses the fact that driver.wait can take a promise as a result.

这使用了driver.wait可以作为结果的事实。