Nous avons un ensemble assez important de tests de bout en bout sur Protractor. Nous suivons le modèle d'objet de page qui nous aide à garder nos tests propres et modulaires. Nous avons également un ensemble de fonctions d'aide qui nous aident à suivre le principe DRY .
Le problème:
Une seule spécification peut nécessiter plusieurs objets de page et modules d'assistance. Par exemple:
"use strict";
var helpers = require("./../../helpers/helpers.js");
var localStoragePage = require("./../../helpers/localStorage.js");
var sessionStoragePage = require("./../../helpers/sessionStorage.js");
var loginPage = require("./../../po/login.po.js");
var headerPage = require("./../../po/header.po.js");
var queuePage = require("./../../po/queue.po.js");
describe("Login functionality", function () {
beforeEach(function () {
browser.get("/#login");
localStoragePage.clear();
});
// ...
});
Vous pouvez voir que nous avons cette traversée de répertoire dans chaque instruction require: ./../..
. En effet, nous avons un répertoire specs
dans lequel nous conservons les spécifications et plusieurs répertoires à l'intérieur regroupés par fonctionnalité d'application sous test.
La question:
Quelle est la manière canonique d'aborder le problème de chemin relatif dans Protractor?
En d'autres termes, nous aimerions éviter de traverser l'arborescence, de monter pour importer des modules. Il serait beaucoup plus propre de descendre du répertoire de l'application de base à la place.
Tentatives et réflexions:
Il existe un excellent article sur la façon d'aborder ce problème: Meilleurs chemins locaux require () pour Node.js , mais je ne sais pas laquelle des options est recommandée lors du développement de tests avec Protractor.
Nous avons également essayé d'utiliser require.main
pour construire le chemin, mais il pointe vers le node_modules/protractor
répertoire au lieu de notre répertoire d'application.
J'ai eu le même problème et je me suis retrouvé avec la solution suivante. Dans mon fichier de configuration du rapporteur j'ai une variable qui stocke un chemin vers un dossier de base de mes tests e2e. De plus, la configuration Protractor fournit le rappel onPrepare
, où vous pouvez utiliser une variable appelée global
pour créer des variables globales pour vos tests. Vous les définissez en tant que propriétés de cette variable global
et utilisez la même manière que vous utilisez les globaux browser
ou element
dans les tests. Je l'ai utilisé pour créer des fonctions de demande globales personnalisées pour charger différents types d'entités:
// __dirname retuns a path of this particular config file
// assuming that protractor.conf.js is in the root of the project
var basePath = __dirname + '/test/e2e/';
// /path/to/project/test/e2e/
exports.config = {
onPrepare: function () {
// "relativePath" - path, relative to "basePath" variable
// If your entity files have suffixes - you can also keep them here
// not to mention them in test files every time
global.requirePO = function (relativePath) {
return require(basePath + 'po/' + relativePath + '.po.js');
};
global.requireHelper = function (relativePath) {
return require(basePath + 'helpers/' + relativePath + '.js');
};
}
};
Et puis vous pouvez utiliser ces méthodes utilitaires globales dans vos fichiers de test tout de suite:
"use strict";
var localStorageHelper = requireHelper('localStorage');
// /path/to/project/test/e2e/helpers/localStorage.js
var loginPage = requirePO('login');
// /path/to/project/test/e2e/po/login.po.js
var productShowPage = requirePO('product/show');
// /path/to/project/test/e2e/po/product/show.po.js
describe("Login functionality", function () {
beforeEach(function () {
browser.get("/#login");
localStorageHelper.clear();
});
// ...
});
Nous avons été confrontés au même problème et avons décidé de transformer tous les fichiers d'objet de page et les fichiers d'assistance en packages de nœuds. Les exiger dans les tests est maintenant aussi simple que var Header = require('header-po')
. Un autre avantage de la conversion en packages est que vous pouvez utiliser un bon contrôle de version.
Voici un exemple simple:
./ objets-page/header-po/index.js
//page-objects/header-po/index.js
'use strict';
var Header = function () {
this.goHome = function () {
$('#logo a').click();
};
};
module.exports = Header;
./ objets-page/header-po/package.json
{
"name": "header-po",
"version": "0.1.1",
"description": "Header page object",
"main": "index.js",
"dependencies": {}
}
./ package.json
{
"name": "e2e-test-framework",
"version": "0.1.0",
"description": "Test framework",
"dependencies": {
"jasmine": "^2.1.1",
"header-po": "./page-objects/header-po/",
}
}
./ tests/header-test.js
'use strict';
var Header = require('header-po');
var header = new Header();
describe('Header Test', function () {
it('clicking logo in header bar should open homepage', function () {
browser.get(browser.baseUrl + '/testpage');
header.goHome();
expect(browser.getCurrentUrl()).toBe(browser.baseUrl);
});
});
J'ai eu le même problème. A fait une solution similaire à celle de Michael Radionov, mais pas en définissant une fonction globale, mais en définissant une propriété pour le rapporteur lui-même.
protractor.conf.js
onPrepare: function() {
protractor.basePath = __dirname;
}
test-e2e.js
require(protractor.basePath+'/helpers.js');
describe('test', function() {
.......
});
Je pense que la méthode que nous utilisons là où je travaille pourrait être une bonne solution pour vous. J'ai publié un bref exemple de la façon dont nous traitons tout. C'est assez joli b/c, vous pouvez simplement appeler les fonctions d'objet de page dans n'importe quel fichier de spécification et vous n'avez pas besoin d'utiliser require dans la spécification.
Appelez un module de nœud à partir d'un autre module sans utiliser require () partout