I'm trying to automate some tests with protractor and jasmine and I'm using async/await to resolve the promises.
The issue is, when an error does happen, the stack trace is TOO short and thus, I can't seem to locate the source of the issue.
I did make sure to put SELENIUM_PROMISE_MANAGER to FALSE in the config file.
I'm using protractor 7 along with node 14.16.0
Does anyone know how to solve this ? There are not enough details
Here's a code snippet
const invoicesButton: Button = new Button("Invoices", LocatorType.Href, "#/Invoices");
describe("Kouka test", function () {
beforeEach(function () {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000000000;
});
it("Does a random test", async function () {
await browser.get("https://appdev.expensya.com/Portal/#/Login?lang=en");
await loginEmailInput.typeText("amr.refacto@yopmail.com")
await loginPasswordInput.typeText("a")
await loginButton.click(true);
await dashboardPage.invoicesButton.click().catch((e) => {
e.stackTraceLimit = Infinity;
throw e;
});
await userInvoicesPage.createManualInvoice(invoice).catch((e) => {
e.stackTraceLimit = Infinity;
console.error("TEST ERROR ", e);
throw e;
});
await browser.sleep(10000);
});
});
And here's the definition of the "Button" Class:
import { browser } from "protractor";
import { WebComponent } from "./webComponent";
export class Button extends WebComponent {
/**
* @param webElementText Text that the web element contains.
* @param locatorType Locator type of the web element to search for.
* @param locator Locator of the web element to search for.
* @param parentElement Parent Web Component if it exists.
*/
constructor(webElementText, locatorType, locator, parentElement: WebComponent = null) {
super(webElementText, locatorType, locator, parentElement);
}
async click(usingJavaScript = false) {
if (usingJavaScript) {
await this.isPresent();
await browser.executeScript("arguments[0].click();", await this.webElement)
}
else {
await this.isVisible();
await this.isClickable();
await this.webElement.click();
}
}
}
Finally, here's the stack trace
Started
Jasmine started
undefined
F
Kouka test
× Does a random test
- Failed: Wait timed out after 10012ms
at C:\Users\Amrou Bellalouna\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\promise.js:2201:17
at runMicrotasks (<anonymous>)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
From asynchronous test:
Error
at Suite.<anonymous> (C:\Users\Amrou Bellalouna\source\repos\NewE2EArchitecture\NewArchitecture\koukouTest.spec.ts:20:5)
at Object.<anonymous> (C:\Users\Amrou Bellalouna\source\repos\NewE2EArchitecture\NewArchitecture\koukouTest.spec.ts:15:1)
at Module._compile (internal/modules/cjs/loader.js:1063:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
at Module.load (internal/modules/cjs/loader.js:928:32)
at Function.Module._load (internal/modules/cjs/loader.js:769:14)
Failures:
1) Kouka test Does a random test
Message:
Failed: Wait timed out after 10012ms
Stack:
TimeoutError: Wait timed out after 10012ms
at C:\Users\Amrou Bellalouna\AppData\Roaming\npm\node_modules\protractor\node_modules\selenium-webdriver\lib\promise.js:2201:17
at runMicrotasks (<anonymous>)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
From asynchronous test:
Error
at Suite.<anonymous> (C:\Users\Amrou Bellalouna\source\repos\NewE2EArchitecture\NewArchitecture\koukouTest.spec.ts:20:5)
at Object.<anonymous> (C:\Users\Amrou Bellalouna\source\repos\NewE2EArchitecture\NewArchitecture\koukouTest.spec.ts:15:1)
at Module._compile (internal/modules/cjs/loader.js:1063:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
at Module.load (internal/modules/cjs/loader.js:928:32)
at Function.Module._load (internal/modules/cjs/loader.js:769:14)
1 spec, 1 failure
Finished in 19.461 seconds
I remember trying to solve this a while ago and I couldn't. But I implemented a bunch of workarounds and apparently this was enough
To begin, can you share what these are doing
await this.isPresent();
await this.isVisible();
await this.isClickable();
async isVisible(){
await browser.wait(
ExpectedConditions.visibilityOf(this.webElement),
this._elapsedTime
)
}
you can use an advantage of third argument of browser.wait
as described here and include an optional message on failure like this
async isVisible(){
await browser.wait(
ExpectedConditions.visibilityOf(this.webElement),
this._elapsedTime,
`Element ${this.webElement.locator().toString()} is not present after ${this._elapsedTime}ms`);
)
}
onPrepare
in the config /**
* Set global environment configuration
*/
Object.defineProperty(global, '__stack', {
get: function() {
let orig = Error.prepareStackTrace;
Error.prepareStackTrace = function(_, stack) {
return stack;
};
let err = new Error();
Error.captureStackTrace(err, arguments.callee);
let stack = err.stack;
Error.prepareStackTrace = orig;
return stack;
},
});
// returns name of the file from which is called
Object.defineProperty(global, '__file', {
get: function() {
let path = __stack[1].getFileName();
try {
//*nix OSes
return path.match(/[^\/]+\/[^\/]+$/)[0];
} catch (error) {
//Windows based OSes
return path.match(/[^\\]+\\[^\\]+$/)[0];
}
},
});
// returns function name from which is called
Object.defineProperty(global, '__function', {
get: function() {
return __stack[1].getFunctionName();
},
});
// returns line number of the position in code when called
Object.defineProperty(global, '__line', {
get: function() {
return __stack[1].getLineNumber();
},
});
then you can use it for logging the file name, function name, and the line where it's called
For example,
async isVisible(){
await browser.wait(
ExpectedConditions.visibilityOf(this.webElement),
this._elapsedTime,
`Failed at ${__file} -> ${__function}() -> line ${__line}`
)
}
will result in this error
- Failed: Failed at common/index.js -> isVisible() -> line 82
Wait timed out after 1032ms
Wait timed out after 1032ms
So you can accommodate this to your needs
also I just realized you may want to play around with __stack
variable itself