Skip to content Skip to sidebar Skip to footer

Is There A Way To Run Particular Protractor Test Depending On The Result Of The Other Test?

This kind of question has been asked before but most of this question has pretty complicated background. The scenario is simple. Let's say we are testing our favorite TODO app. Tes

Solution 1:

Man, I spent good couple of weeks researching this, and yes there was NO clear answers, until I realized how protractor works in details. If you understand this too you'll figure out the best option for you.

SOLUTION IS BELOW AFTER SHORT THEORY

1) If you try to pass async function to describe you see it'll fail, because it only accepts synchronous function

What it means for you, is that whatever condition you want to pass to it block, it can't be Promise based (Promise == resolves somewhen, but not immediately). What you're trying to do essentially IS a Promise (open page, do something and wait to see if the condition satisfies your criteria)

if (conditionIsTrue) { // can't be Promiseit('name', () => {
  })
}

Thats first thing to consider...

2) When you run protractor, it picks up spec files specified in config and builds the queue of describe/it AND beforeAll/afterAll blocks. IMPORTANT DETAIL HERE IS THAT IT HAPPENS BEFORE THE BROWSER EVEN STARTED.

Look at this example

let conditionIsTrue; // undefinedit('name', () => {
    conditionIsTrue = true;
  })
if (conditionIsTrue) { // still undefinedit('name', () => {
  })
}

By the time Protractor reaches if() statement, the value of conditionIsTrue is still undefined. And it maybe overwritten inside of it block, when browser starts, later on, but not when it builds the queue. So it skips it.

In other words, protractor knows which describe blocks it'll run before it even opens the browser, and this queue can NOT be modified during execution

POSSIBLE SOLUTION

1.1 Define a global variable outside of describe

let conditionIsTrue; // undefineddescribe("describe", () => {
  it('name1', async () => {
    conditionIsTrue = await element.isPresent(); // NOW IT'S TRUE if element is present
  })

  it('name2', async () => {
    if (conditionIsTrue) {
      //do whatever you want if the element is present
    } else {
      console.log("Skipping 'name2' test")
    }
  })
})

So you won't skip the it block itself, however you can skip anything inside of it

1.2 The same approach can be used for skipping it blocks across different specs, using environment variable. Example:

spec_1.js

describe(`Suite: 1`, () => {
  it("element is present", async () => {
    if (await element.isPresent()) {
      process.env.FLAG = true
    } else {
      process.env.FLAG = false
    }
  });
});

spec_2.js

describe(`Suite: 2`, () => {
  it("element is present", async () => {
    if (process.env.FLAG) {
      // do element specific actions
    }
  });
});
  1. Another possibility I found out, but never had a chance to check is to use Grunt task runner, which may help you implement the following scenario

    • Run protractor to execute one spec
    • Check a desired condition
    • Export this condition to environment variable
    • Exit protractor
    • In your Grunt task implement a conditional logic for executing the rests of conditional specs, by starting protractor again

But honestly, I don't see why you'd want to go this time consuming route, which requires a lot of code... But just as an FYI

Solution 2:

There is one way provided by Protractor which might achieve what you want to achieve. In protractor config file you can have onPrepare function. It is actually a callback function called once protractor is ready and available, and before the specs are executed. If multiple capabilities are being run, this will run once per capability.

Now as i understand you need to do a test or we can say execute a parent function and then based on its output you want to run some tests and do not want to run other tests.

onPrepare function in protractor config file will look like this :

onPrepare: async () => {
        await browser.manage().window().maximize();
        await browser.driver.get('url')
        // continue your parent test steps for adding an item and at the last of function you can assign a global variable say global.itemAdded = true/false based on the result of above test steps. Note that you need to use 'global.' here to make it a global variable which will then be available in all specs 
}

Now in you specs file you can run tests (it()) based on global.itemAdded variable value

if(global.itemAdded === true) {
  it('This test should be running' () => {
  })
}

if(global.itemAdded === false) {
  it('This test should not be running' () => {
  })
}

Post a Comment for "Is There A Way To Run Particular Protractor Test Depending On The Result Of The Other Test?"