4

I want to move appart from the selenium control flow in my Protractor tests.

Here are the steps and problems I went through so far:

1. Disable it test by test

My first idea was to use SELENIUM_PROMISE_MANAGER in order to move from selenium promises to async/await code.

Unfortunately, I found no way to put one test to SELENIUM_PROMISE_MANAGER=0 while keeping others to SELENIUM_PROMISE_MANAGER=1 in order to do the migration smoothly.

2. Keep it but use async/await too

So I thought about a code using async/await while keeping SELENIUM_PROMISE_MANAGER=1.

Unfortunately it seems not to be compatible: https://github.com/angular/protractor/tree/master/exampleTypescript/asyncAwait

There is nothing about such issue on Selenium side so I am wondering if this is an advice or a real it always fails.

3. Override promise.USE_PROMISE_MANAGER

Using protractor.promise.USE_PROMISE_MANAGER=false does not work for me (in beforeEach).

4. Call the control flow on async code

protractor.promise.controlFlow().execute(/* my async code*/);

For me it seems to mix async/await to control flow...

What is the right strategy?

I am wondering, what is the right strategy to move to async/await in Protractor tests?

I don't want to put everything in async/await in one change but to spread the change in multiple small changes

DubZzz
  • 145
  • 2
  • 8
  • Reading the [full thread here about the deprecate issue](https://github.com/SeleniumHQ/selenium/issues/2969) seems pretty straight forward. You'll need to enable async/await via command line (check Feb, 4th). So, why do you think it's incompatible and what error do you get? – Ernst Zwingli Oct 10 '17 at 06:38
  • 1
    My problem is that Protractor guide explicitely says "However, you cannot use a mix of async/await and the control flow" and I haven't found any way to move only parts of the tests to async/await and not others. – DubZzz Oct 10 '17 at 07:50

1 Answers1

1

Incompatible, because

Read all about in this issue here.

As it's very technical, the way I (as relatively untechnical guy) understood it, is that jasminewd2, protractor and webDriver incl. ControlFlow are not designed to handle a mix of native promises and managed promises. It handle only managed promises and such are created by many jasminewd2-commands. However, async/await creates native promises and pushes it into the ControlFlow, which ends in a mix of both promises type and it all ends up with heavy timing issues. It can't be resolved as the ControlFlow works as expected and as it was designed for. The situation with async/await was never part of the ControlFlow design.

Switching off the ControlFlow to me means, managed promises get ignored. But because of async/await any managed promise would be wrapped inside a native promise and therefore it doesn't matter, that managed promises get ignored as you keep track of all asynchronous tasks already by tracking native promises only.

How to test both, migrated and not yet migrated test cases

Create two separate conf.js (or whatever your config file is named) and keep them separated. If you have common parts, i.e. helper functions, also migrate those and potentially keep the un-migrated as a duplicate as well. (create to .js-files or use a boolean-indicator to execute either or)

@DubZzz found a possible trick to move smoothly to async / await. His trick is to convert helpers using async / await and call them in protractor.promise.controlFlow().execute. Then move test by test and finally remove controlFlow execute and flag.

For Migration these links I can provide:

The official introduction and migration guide

A similar question witha well documented answer

A good blog about async/await and promises

The official thread about deprecate promise Manager. It also contains helpful information in how to make async/await work.

Ernst Zwingli
  • 1,402
  • 1
  • 8
  • 24
  • Thanks a lot for the link, I already had a look to the official migration guide given by selenium. Nonetheless I don't see how it (Option 3: Migrate to async/await) can be applied to Protractor. I haven't found anyway to set promise.USE_PROMISE_MANAGER to false for some specific tests only. – DubZzz Oct 10 '17 at 07:47
  • Thanks for your comment. I indeed misread that. Why don't you just create a second `conf.js` file, in which you list the `specs` you want to test with disabled Promise Manager? That should by far be the easiest. And you can keep track of which tests you migrated within the config-file itself as well. – Ernst Zwingli Oct 10 '17 at 07:57
  • Indeed it would be great. The problem is that those tests are sharing some helpers. Those helpers rely on selenium control flow. – DubZzz Oct 11 '17 at 07:21
  • 1
    I think I found a possible trick to move smoothly to async / await but I still don't know what are the real problems behind 'do not mix control flow and javascript promises'. My trick would be to convert helpers using async / await and call them in protractor.promise.controlFlow().execute. Then move test by test and finally remove controlFlow execute and flag. – DubZzz Oct 11 '17 at 07:29
  • It sounds reasonable. As you'll need to migrate the `helpers` function anyway, so I'd assume it needs to be done in any case. About the question why it all is not compatible I suggest [reading this issue here](https://github.com/seleniumhq/selenium/issues/3037), though it's highly technical. Highly simplified: `async / await` creates native promises, while protractor/webdriver deals with managed promises. Because `async/await` pushes native promises via `jasminewd2` into `ControlFlow` it gets messy. It was never designed for that. I edited my answer to match with the results of our comments. – Ernst Zwingli Oct 11 '17 at 19:11
  • @DubZzz Thank you for accepting my answer as the correct one. I added your trick to it (with reference to you) to complete the answer now. – Ernst Zwingli Oct 13 '17 at 08:01