5

I have a Protarctor-CucumberJS framework and a suite of test scenarios. When I execute the entire suite, one script fails at an expect (ChaiJS) statement.

Scenario 1  : Passed
Scenario 2  : Passed
Scenario 3  : Failed (Unresolved Promise)
Scenario 4  : Skipped
Scenario 5  : Skipped
Scenario 6  : Skipped
Scenario 7  : Skipped
Scenario 8  : Skipped
Scenario 9  : Skipped
Scenario 10 : Skipped

The step definition of that particular step looks like this:

Then('I verify if valid success message received as {string}', function (successMessage) {
    expect($(.abc).getText()).to.eventually.equal(successMessage);
});

Due to a defect, app is not showing an error, the element: $(".abc") is not displayed on screen and this scenario fails after 30 seconds of function time-out. Complete error is pasted below. But the problem is all other scenarios after this are skipped with the same error message.

Error: function timed out, ensure the promise resolves within 30000 milliseconds at Timeout._time.default.setTimeout [as _onTimeout] (C:\bla\bla\node_modules\cucumber\lib\user_code_runner.js:81:20) at ontimeout (timers.js:436:11) at tryOnTimeout (timers.js:300:5) at listOnTimeout (timers.js:263:5) at Timer.processTimers (timers.js:223:10)

Questions:

  1. How can I avoid skipping of preceding scenarios if one scenario fails?
  2. How to resolve the promise in situations like above.
Harisha K P
  • 327
  • 2
  • 7
  • 19

1 Answers1

2

Are you able to use async functions? If so you could try with a conditional for if the element is present or not, something like this:

    Then('I verify if valid success message received as {string}', async function (successMessage, done) {
        const abcElement = await $(.abc).isPresent();
        if (abcElement) {
            expect(await $(.abc).getText()).to.eventually.equal(successMessage);
            done();
        } else {
            done();
        }
    });
Joaquin Casco
  • 704
  • 5
  • 14
  • Also I have used async functions too. That didn't effect in my case. – Harisha K P Nov 22 '19 at 19:00
  • async/await is just an _easier_ way to handle promises imo. You could try creating getText/click/etc functions with explicit waits inside so you don't repeat too much code – Joaquin Casco Nov 22 '19 at 19:01
  • Yeah. That can really help but i will have to update my existing code. That takes much effort. – Harisha K P Nov 22 '19 at 19:05
  • you can always change your `allScriptsTimeout` value in the conf.js file. It looks like is set to 30 secs, you could try lowering it to see what happens – Joaquin Casco Nov 22 '19 at 19:06
  • I have used setDefaultTimeout(30 *1000) in my BeforeAll hook. If I reduce it, it's Timed out like in 20 sec or 10 sec etc.. – Harisha K P Nov 22 '19 at 19:10
  • I have started to think about your solution seriously. I'm looking for one more info from your code sample above. Can you explain what;s the significance of 'done' argument of function and what happens when you call done()? – Harisha K P Nov 25 '19 at 15:39
  • It's a way to _let_ your app to _know_ when your task is complete when doing async work, like in the example I gave you. It's also pretty useful if you want to fail a case if something goes wrong. In my example you could do `done.fail('something');` in the `else` block – Joaquin Casco Nov 25 '19 at 17:23
  • That helps. Thanks a lot :-) – Harisha K P Nov 25 '19 at 17:51
  • I tried to use your code and I see error, can you help me resolve it: Error: function uses multiple asynchronous interfaces: callback and promise to use the callback interface: do not return a promise to use the promise interface: remove the last argument to the function – Harisha K P Nov 26 '19 at 20:18
  • Here is my code, you might have to format it to view properly: When('I click on {string}', async function(eleName, done){ let ele=eval(eleName); if (typeof ele !== 'undefined') { if (ele.isPresent()) { await ele.click(); done(); }else{ done.fail("Error: Element " + eleName + " not present on the screen"); } } else { done.fail("Error: Unable to find the element " + eleName + " in the page class."); } }); – Harisha K P Nov 26 '19 at 20:19
  • what are you passing through 'eleName' ? The whole `if typeOf` conditional might not be needed – Joaquin Casco Nov 26 '19 at 22:34
  • My way of implementation is little different. "eleName" is actually element name I'm sending from the Gherkin step as parameter. My elements are in a constructor of a class. The line "eval(eleName)" actually returns the element based on element name I'm sending from a step. This is to make the step definition reusable. just need to say: `When I click on "dealPage.addIssuer"` or `When I click on "productPage.dealName"` etc. Saying that, The error occurred at the line: `done.fail("");`. Actually `if typeOf` checks if the element returned successfully. – Harisha K P Nov 27 '19 at 14:17
  • So that, I can fail if the element not found in the repository class. – Harisha K P Nov 27 '19 at 14:21