简体   繁体   中英

Make a variable available throughout a spec.js file

I have a test spec file whose purpose is to check for a booking reference in our application then check that the same reference is quoted in an email.

In the first part of the test I declare a variable called dbmRef - I know this is working as I've got a console.log that shows the contents of the variable.

Further down- on in the email system (Outlook.com), I have another variable called dbm that finds the booking ref in the email body.

Finally, I have expect(dbm).toContain(dbmRef) but this errors with Expected 'DBM040815' to contain undefined.

I'm assuming that Protractor cannot 'see' the first variable from further up the script...is that right? If so, how can I remedy please?

Herewith the code - not in final form!

/**********************
 * Company: Guestline
 * Product: DBM
 * Author: D Redmayne
 **********************/

var hotKeys = require('protractor-hotkeys');

describe('DBM Hotel', function() {

  it('Confirmation', function() {
    browser.ignoreSynchronization = true;
    browser.sleep(500);

    // assertions
    expect(browser.getTitle()).toEqual('| Confirmation');

    var conf1 = element(by.xpath(".//*[@id='root']/div[2]/div/div[2]/div/section/div[1]/div[2]/div/h4")).getText();
    expect(conf1).toContain("DBM");

    var conf2 = element(by.xpath(".//*[@id='root']/div[2]/div/div[2]/div/section/div[3]/div[2]/div[1]/div/div[2]/span/span/span")).getText();
    expect(conf2).toContain("£50.00");

    var dbmRef = element(by.xpath(".//*[@id='root']/div[2]/div/div[2]/div/section/div[1]/div[2]/div/h4")).getText().then(console.log);

    // allows time for Outlook to capture email
    browser.sleep(2000);
    browser.get('https://outlook.com/');
    browser.ignoreSynchronization = true;
    browser.sleep(10000);

    //chooses sign-in
    element(by.xpath("html/body/section/div/div/nav/div/div/div/a")).click();
    browser.sleep(500);
    // enters credentials
    element(by.xpath(".//*[@id='i0116']")).sendKeys('xxxxxx@outlook.com');
    browser.sleep(1000);
    element(by.xpath(".//*[@id='idSIButton9']")).click();
    browser.sleep(500);
    element(by.xpath(".//*[@id='i0118']")).sendKeys('pppppppp');
    element(by.xpath(".//*[@id='idSIButton9']")).click();
    browser.sleep(300);
    expect(browser.getTitle()).toEqual('Mail - David Redmayne - Outlook');
    browser.sleep(10000);

    element(by.xpath("html/body/div[2]/div/div[2]/div/div[1]/div[3]/div[2]/div/div[1]/div[2]/div/div/div/div/div/div[2]/div/div/div")).click();
    browser.sleep(500);

    var dbm = element(by.xpath("html/body/div[2]/div/div[2]/div/div[1]/div[3]/div[2]/div/div[3]/div/div/div/div/div[2]/div/div[1]/div/div/div/div[2]/div[1]/div/div/div/table/tbody/tr[3]/td/table/tbody/tr/td/table/tbody/tr/td/table/tbody/tr[2]/td/b")).getText();
    expect(dbm).toContain(dbmRef);
  });
}); 

Answer to your question is simple, you just define your variable outside of describe like this

let myVar;

describe('DBM Hotel', function () {

  it('Confirmation', function () {
    console.log(myVar); // undefined
    myVar = "value";
  });

  it('Confirmation', function () {
    console.log(myVar); // value
  });
});

Not sure why it doesn't work inside of describe , but I assume because of how Jasmine works, which 'parses' describe with all its it blocks when browser isn't open yet.

BUT THIS IS NOT YOUR PROBLEM , because you do everything inside of same it block. Essentially you have bunch of problems. Your main issue is how you het variable

var dbmRef = element(by.xpath("xpath")).getText().then(console.log);

What this means is

var dbmRef = element(by.xpath("xpath")).getText().then(
  function(value) {
    console.log(value)
  }
);

You log your text, but the function still returns undefined by default, to change that you just need to add return statement like so

var dbmRef = element(by.xpath("xpath")).getText().then(
  function(value) {
    console.log(value);
    return value
  }
);

That's one way. Another way is

let dbmRef;

describe('DBM Hotel', function () {

  it('Confirmation', function () {
  // ...
    element(by.xpath("xpath")).getText().then(
      function(value) {
        dbmRef = value
      }
    );
  // ...
  });
});

You have to understand Promises to use this syntax. And finally the best way is this

it('Confirmation', async function () {
  // ...
  dbmRef = await element(by.xpath("xpath")).getText();
  // ...
});

But it requires await browser.waitForAngularEnabled(true) and some knowledge about async/await keywords. But it's a lot easier to understand them then Promises, so I highly recommend to spend a day and read all about it

And lastly I'll mention a few other problems in your code

// #1
browser.ignoreSynchronization = true;
browser.sleep(500);

expect(browser.getTitle()).toEqual('| Confirmation');

// #2
var conf1 = element(by.xpath(".//*[@id='root']/div[2]/div/div[2]/div/section/div[1]/div[2]/div/h4")).getText();
expect(conf1).toContain("DBM");

var conf2 = element(by.xpath(".//*[@id='root']/div[2]/div/div[2]/div/section/div[3]/div[2]/div[1]/div/div[2]/span/span/span")).getText();
expect(conf2).toContain("£50.00");
// #3
var dbmRef = element(by.xpath(".//*[@id='root']/div[2]/div/div[2]/div/section/div[1]/div[2]/div/h4")).getText().then(console.log);

browser.sleep(2000);
browser.get('https://outlook.com/');
// #4
browser.ignoreSynchronization = true;
browser.sleep(10000);

element(by.xpath("html/body/section/div/div/nav/div/div/div/a")).click();
browser.sleep(500);


element(by.xpath(".//*[@id='i0116']")).sendKeys('xxxxxx@outlook.com');
browser.sleep(1000);
element(by.xpath(".//*[@id='idSIButton9']")).click();
browser.sleep(500);
element(by.xpath(".//*[@id='i0118']")).sendKeys('pppppppp');
element(by.xpath(".//*[@id='idSIButton9']")).click();
browser.sleep(300);
expect(browser.getTitle()).toEqual('Mail - David Redmayne - Outlook');
browser.sleep(10000);

element(by.xpath("html/body/div[2]/div/div[2]/div/div[1]/div[3]/div[2]/div/div[1]/div[2]/div/div/div/div/div/div[2]/div/div/div")).click();
browser.sleep(500);

// #5
var dbm = element(by.xpath("html/body/div[2]/div/div[2]/div/div[1]/div[3]/div[2]/div/div[3]/div/div/div/div/div[2]/div/div[1]/div/div/div/div[2]/div[1]/div/div/div/table/tbody/tr[3]/td/table/tbody/tr/td/table/tbody/tr/td/table/tbody/tr[2]/td/b")).getText();
expect(dbm).toContain(dbmRef);

#1 if you use Protractor 5 and higher this command is deprecated

#2 the command may not work at times, because of how promises work

#3 is your main problem, I already explained

#4 duplicate command, you don't need it

#5 don't use these long xpath, they'll be breaking every day

Yep, AZ_ is right this question is related to the javascript variable scope .

However, the solution is that you could initialize variables outside the it block.

UPDATED:

    describe('DBM Hotel', function () {
      var dbmRef;

      it('Confirmation', function () {
        // ...
        element(by.xpath(".//*[@id='root']/div[2]/div/div[2]/div/section/div[1]/div[2]/div/h4")).getText().then(text => {
          dbmRef = text;
        });

        // ...
        var dbm = element(by.xpath("html/body/div[2]/div/div[2]/div/div[1]/div[3]/div[2]/div/div[3]/div/div/div/div/div[2]/div/div[1]/div/div/div/div[2]/div[1]/div/div/div/table/tbody/tr[3]/td/table/tbody/tr/td/table/tbody/tr/td/table/tbody/tr[2]/td/b")).getText();
        expect(dbm).toContain(dbmRef);
      });
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM