Protractor: Element explorer doesn't work on Node 8

Created on 1 Jun 2017  ·  65Comments  ·  Source: angular/protractor

Bug report

  • Node Version: 8.0.0
  • Protractor Version: 5.1.2
  • Angular Version: n/a
  • Browser(s): Chrome / chromedriver 2.29.0
  • Operating System and Version Mac Sierra 10.12.5
  • Your protractor configuration file n/a

After installing node v8.0.0 and npm v5.0.0, reinstalling protractor globally and running webdriver-manager update, I cannot run protractor --elementExplorer because I receive the following error:

protractor --elementExplorer
(node:76684) [DEP0022] DeprecationWarning: os.tmpDir() is deprecated. Use os.tmpdir() instead.
[11:04:10] I/hosted - Using the selenium server at http://localhost:4444/wd/hub
[11:04:11] I/protractor -
[11:04:11] I/protractor - ------- Element Explorer -------
[11:04:11] I/protractor - Starting WebDriver debugger in a child process. Element Explorer is still beta, please report issues at github.com/angular/protractor
[11:04:11] I/protractor -
[11:04:11] I/protractor - Type <tab> to see a list of locator strategies.
[11:04:11] I/protractor - Use the `list` helper function to find elements by strategy:
[11:04:11] I/protractor -   e.g., list(by.binding('')) gets all bindings.
[11:04:11] I/protractor -
module.js:487
    throw err;
    ^

Error: Cannot find module '_debugger'
    at Function.Module._resolveFilename (module.js:485:15)
    at Function.Module._load (module.js:437:25)
    at Module.require (module.js:513:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/usr/local/lib/node_modules/protractor/built/debugger/debuggerCommons.js:1:82)
    at Module._compile (module.js:569:30)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:503:32)
    at tryModuleLoad (module.js:466:12)
    at Function.Module._load (module.js:458:3)

If I revert back to node 7.10.0 I don't get this error.

PRs plz! needs investigation

Most helpful comment

Are there plans from the team to get this working again with either the inspect API or something other approach?

All 65 comments

I don't think we are currently testing against node 8 so it makes sense that this may be broken. Thanks for bringing this up!

I'll try to dig into this in the next few days but a PR to fix this would be very welcome!

_debugger and the legacy CLI debugger were removed in Node 8: https://github.com/nodejs/node/commit/90476ac6ee

Any updates on this?

Could we please know what are the plans for Node 8 support? :)

With Node v8 set to enter LTS in October, maybe we could get an update?

https://github.com/nodejs/LTS#lts-schedule1

According to https://nodejs.org/en/docs/guides/debugging-getting-started/#legacy-debugger ,
the node.js team is migrating users to the new inspect API.

Are there plans from the team to get this working again with either the inspect API or something other approach?

I've started having a look into this. Here are a bunch of guesses about how updating this might work:

As far as I can tell, the changes need to happen in debuggerCommons.js

Rather than require('_debugger'); it needs to use require('inspector'); (docs here). You can then open the inspector, create a session, connect to it, and then use session.post and the Chrome DevTools Protocol to send the messages to add the breakpoints.

I'll have a crack at a PR when I get some time.

@phenomnomnominal Hey that's great! May I know when you are available for making the PR? Since this functionality is so useful, would be great if it can be created soon. It will speed up our development so much.
Thanks!

@phenomnomnominal Hi, we are planing to support node 8.0 recently, what's your current plan of fixing this issue?

Only what I outlined above. I was planning on having a crack at it this evening.

@phenomnomnominal that's great, thanks a lot!

@phenomnomnominal Hi, any updates so far?

I started having a go, but I was having issues with Selenium when trying to run the tests (any tips?). I’m going to have some more time Tuesday night. The new API is quite different, but I don’t foresee any real issues.

ok, thanks a lot. I am supposed to have some time after Monday, maybe I can also look into it after that.

I got... somewhere? Turns out debugging the debugger isn't as straightforward as I'd have hoped. @qiyigg did you have a chance to look at anything?

I will look into it today, thanks!

I’ll have some more time this evening too, we can compare notes later.

Hi, any progress on this issue in the last week? It's still occurring.

For protractor debugger/explorer, we decided not to support it in node 8.

  1. Protractor debugger/explorer mainly designed to debug test in control flow; but control flow is something we don't encourage(Especially we have native async/await in node 8) and will be eventually deprecated.
  2. After investigating, we found it might need much effort to fix it and not worth doing that according to reason 1.
  3. We are working on providing new debugging documents for node 8 using native async/await and chrome inspector tool, which will give better experience than original debugger.
  4. @phenomnomnominal If you have some breakthrough about this, we'd like to review it. Thanks for your effort.

Do you have some kind of ETA for this? We're chomping at the bit for it where I work. Trying to teach some people about e2e testing and we don't have a way to go into debug mode and actually execute code in the context where the failure occurs. If there is a way this can be done outside of this please let me know.

@KellyR-STCU
Hi,
For node version < 8, you can use the original debugging process/tools.
For node version >=8, you can follow the new debugging process, which uses Node.js native async/await to handle asynchronous call(so that we don't need rely on control flow and old debugger), and use chrome inspector(or any other node debugger) to debug

We have some documents to describe how to debug with native async/await and chrome inspector
debugging with control flow disabled
how to use async/await

Hope it helps

@qiyigg what about elementExplorer?

@monkpit it won't work in Node 8 for the same reason. We don't have a complete substitute for that, but you can open and use chrome development tool during debugging, it won't conflict with protractor debugging as we encountered before.

@qiyigg ok, since the elementExplorer feature was the focus of the issue, I am going to leave it open.

The solution is also a bit of a problem since it requires rewriting existing tests because "you cannot use a mix of async/await and the control flow". It would be nice if you could specify which approach to take per test so that switching didn't require updating all existing tests.

@uriah-ascend
yes, I have to admit that it's not a perfect solution. But as I mentioned above, control flow is something that will be eventually removed. Convert our tests to async/await is something we should do gradually, and it does give us better debugging experience.
I guess one way you could do is to have a separate test config for new tests, and then convert them gradually.

@qiyigg is there some guide or documentation how to convert to async/await?

Pretty good info in those two links he provided titled debugging with control flow disabled and
how to use async/await

The second one is probably more of a step by step for conversion.

After having issue with browser.pause() on Node 8.

I followed Disabled Control Flow.

Instead of running node --inspect-brk bin/protractor <config_file> and do debugging in the browser, I use node inspect $(which protractor) <config_file> followed by debug> cont in the terminal.

Now I have browser.pause() equivalent.

i.e. use debugger in place of browser.pause()

Just to check: we have a large protractor codebase, which can't be converted to async/await all at once. A good way to go about this is to first convert all the "async" protractor actions using promise chaining right ? This way things should work whether control flow is enabled or not.
Thanks !

Promise chaining will work whether control flow is enabled or not, but it is kind of messy sometimes and you might want to change it back to async/await someday?
So my suggestion is to have two separate config for now, put the new test / converted test into the new config which disables control_flow and get rid of the old one gradually

The problem is that we share a lot of functions between tests, so if we migrate these functions to async await we'll be breaking all the tests that use them and that haven't been migrated to async await (hint: A LOT). And if we keep two versions of the same function we risk having them diverge.
So it seems to me that either we move everything to promise chaining as an intermediate step before moving to async/await, or we set up babel to transpile our test codebase (using something like that: https://stackoverflow.com/questions/28708975/transpile-async-await-proposal-with-babel-js ?), so that we can write async/await and have it transpiled to something that can be run either with control flow or without.
Does anyone know if this has been done before ?
In any case it seems it would be a good idea to give migrations paths for large codebases on the readme...

Make sense, actually we are thinking about it recently.
I've talked to an internal team who migrated large code base to async/await.
They found that it will introduced subtle bugs and race conditions if they changed common utils to promise chain and they already gave up to do that.
They did copy some common utils and translate them into async/await. I don't know whether it is the best solution, but as you mentioned, it will have some diverge risk
We are also working on writing some migration tool to make it easier, but the tools perhaps won't work externally.

Anyway, we are working on migration plan recently, and should give some migration advice in somewhere in the near future.

Thanks you for your reply, it's good to know that it is an issue that is
being looked into !
I think it would be a good idea to create a specific issue for how to
migrate large codebases, so that people see it's being worked on.

Le 16 janv. 2018 19:58, "qiyi" notifications@github.com a écrit :

Make sense, actually we are thinking about it recently.
I've talked to an internal team who migrated large code base to
async/await.
They found that it will introduced subtle bugs and race conditions if they
changed common utils to promise chain and they already gave up to do that.
They did copy some common utils and translate them into async/await. I
don't know whether it is the best solution, but as you mentioned, it will
have some diverge risk
We are also working on writing some migration tool to make it easier, but
the tools perhaps won't work externally.

Anyway, we are working on migration plan recently, and should give some
migration advice in somewhere in the near future.


You are receiving this because you commented.
Reply to this email directly, view it on GitHub
https://github.com/angular/protractor/issues/4307#issuecomment-358068096,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AHHOgiLEdFS-xZVcOKmO1EB-CID53cryks5tLPFagaJpZM4NtM1n
.

Hi guys! Any workaround exist?

protractor - 5.2.2
nodejs - 9.3
protractor --elementExplorer
(node:72438) [DEP0022] DeprecationWarning: os.tmpDir() is deprecated. Use os.tmpdir() instead.
[19:15:43] I/local - Starting selenium standalone server...
[19:15:44] I/local - Selenium standalone server started at http://172.29.148.101:58279/wd/hub
[19:15:45] I/protractor -
[19:15:45] I/protractor - ------- Element Explorer -------
[19:15:45] I/protractor - Starting WebDriver debugger in a child process. Element Explorer is still beta, please report issues at github.com/angular/protractor
[19:15:45] I/protractor -
[19:15:45] I/protractor - Type <tab> to see a list of locator strategies.
[19:15:45] I/protractor - Use the `list` helper function to find elements by strategy:
[19:15:45] I/protractor -   e.g., list(by.binding('')) gets all bindings.
[19:15:45] I/protractor -
module.js:557
    throw err;
    ^

Error: Cannot find module '_debugger'
    at Function.Module._resolveFilename (module.js:555:15)
    at Function.Module._load (module.js:482:25)
    at Module.require (module.js:604:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/usr/local/lib/node_modules/protractor/built/debugger/debuggerCommons.js:1:82)
    at Module._compile (module.js:660:30)
    at Object.Module._extensions..js (module.js:671:10)
    at Module.load (module.js:573:32)
    at tryModuleLoad (module.js:513:12)
    at Function.Module._load (module.js:505:3)
[19:15:45] I/local - Shutting down selenium standalone server.
MB-219751:~ olekh$ 

Also experiencing the Error: Cannot find module '_debugger', OSX.

This issue has been open for almost a year. Still no progress?

@ajklotz I can confirm it still only works with Node 7. I've been using nvm to switch between Node versions in order to use element explorer. It's a pain, but it works!

@ajklotz @monkpit @mraible If you are able to run with Node 8 or higher, I recommend that you try to do the following:

  1. Watch this video "Protractor: A New Hope" https://youtu.be/6aPfHrSl0Qk?t=1051 , specifically starting around 17:31
  2. Switch to using Node 8 or higher
  3. Convert your tests to use the ES2017 async/await keywords: https://github.com/angular/protractor/blob/master/docs/async-await.md
  4. Add SELENIUM_PROMISE_MANAGER: false, to your protractor.conf.js
  5. Use the new debugger function and use chrome inspector to debug: https://github.com/angular/protractor/blob/master/docs/debugging.md#disabled-control-flow

I have done this with my own Protractor tests and confirm that it works.

@ajklotz @monkpit @mraible Here is an example where I converted Protractor tests to use async/await: https://github.com/buildbot/buildbot/pull/4074/files

Anything that returns a Promise, you stick an await in front of it such as:

  • .click()
  • .browser.wait()
  • .browser.get()
  • .getText()

If a function has a call to await, then the function signature must have async in front of it.

If you call a function with async, then you must await it.

It takes a while but once you do it, then it works.

@rodrigc My tests area already using async/await, the point of this issue is that from the command line, protractor --elementExplorer doesn't work unless you use node 7.

FWIW, seems like a language feature like async/await should be irrelevant anyway. Perhaps a swap as a stop-gap fix makes sense, but Protractor doesn't imply dependence on that style.

@monkpit Yes you are absolutely right. The root cause of your problem is that on this line: https://github.com/angular/protractor/blob/master/lib/debugger/debuggerCommons.js#L1 , the _debugger module is imported, which is unavailable on node8. Anything that uses debuggerCommons.js will thus not work on node8, including elementExplorer.

So, if you want to use node8 or higher and debug with protractor, the key is to use async/await and follow the steps at: https://github.com/angular/protractor/blob/master/docs/debugging.md

The old debugging stuff won't work.

Either it’s not going to get fixed (that’s fine, I can use the workaround) or it will be updated to use node 8+ (that’s also fine). But I would love to see an official response one way or the other.

@monkpit

I think the answer lies in this comment of @qiyigg.

For protractor debugger/explorer, we decided not to support it in node 8...

From what I've heard from @qiyigg when I talked to him the current focus in the team is lying on _disabling control flow in Protractor tests_.

I'm going to close this issue for now. It's still open for discussion.

@qiyigg I have started using the new debugger with chrome inspector, and node8 and it works well.

Can the protractor team start marking the documentation for the old debugging code which uses debuggerCommon.js as DEPRECATED? I agree with @monkpit that things are a bit confusing now where the code does not work with node8, but it is not marked as deprecated. Ultimately this old debugging code should just be deleted if it is never going to get fixed with node8.

If you take a look at the debugging document, we have already mentioned the debugger won't work on Node 8
https://github.com/angular/protractor/blob/master/docs/debugging.md#enabled-control-flow
"Note: Protractor debugger and element explorer cannot be used for Node.js 8+"

One thing to keep in mind is: not everyone is using Node 8+, we cannot say debugger is deprecated and enforce everyone to use async/await (Although we will do so inside google).

Apparently, moving to Node 8+ and async/await have many benefits and we should move to it eventually, but it is not an easy job since we have to change lots of our existing code. We are working on this inside google and try to accumulate more experience about migration (even migration tools)and hope it could also help users outside google eventually.

I think what we could do now is to make this error more clear, say, throw an exception: element explorer/debugger is not supported for Node 8+ instead of "Error: Cannot find module '_debugger'", A PR will be very welcomed.

@qiyigg I would suggest to make that warning in bold and ALL CAPS. It is a bit hard to catch on that page, because there are a lot of words.

i'm really happy with the new debugger because i can use intellij to run my tests. this is way better than the element explorer (which i rather liked) but using my IDE to debug tests is a huge win.

@qiyigg I work at a company that makes large production pinters. Because we changed all our UI's to use Angular (hurray!) we decided to use Protractor for the UI E2E tests (also hurray). Apart from these E2E tests we also have real end to end tests that work on an actual running system. All the test cases for that test system are specified in the Microsft TFS testing framework and we use a DSL to write them. This DSL loads the page objects we wrote for our UI's through an interactively started protractor (so the element explorer) and calls methods on them to execute its tests.

So far so good, you would say, we have thousands of these tests and they run really "as a user". What I make out of this conversation is that element explorer is dropped with the new node (and the new node is mandatory for upgrading Angular). This also means that all of a sudden our entire test base would stop working.

I get the change with async / wait and we will rewrite our page objects obviously to support it, but there's no real alternative to remotely insert protractor commands, right? I will always have to pass in "a test" that only calls "debugger", and then directly communicate with chrome to call a command on my page objects and then run to the next "debugger" call which I then probably will have to run in a while loop.

Were scenario's like these not supported? Won't they be? Or am I just missing something ... To me, debugging errors in your tests/code is entirely different from remotely instructing test commands. The latter is something element explorer used to facilitate :)

To at least share what my current solution is, I have written this test, which is the only system test I run with protractor (CompletableFuture is a helper class obviously):

jasmine.DEFAULT_TIMEOUT_INTERVAL = 3600000; // arbitrary large timeout
(global as any).systemTestsDone = new CompletablePromise<void>();

describe('TestHelper', () => {
  it('should provide a way to interactively run tests', async () => {
    await (global as any).systemTestsDone;
  });
});
node --inspect .\node_modules\protractor\bin\protractor .\systemTests\protractor.conf.js

This test then keeps running while I connect my (C#) WS client that acts as a bridge between the test specs, and the page objects. This bridge then instructs the browser to load the page objects and the tests start executing.

The last command I send to the browser is of course

global.systemTestsDone.complete()

so that the test completes normally. I don't think this is really awful, the only strange thing is that I now have to abuse a test to get into an interactive mode. If more people are missing functionality like this it might be a good idea to include it in protractor again. I don't mean an entire devtools protocol but the option to leave protractor running while you, for example, use the console of chrome or visual studio code as "element explorer".

add @vikerman, who will take over the Protractor stuff.

@vikerman Should I make a feature request out of the above comments?

In short, what I would like to have in protractor (since --elementExplorer is no longer working with recent node.js versions) is a mode that just starts protractor, ignores spec files and just keeps running until some manual method call (something like protractor.exit()?). We could start protractor in this mode with node --inspect, load some page objects and connect an external test runner to the debugger protocol and run the tests interactively.

this would be really good if someone fixes this. I am currently using nvm as a work around.
i use nvm to install node 7.10.1 and fire up elementExplorer from there.
bit of lame workaround but it works for now

I downgraded to node v6 to get this to work and now I can't run my Angular 6 app because node 6 isn't supported in Angular 6+. It looks like Angular now targets node >= 8.9.0.

Is there a good work around that I can follow to get a protractor REPL w/o having to run two versions of node?

I'm having the same error in the console. I'm following these instructions given here
https://github.com/angular/protractor/blob/master/docs/debugging.md#enabled-control-flow

but still same error is coming 👎

So is this the end for browser.pause() / browser.debugger()? Appears we should be moving away from control flow and using node debugger.
https://github.com/angular/protractor/blob/master/docs/debugging.md

Using NVM to switch to node version 7.10.1 fixed the browser.pause() issue for me.

I understand that async/await is the way forward, and using Webstorm to debug tests with breakpoints is absolutely seamless, but where I feel the absence of elementExplorer is its extended usage in the elementor package, which was a delightful way to interactively test out parts of code on the fly (in the omnibox) instead of running the entire test from scratch.
With the given debugging process for nodejs 8+, the commands from the console do not resolve promises while the inspector is paused at a breakpoint, which I realise is counter-intuitive, but all this has meant a subtle increase in time spent on writing/debugging tests, and loss of a widely used feature (going by number of responses on this thread).
Are there any plans to have a substitute for the old elementExplorer feature in protractor?

@woppa684 Suggestion is working nicely for me. Thanks @woppa684. I just moved to node 10+ which has repl-await (so you can just await in the console)

Added all my config files for reference, hopefully it helps someone:

Special interactive debug spec - interactive.e2e.ts

import { LoginPage } from './src/pages/login.po';
import { AppPage } from './src/pages/app.po';
import { SwitchProfileSideSheet } from './src/side-sheets/switch-profile-side-sheet.po';
import { sel } from '../src/testing/get-component';

const login = new LoginPage();
const app = new AppPage();
const switchProfileSideSheet = new SwitchProfileSideSheet();

// add my own page objects to the global object so I can use them interactively.
global['sel'] = sel;
global['po'] = {
  login,
  app,
  switchProfileSideSheet,
};

(global as any).systemTestsDone = new Promise(function(_resolve, _reject) {
  global['finishInteractiveDebug'] = _resolve;
});

describe('TestHelper', () => {
  it('should provide a way to interactively run tests', async () => {
    await (global as any).systemTestsDone;
  });
});

package.json

    "e2e-interactive": "node --experimental-repl-await --inspect-brk ./node_modules/.bin/protractor ./e2e/protractor.interactive.conf",

protractor.interactive.conf.js

// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts

// standard protractor config
const baseConfig = require('./protractor.conf');
const configCopy = Object.assign({}, baseConfig.config);

const oneDayInMilliSeconds = 1000 * 60 * 60 * 24;
// set timeout to a huge number
// so it's not an issue when we pause in the debugger
configCopy.allScriptsTimeout = oneDayInMilliSeconds;
configCopy.jasmineNodeOpts.defaultTimeoutInterval = oneDayInMilliSeconds;
// just load our interactive specs
configCopy.specs = ['./interactive.e2e.ts'];

console.log('interactive config', configCopy);
exports.config = configCopy;

I use browser.sleep(100000) instead of browser.pause()

Was this page helpful?
0 / 5 - 0 ratings

Related issues

gamecheck80 picture gamecheck80  ·  3Comments

vishalshivnath picture vishalshivnath  ·  3Comments

koshkarov picture koshkarov  ·  3Comments

smarts picture smarts  ·  3Comments

luakri picture luakri  ·  3Comments