Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using require with relative paths

We have a rather big set of end-to-end tests on Protractor. We are following the Page Object pattern which helps us to keep our tests clean and modular. We also have a set of helper functions which help us to follow the DRY principle.

The Problem:

A single spec may require multiple page objects and helper modules. For instance:

"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();     });      // ...  }); 

You can see that we have that directory traversal in every require statement: ./../... This is because we have a specs directory where we keep the specs and multiple directories inside grouped by application functionality under test.

The Question:

What is the canonical way to approach the relative path problem in Protractor?

In other words, we'd like to avoid traversing the tree, going up to import modules. It would be much cleaner to go down from the base application directory instead.


Attempts and thoughts:

There is a great article about approaching this problem: Better local require() paths for Node.js, but I'm not sure which of the options is a recommended one when developing tests with Protractor.

We've also tried to use require.main to construct the path, but it points to the node_modules/protractor directory instead of our application directory.

like image 952
alecxe Avatar asked Jul 18 '15 14:07

alecxe


People also ask

Does chdir work with relative path?

Yes. The current working directory is a property of the process.

How do you use relative paths?

Relative paths make use of two special symbols, a dot (.) and a double-dot (..), which translate into the current directory and the parent directory. Double dots are used for moving up in the hierarchy. A single dot represents the current directory itself.

Should I use relative or absolute paths?

If you do a lot of testing and move content frequently between domains, then relative links are the best solution. Absolute paths are more secure, protect content, and prevent duplicate pages. The main point is that the link format you prefer should be applied to all URLs on the site.

Why is it better to use relative paths instead of absolute paths?

Absolute URLs must be used to link to other websites that are not located on the same domain. Relative URLs, on the other hand, are more easy to use because they are relative to the page they are on.


1 Answers

I had the same problem and I ended up with the following solution. In my Protractor config file I have a variable which stores a path to a base folder of my e2e tests. Also, Protractor config provides the onPrepare callback, where you can use a variable called global to create global variables for your tests. You define them as a properties of that global variable and use the same way you use globals browser or element in tests. I've used it to create custom global require functions to load different types of entities:

// __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');         };      }  }; 

And then you can use these global utility methods in your test files right away:

"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();     });      // ...  }); 
like image 186
Michael Radionov Avatar answered Oct 11 '22 16:10

Michael Radionov