Доступ к переменной AngularJS с помощью Java Selenium JavascriptExecutor - PullRequest
0 голосов
/ 20 октября 2018

Вот div с атрибутом AngularJS ng-click, который устанавливает переменную при нажатии на div.

<div id="id"
     ng-click="foo.bar = true;">
     Set bar variable on foo object to true
</div>

Вот некоторый Java-код, который использует Selenium для нажатия на элемент div.

By upload = By.id("id");
driver.findElement(uploadCensus).click();

Когда я запускаю код Java, AngularJS зависает на вечность.Я полагаю, что foo.bar не устанавливается при нажатии на div, поэтому здесь приведен код, который устанавливает переменную напрямую.

By upload = By.id("id");
((JavascriptExecutor) driver)
    .executeScript("foo.bar = true;",   
    driver.findElement(upload));

Stacktrace

неизвестная ошибка: foo не определен (информация о сеансе: chrome = 56.0.2924.87) (информация о драйвере: chromedriver = 2.25.426923 (0390b88869384d6eb0d5d09729679f934aab9eed),= Windows NT 6.1.7601 SP1 x86_64) (ПРЕДУПРЕЖДЕНИЕ: сервер не предоставил никакой информации о трассировке стека) Длительность или тайм-аут команды: 51 миллисекунда Информация о сборке: версия: '2.53.0', версия: '35ae25b', время: '2016-03-15 17:00:58 'Системная информация: хост:' WV-VC104-027 ', ip:' {ip} ', os.name:' Windows 7 ', os.arch:' amd64 ', os.version: '6.1', java.version: '1.8.0_151' Информация о драйвере: org.openqa.selenium.chrome.ChromeDriver Capabilities [{applicationCacheEnabled = false, rotatable = false, mobileEmulationEnabled = false, networkConnectionEnabled = false, chrome = {chromedriverVersion =2.25.426923 (0390b88869384d6eb0d5d09729679f934aab9eed), userDataDir = C: \ Users {user} \ AppData \ Local \ Temp \ scoped_dir5600_4225}, takeHeapSnapshot = true, pageLoadStrategy = нормальный метод, уволенn = false, версия = 56.0.2924.87, платформа = XP, browserConnectionEnabled = false, nativeEvents = true, acceptSslCerts = true, locationContextEnabled = true, webStorageEnabled = true, browserName = chrome, getsScreenshot = true, javascriptEnabled = true, cssSelect] ID сеанса: a7734312eff62fe452a53895b221a58d

Когда я пытаюсь установить foo.bar, я не могу получить ссылку на переменную, потому что она не определена глобально и похоронена где-то внутри исходного кода AngularJS.Я пытался унифицировать индекс и искать переменную, но я не могу найти ее.Я хочу вручную установить переменную foo.bar через JavascriptExecutor, но не могу получить ссылку на переменную.Как бы я нашел затем установить переменную?

Если это кажется неправильным способом вызвать это ng-click, я открыт для идей.Я уверен, что у Protractor есть способ справиться с этим, но это приложение AngularJS развернуто в корпоративной среде и уже несколько месяцев пытается заставить бизнес одобрить технологию.Я застрял с Селеном.Помощь ...

1 Ответ

0 голосов
/ 21 октября 2018

Просто ответьте на ваши вопросы напрямую [Не используйте его для вашего случая :)]

Angular имеет изолированную переменную scope. Так что вам нужно получить область действия и установить переменную в ней.

angular.element("#id").scope().foo.bar = true;

Но не используйте это для своего случая.Поскольку вы тестируете приложение на системном уровне, вы должны тестировать их так же, как это делает пользователь.

Рекомендуемый ответ: дождитесь угловой угловатости в java

Каким бы ни был транспортирможет справиться, ваш тест Java также может сделать.Оба являются обертками над селеновыми связями.В конечном итоге весь код selenese выполняется в том же браузере, который вы тестируете.

waitForAngularMethod - это самый неизбежный метод, который вы пропустили в своем тесте.Хорошо, что вы можете выполнить такой же тип JavaScript с помощью JavaScriptExecutor внутри expilcit wait.

Если вы любитель javascript, вы можете ссылаться на реализацию метода waitForangular в транспортире.Это всего лишь простая проверка правильности и ожидание с использованием обратного вызова.

Ваш Java-код для создания ожидаемого условия для waitforangular

String waitForAngularJs ="Your javascript goes here"; // as it is lengthy read it from file and store here.
ExpectedCondition<Boolean> waitForAngular= new ExpectedCondition<Boolean>() {
            public Boolean apply(WebDriver driver) {
                return ((JavascriptExecutor) driver).executeAsyncScript(waitForAngularJs).equals(true);
            }
};

 WebDriverWait wait = new WebDriverWait(driver, 60);
 wait.until(waitForAngular);

Ожидание углового Javascript (изменено для вашегоВыполнение Java. Но я его не проверял):

Метод требует два атрибута: ловушка корневого локатора и обратный вызовЯ установил функцию обратного вызова в качестве простой функции возврата true и перехватывает с корневым локатором, который [ng-app].

var testCallback = function() {
  return true;
 };

    // Wait for angular1 testability first and run waitForAngular2 as a callback
    var waitForAngular1 = function(callback) {

      if (window.angular) {
        var hooks = window.angular.element('[ng-app]');
        if (!hooks){
          callback();  // not an angular1 app
        }
        else{
          if (hooks.$$testability) {
            hooks.$$testability.whenStable(callback);
          } else if (hooks.$injector) {
            hooks.$injector.get('$browser')
                .notifyWhenNoOutstandingRequests(callback);
          } else if (!rootSelector) {
            throw new Error(
                'Could not automatically find injector on page: "' +
                window.location.toString() + '".  Consider using config.rootEl');
          } else {
            throw new Error(
                'root element (' + rootSelector + ') has no injector.' +
                ' this may mean it is not inside ng-app.');
          }
        }
      }
      else {callback();}  // not an angular1 app
    };

    // Wait for Angular2 testability and then run test callback
    var waitForAngular2 = function() {
      if (window.getAngularTestability) {
        if (rootSelector) {
          var testability = null;
          var el = document.querySelector(rootSelector);
          try{
            testability = window.getAngularTestability(el);
          }
          catch(e){}
          if (testability) {
            testability.whenStable(testCallback);
            return;
          }
        }

        // Didn't specify root element or testability could not be found
        // by rootSelector. This may happen in a hybrid app, which could have
        // more than one root.
        var testabilities = window.getAllAngularTestabilities();
        var count = testabilities.length;

        // No angular2 testability, this happens when
        // going to a hybrid page and going back to a pure angular1 page
        if (count === 0) {
          testCallback();
          return;
        }

        var decrement = function() {
          count--;
          if (count === 0) {
            testCallback();
          }
        };
        testabilities.forEach(function(testability) {
          testability.whenStable(decrement);
        });

      }
      else {testCallback();}  // not an angular2 app
    };

    if (!(window.angular) && !(window.getAngularTestability)) {
      // no testability hook
      throw new Error(
          'both angularJS testability and angular testability are undefined.' +
          '  This could be either ' +
          'because this is a non-angular page or because your test involves ' +
          'client-side navigation, which can interfere with Protractor\'s ' +
          'bootstrapping.  See http://git.io/v4gXM for details');
    } else {waitForAngular1(waitForAngular2);}  // Wait for angular1 and angular2
// Testability hooks sequentially

Почему нам нужно ждать угловых и логических значений

Зачем нам это нужно, потому что angular использует HTML-шаблоны, двухстороннее связывание данных, запросы ajax и маршрутизацию.Поэтому после навигации по страницам мы должны дождаться завершения всей этой операции (запросов и обещаний).В противном случае HTML не будет отвечать, как ожидалось, как в вашем случае.

Проверьте угловую тестабильность

, т. Е. Проверить угловую тестабельность.Для этого самого углового метода есть метод.

Для проверки на основе элемента,

 window.getAngularTestability(el).whenStable(callback); //Here el is element to be valiated.

Для проверки всех признаков,

 window.getAllAngularTestabilities();
   testabilities.forEach(function(testability) {
        testability.whenStable(callback);
});

Подождите, пока всеЗавершенный запрос http для завершения

Прежде чем проверять угловую тестабильность, мы можем убедиться, что нет запроса http в следующих строках.

angular.element(document).injector().get('$http').pendingRequest.length
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...