The Question:
Is it possible to clean up the stack trace and leave only relevant frames eliminating everything Protractor
, WebDriverJS
and Jasmine
specific?
The Story:
Let's execute this example test:
describe("SO test", function () { beforeEach(function () { browser.get("https://angularjs.org"); }); it("should throw a meaningful error", function () { element(by.id("not_found")).click(); }); });
It would fail with a following stacktrace:
SO test should throw a meaningful error - Failed: No element found using locator: By.id("not_found") at new bot.Error (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/atoms/error.js:108:18) at /usr/local/lib/node_modules/protractor/lib/element.js:676:15 at [object Object].promise.Promise.goog.defineClass.invokeCallback_ (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/goog/../webdriver/promise.js:1337:14) at [object Object].promise.ControlFlow.goog.defineClass.goog.defineClass.abort_.error.executeNext_.execute_ (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/goog/../webdriver/promise.js:2776:14) at [object Object].promise.ControlFlow.goog.defineClass.goog.defineClass.abort_.error.executeNext_ (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/goog/../webdriver/promise.js:2758:21) at goog.async.run.processWorkQueue (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/goog/async/run.js:124:15) at process._tickCallback (node.js:377:9) Error at [object Object].ElementArrayFinder.applyAction_ (/usr/local/lib/node_modules/protractor/lib/element.js:382:21) at [object Object].ElementArrayFinder.(anonymous function) [as click] (/usr/local/lib/node_modules/protractor/lib/element.js:78:17) at [object Object].ElementFinder.(anonymous function) [as click] (/usr/local/lib/node_modules/protractor/lib/element.js:711:7) at Object.(/Users/user/job/project/test/e2e/specs/test.spec.js:9:37) at /usr/local/lib/node_modules/protractor/node_modules/jasminewd2/index.js:96:23 at [object Object].promise.Promise.goog.defineClass.constructor (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/goog/../webdriver/promise.js:1056:7) at new wrappedCtr (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/goog/base.js:2468:26) at controlFlowExecute (/usr/local/lib/node_modules/protractor/node_modules/jasminewd2/index.js:82:18) at [object Object].promise.ControlFlow.goog.defineClass.goog.defineClass.abort_.error.executeNext_.execute_ (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/goog/../webdriver/promise.js:2776:14) at [object Object].promise.ControlFlow.goog.defineClass.goog.defineClass.abort_.error.executeNext_ (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/goog/../webdriver/promise.js:2758:21) From: Task: Run it("should throw a meaningful error") in control flow at Object. (/usr/local/lib/node_modules/protractor/node_modules/jasminewd2/index.js:81:14) at /usr/local/lib/node_modules/protractor/node_modules/jasminewd2/index.js:18:5 at [object Object].promise.Promise.goog.defineClass.invokeCallback_ (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/goog/../webdriver/promise.js:1337:14) at [object Object].promise.ControlFlow.goog.defineClass.goog.defineClass.abort_.error.executeNext_.execute_ (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/goog/../webdriver/promise.js:2776:14) at [object Object].promise.ControlFlow.goog.defineClass.goog.defineClass.abort_.error.executeNext_ (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/goog/../webdriver/promise.js:2758:21) at goog.async.run.processWorkQueue (/usr/local/lib/node_modules/protractor/node_modules/selenium-webdriver/lib/goog/async/run.js:124:15) From asynchronous test: Error at Suite. (/Users/user/job/project/test/e2e/specs/test.spec.js:8:5) at Object. (/Users/user/job/project/test/e2e/specs/test.spec.js:3:1) at Module._compile (module.js:425:26) at Object.Module._extensions..js (module.js:432:10) at Module.load (module.js:356:32)
As you can see, it's not easy to find on which line in the test the error actually happened. It's hidden somewhere inside the stack trace covered by Protractor
, WebDriverJS
and Jasmine
stack frames. This makes it difficult to debug and develop end-to-end tests.
Desired output:
SO test should throw a meaningful error - Failed: No element found using locator: By.id("not_found") at Object.(/Users/user/job/project/test/e2e/specs/test.spec.js:9:37) From asynchronous test: Error at Suite. (/Users/user/job/project/test/e2e/specs/test.spec.js:8:5) at Object. (/Users/user/job/project/test/e2e/specs/test.spec.js:3:1) at Module._compile (module.js:425:26) at Object.Module._extensions..js (module.js:432:10) at Module.load (module.js:356:32) at Function.Module._load (module.js:311:12)
Using protractor
3.0.0 and jasmine2
.
In mocha
world, there is a relevant mocha-clean
package that filters out everything coming from inside node_modules
and mocha
itself leaving a clean stack trace that is easy to read.