7

I have (I think) kind of unique problem with js. I'm writing tests using protractor stuff and Jasmine and I need to share data between js files. Is there any way to do that? All the solutions I've found are for webpages and I use just js files.

I look forward to your swift response, if there is any information missing, please let me know and I'll add it immediately.

Krzysztof Piszko
  • 1,355
  • 3
  • 12
  • 17
  • 2
    I haven't used protractor yet, but with karma and jasmine, you can share data using requirejs. If you want I can give some more details. – kihu Sep 25 '14 at 10:43
  • As far as I know I can only use: Protractor API, Selenium API, Jasmine, JS. It's not my private project so unfortunately I can't use other stuff. UNLESS, I understood you wrong and this is "built into" js. @Edit: Wait, you mean that requirejs is built into Jasmine? If yes, then by all means elaborate. – Krzysztof Piszko Sep 25 '14 at 10:51
  • no, requirejs is a saparate library http://requirejs.org/ – kihu Sep 25 '14 at 10:55
  • That's a darn shame then. Thanks anyway! – Krzysztof Piszko Sep 25 '14 at 10:56
  • Otherwise. perhaps you could declare your data as a global variable in first test, then it would be available for other tests to read. I'm not 100% sure it will work, though. – kihu Sep 25 '14 at 11:01
  • Yeah, I've thought about declaring it globally, but it could mess up some future tests, and I'd very much prefer to share it between those files only. I'm kind new to JS, but could you tell me if [this](http://stackoverflow.com/questions/1535631/static-variables-in-javascript) could do the trick? Like set value in one file and then it should have the same value in another instance, right? – Krzysztof Piszko Sep 25 '14 at 11:04
  • Yeah, but this still causes problems if you alter data in one test and then read in another. You could do sth like: MyClass.getFreshData() and return a new data object (copy) every time it's called. This way each test will use the same non-altered data. JS passes Objects by reference and primitives by value, so if your data is Object, you need to make a deep copy each time. – kihu Sep 25 '14 at 11:19

4 Answers4

8

I have not tested this myself, but maybe you can try to put stuff in the global scope using:

global.mySharedData = {someKey: 'some value'}

// in one of your test files
it('should do something', function() {
  global.mySharedData = {someKey: 'some value'}
});

...

// This is in another test suite
it('should do something', function() {
  var valueFromFirstTest = global.mySharedData.someKey;
});

http://nodejs.org/api/globals.html

Let me know if it works.

Andres D
  • 8,910
  • 2
  • 26
  • 31
  • 2
    I like it, simple and effective Andres!. Curious: why not using `browser.params` instead of global? I actually use both approaches: `browser.params` for immutable shared testing config data while `global.testState` when I need to grab running test data like the x,y location of an element in order to test resizing it, for example. – Leo Gallucci Sep 25 '14 at 16:39
  • Andres, btw, there is plenty of unanswered questions in `protractor` tag, hope you would show up more often and help here. Also, how can I get a protractor t-shirt like you were wearing on the meetup? :) – alecxe Sep 26 '14 at 00:41
  • Holly molly, it does indeed work. Thanks a lot! Such a simple solution. – Krzysztof Piszko Sep 26 '14 at 07:06
  • 1
    @LeoGallucci I usually pull the data I need from with a rest api call from protractor. I haven't used browser.params because I use flags, but it is a good tip! – Andres D Sep 26 '14 at 14:38
  • I used global['myVariable] in Jasmine and it works with variables from `declare var` – L1ghtk3ira Sep 11 '18 at 19:40
2

If you need to share dynamic data between files you can also do the following. Here's a working example. What I needed to do was take parts of the URL and use them across different files.

it('should click on one of the clickable profiles', function(){

        //Get entity type and entity id before clicking the link
        tableEls.get(1).all( by.xpath('./td') ).get(0).element( by.xpath('./a') ).getAttribute('href').then(function(text){

            var hrefTokens  = text.split('/');
            var entityID    = hrefTokens[ hrefTokens.length - 1 ];
            var entityType  = hrefTokens[ hrefTokens.length - 2 ];

            browser.params.entityID   = entityID;
            browser.params.entityType = entityType;
        });

        tableEls.get(1).all( by.xpath('./td') ).get(0).element( by.xpath('./a') ).click();
        browser.sleep(2000);
    });

I simply assigned the values that I needed to use in other files to the browser.params. So in my other files I can access them like this

    it('Retrieving JSON Data ...', function(){

        var entityID   = browser.params.entityID;
        var entityType = browser.params.entityType;
   });
Haseeb
  • 190
  • 1
  • 6
  • 16
1

There is a simple way to share data and even functions among Protractor spec JavaScript files. They run in node.js with a built-in way to define modules and use and reuse them - http://nodejs.org/docs/latest/api/modules.html.

Assuming the following folder's stracture:

o e2e
|-- utils.js
|-- a-spec.js
|-- b-spec.js

In utils.js:

exports.sharedData = { num: 42, str: 'hi' };
exports.foo = function (x) { return x + 1; };

In a-spec.js:

var utils = require('./utils.js'); // Note './'

describe("The a page", function () {
    it("should give the ultimative answer", function () {
        expect(element(by.binding("answer")).getTest())
            .toBe(utils.sharedData.num); // Using shared data
    });
});
Ilia Barahovsky
  • 10,158
  • 8
  • 41
  • 52
1

I included this in my config js file where i declare my variables for protractor.

(function () {
    this.defaultPassword = function () {
        return 'superPassword';
    };
}());

Usage in other file is like:

var userLogin = { 'Email': 'something@gmail.com', 'Password': defaultPassword },
Hans Poppe
  • 323
  • 2
  • 10