Задать вопрос
@valentine11

Node.js — имортируемая функция не видит переменные в текущей области видимости, решение?

Добрый день. Я тестировщик, осваиваю автоматизацию.
В js и nodejs новичок.
Есть файл с блоками тестов. Пытаюсь вынести постоянно повторяющиеся действия за пределы исходного файла дабы уменьшить количество кода. Но что-то идет не так.
Вынесенные действия:
exports.loadRegistrationForm = function() {
    driver.get('http:...');
    driver.getTitle().then(function(title){
	    if("..."===title){
		    driver.findElement(webdriver.By.xpath('html/body/div/header/div/div/div[2]/div[2]/a[1]'))
			      .click();
	    };
    });
	driver.wait(function(){
		return driver.isElementPresent(webdriver.By.name('fos_user_registration_form[email]'));
	}, 3000, 'Failed to load Registration form');    	
};

// заполнение формы регистрации и проверка соответствия
exports.fillingRegistrationForm = function(inputEmail, inputPassword, errElement, errMessage){ 
	driver.findElement(webdriver.By.name('fos_user_registration_form[email]'))
		  .sendKeys(inputEmail); //вводим уже зарегистрированный email
	driver.findElement(webdriver.By.name('fos_user_registration_form[plainPassword]'))
		  .sendKeys(inputPassword); //вводим валидный пароль
	driver.findElement(webdriver.By.id('btn-submit')).click();//сабмит

	driver.wait(function(){
		return driver.isElementPresent(webdriver.By.xpath(errElement));
	}, 3000, 'Элемент не найден'); //ожидание загрузки текста ошибки

	var flow = webdriver.promise.controlFlow();
	function getErrObject(){
		errObject = driver.findElement(webdriver.By.xpath(errElement))
						.getText()
	} //берем объект элемента с текстом ошибки
	flow.execute(getErrObject).then(function(){
		if(errObject.value_ === errMessage){
			assert.equal(errObject.value_, errMessage);
			console.log('OK')
		};
	});
};

Попытка переписать исходный файл с подгрузкой функций:
var assert = require("assert")
var webdriver = require('selenium-webdriver');
var driver = new webdriver.Builder().
			withCapabilities(webdriver.Capabilities.chrome()).
			build();
var loadRegistrationForm = require('./reusable_function').loadRegistrationForm;
var fillingRegistrationForm = require('./reusable_function').fillingRegistrationForm;

describe('Проверка поля Email формы регистрации.', function(){
	it('Ввод уже зарегистрированного Email', function(done){
	    var inputEmail = '123@ya.ru';
		var inputPassword = '12345678Aa';
		var errElement = "//*[@class='form-errors server-error']";
		var errMessage = 'Email уже используется';
        loadRegistrationForm();	//загружаем форму регистрации
		fillingRegistrationForm(inputEmail, inputPassword, errElement, errMessage);
		return done();
	});
});

При запуске теста, в консоль выдается:
C:\Program Files\nodejs\test\reusable_function.js:9
    driver.get('http://...');
    ^

ReferenceError: driver is not defined
    at Object.exports.loadRegistrationForm (C:\Program Files\nodejs\test\reusabl
e_function.js:9:5)
    at Object.<anonymous> (C:\Program Files\nodejs\test\test2_mocha.js:7:32)
    at Module._compile (module.js:435:26)
    at Object.Module._extensions..js (module.js:442:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:311:12)
    at Module.require (module.js:366:17)
    at require (module.js:385:17)
    at C:\Users\Valentine11\AppData\Roaming\npm\node_modules\mocha\lib\mocha.js:
216:27
    at Array.forEach (native)
    at Mocha.loadFiles (C:\Users\Valentine11\AppData\Roaming\npm\node_modules\mo
cha\lib\mocha.js:213:14)
    at Mocha.run (C:\Users\Valentine11\AppData\Roaming\npm\node_modules\mocha\li
b\mocha.js:453:10)
    at Object.<anonymous> (C:\Users\Valentine11\AppData\Roaming\npm\node_modules
\mocha\bin\_mocha:393:18)
    at Module._compile (module.js:435:26)
    at Object.Module._extensions..js (module.js:442:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:311:12)
    at Function.Module.runMain (module.js:467:10)
    at startup (node.js:136:18)
    at node.js:963:3


Т.е. не находит переменную driver.
Вопрос: почему? Может быть, я как-то не так подгружаю функции?
Решение из поста: Node.js. Подгрузка файла в текущее окружение не работает.
Если убрать ; в строчках 6 и 7, то ту же самую ошибку выдает уже сам mocha:
Проверка поля Email формы регистрации.
    1) Ввод уже зарегистрированного Email


  0 passing (41ms)
  1 failing

  1) Проверка поля Email формы регистрации. Ввод уже зарегистрированного Email:
     ReferenceError: driver is not defined
      at exports.loadRegistrationForm (C:\Program Files\nodejs\test\reusable_fun
ction.js:9:5)
      at Context.<anonymous> (C:\Program Files\nodejs\test\test2_mocha.js:15:9)
      at callFnAsync (C:\Users\Valentine11\AppData\Roaming\npm\node_modules\moch
a\lib\runnable.js:306:8)
      at Test.Runnable.run (C:\Users\Valentine11\AppData\Roaming\npm\node_module
s\mocha\lib\runnable.js:261:7)
      at Runner.runTest (C:\Users\Valentine11\AppData\Roaming\npm\node_modules\m
ocha\lib\runner.js:421:10)
      at C:\Users\Valentine11\AppData\Roaming\npm\node_modules\mocha\lib\runner.
js:528:12
      at next (C:\Users\Valentine11\AppData\Roaming\npm\node_modules\mocha\lib\r
unner.js:341:14)
      at C:\Users\Valentine11\AppData\Roaming\npm\node_modules\mocha\lib\runner.
js:351:7
      at next (C:\Users\Valentine11\AppData\Roaming\npm\node_modules\mocha\lib\r
unner.js:283:14)
      at Immediate._onImmediate (C:\Users\Valentine11\AppData\Roaming\npm\node_m
odules\mocha\lib\runner.js:319:5)


Не пишу пока первоначальный код, т.к. считаю, что он тут в принципе не нужен, и не хочется превращать вопрос в простыню..., но если надо - добавлю. Заранее спасибо за ответы.
---
UPD. Ошибку с драйвером убрала пока, указав driver в файле с вынесенными функциями. Мне не нравится это решение но пусть пока так.
Сейчас код выглядит следующим образом:
var assert = require("assert")
var webdriver = require('selenium-webdriver');
var driver = new webdriver.Builder().
			withCapabilities(webdriver.Capabilities.chrome()).
			build();
var flow = webdriver.promise.controlFlow();
			

loadRegistrationForm = require('./reusable_function').loadRegistrationForm
fillingRegistrationForm = require('./reusable_function').fillingRegistrationForm


describe('Проверка поля Email формы регистрации.', function(){
	it('Ввод уже зарегистрированного Email', function(done){
	    var inputEmail = '123@ya.ru';
		var inputPassword = '12345678Aa';
		var errElement = "//*[@class='form-errors server-error']";
		var errMessage = 'Email уже используется';
        loadRegistrationForm();
		fillingRegistrationForm(inputEmail, inputPassword, errElement, errMessage);
		flow.execute(function(){
		    return done();	
		});
	});
});

Код работает, тест выполняется. НО! скрипт открывает два окна браузера, т.к. при импорте инициализируется драйвер, это напрягает. Если убрать инициализацию драйвера, в файле с тестами опять выдается driver is not defined. Т.е. по сути, проблема, вынесенная в заголовок, осталась.
Также непонятно, почему код работоспособен, только если импортировать как Function Declaration:
loadRegistrationForm = require('./reusable_function').loadRegistrationForm
fillingRegistrationForm = require('./reusable_function').fillingRegistrationForm?
Во всех примерах используется импорт через var.
Почему код неработоспособен, если в импортируемых функциях ставить module.export, а не просто export, тоже неясно.
  • Вопрос задан
  • 1817 просмотров
Подписаться 2 Оценить Комментировать
Пригласить эксперта
Ответы на вопрос 4
P.S. Не сразу понял, в чем именно ошибка. Моё предложение сделать вот так вот:
В вспомогательном модуле:
function testsHelper(driver) {
	var _driver = driver;
	function loadRegistrationForm() {
		_driver.get('http:...');
	    _driver.getTitle().then(function(title){
	      if("..."===title){
	        _driver.findElement(web_driver.By.xpath('html/body/div/header/div/div/div[2]/div[2]/a[1]'))
	            .click();
	      };
	    });
	  _driver.wait(function(){
	    return _driver.isElementPresent(web_driver.By.name('fos_user_registration_form[email]'));
	  }, 3000, 'Failed to load Registration form'); 
	}
	
	// заполнение формы регистрации и проверка соответствия
	function fillingRegistrationForm(inputEmail, inputPassword, errElement, errMessage) { 
	  _driver.findElement(web_driver.By.name('fos_user_registration_form[email]'))
	      .sendKeys(inputEmail); //вводим уже зарегистрированный email
	  _driver.findElement(web_driver.By.name('fos_user_registration_form[plainPassword]'))
	      .sendKeys(inputPassword); //вводим валидный пароль
	  _driver.findElement(web_driver.By.id('btn-submit')).click();//сабмит

	  _driver.wait(function(){
	    return _driver.isElementPresent(web_driver.By.xpath(errElement));
	  }, 3000, 'Элемент не найден'); //ожидание загрузки текста ошибки

	  var flow = web_driver.promise.controlFlow();
	  function getErrObject(){
	    errObject = _driver.findElement(web_driver.By.xpath(errElement))
	            .getText()
	  } //берем объект элемента с текстом ошибки
	  flow.execute(getErrObject).then(function(){
	    if(errObject.value_ === errMessage){
	      assert.equal(errObject.value_, errMessage);
	      console.log('OK')
	    };
	  });
	}
	return {
		fillingRegistrationForm: fillingRegistrationForm,
		loadRegistrationForm: loadRegistrationForm
	}
}
module.exports = testsHelper;


В непосредственно тестах:
var Helper = require(testsHelper.js);

// инициализируем driver
var driver = ...
var helper = new Helper(driver);
Ответ написан
edli007
@edli007
full stack, team lead
Передавайте нужные переменные в функцию, а вобще фигней какой занимаетесь, выносите посторяющиеся блоки там, где есть эти переменные.
Ответ написан
atlantech
@atlantech
Full Stack Software Developer
Инициализируйте переменную
var driver = new webdriver.Builder().
      withCapabilities(webdriver.Capabilities.chrome()).
      build();

в начале того файла, куда вы вынесли функцию loadRegistrationForm. Тогда переменная driver станет глобальной по отношению к loadRegistrationForm. Должно сработать
Ответ написан
@timfcsm
вынесите driver в отдельный модуль и импортируйте там, где надо
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы