Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support service launcher in standalone mode #7185

Closed
conradkirschner opened this issue Jul 26, 2021 · 10 comments
Closed

Support service launcher in standalone mode #7185

conradkirschner opened this issue Jul 26, 2021 · 10 comments
Labels
Enhancement help wanted Issues that are free to take by anyone interested

Comments

@conradkirschner
Copy link

conradkirschner commented Jul 26, 2021

Is your feature request related to a problem? Please describe.
I want to use wdio programmatically:
await remote();

Here I want to use sauce service.

Describe the solution you'd like
https://webdriver.io/docs/wdio-image-comparison-service/#running-programmatically
I want to use it like this but able to hook the services like in wdio.conf.js

example:
const browser = await remote({
logLevel: "silent",
capabilities: {
browserName: "chrome"
},
services: [['sauce', {sauceOptions}]]
});

Describe alternatives you've considered
Alternative could be a hook or better documentation

@christian-bromann
Copy link
Member

@conradkirschner services only automatically work when using the wdio testrunner. You can still use services in standalone mode by importing and initialising manually, e.g.:

  import SauceService from '@wdio/sauce-service'

  const browser = await remote({
    logLevel: "silent",
    capabilities: {
      browserName: "chrome"
    }
  });
  const sauceService = new SauceService(sauceOptions)
  await sauceService.onPrepare()

There is not much documentation which hook method does which things but you can just check out the code to see what is going on and what you need to parse in as arguments.

@conradkirschner
Copy link
Author

I raised that feature request, because I would like to wish to pass launcher services directly to remote();

Background: I integrate currently wdio in backstopJS
garris/BackstopJS#1342

To avoid to go out of sync later with BackstopJS logic, I would like to make it happen in wdio.
An extension for remote() that allows usage the services out of testrunner scope (if possible like with the example you posted) would be great.

On the other Hand I could implement this in a programmatically way, but that would mean I have to rebuild/copy stuff from wdio...

(Not sure if that is understandable, maybe that is out of scope for wdio, then implementing it in backstopjs is fine)
@christian-bromann

@christian-bromann
Copy link
Member

An extension for remote() that allows usage the services out of testrunner scope (if possible like with the example you posted) would be great.

I am not sure how this is suppose to work. In the testrunner scenario we have various of very well defined situations, e.g. before a test starts or after a worker finishes. We have none of that in the standalone world. The only thing that might work is to add support for beforeCommand and afterCommand but almost all of the services use usually other wdio hooks. It seems that backstop has its own testrunner so I recommend to integrate services in there.

@conradkirschner
Copy link
Author

Yeah, I would not go for full support.

Partly support for launcher services would be fine, as for most of them calling onPrepare (so when remote() get called?) and complete on remote() close event.

How it should work?
Like the example you published above, just that you pass service name to remote({config}) object and run onPrepare();
Doesn't look that much complicated, that's why I am asking here again.

(Worker Services)
-- > For testrunner extensions(services) I would totally agree to not support them in remote() call.
https://webdriver.io/docs/customservices/

Thanks for fast response.

@christian-bromann christian-bromann changed the title Use Services in remote() [call wdio programmatically] Support service launcher in standalone mode Jul 27, 2021
@christian-bromann christian-bromann added Enhancement help wanted Issues that are free to take by anyone interested labels Jul 27, 2021
@christian-bromann
Copy link
Member

Ok, I guess it makes sense to enable support for launcher. Some things we need to consider to do:

  • update the remote and multiremote methods to initialise services provided by the option parameter (ideally reusing the logic we have for that from the testrunner)
  • update types in @wdio/types to support services for standalone options
  • make necessary documentation changes

The problem I see is that currently the last command is deleteSession which is a protocol command where we can't add any logic, e.g. shutting down services. One option is to overwrite that command only in case we have services defined and need to tear down something.

Any contributions on this are appreciated.

@erwinheitzman
Copy link
Member

I wonder how you are expecting this to work because I too use services in a programmatic way as can be seen here https://github.com/erwinheitzman/jest-webdriverio-standalone-boilerplate and in my case I run the onPrepare method in Jest's globalSetup, however I could have set this up in different ways. Sometimes you want a service to be run once and other times it needs to run multiple times (think of before anything like in my setup, or for example on every remote instance creation).
So how would we know when to run the onPrepare? Taking the example of triggering it when the remote is instantiated, in my example that would mean that the onPrepare would run 3 times, which is not what you want because that would be like a before instead of onPrepare.
Maybe I am overlooking something so I would love to hear what you think 👍

@conradkirschner
Copy link
Author

conradkirschner commented Jul 27, 2021

very very good input, thanks for that.

I would assume that there should be a check if the service is already instantiated, calling it more then once would mean it's "onBefore call". (Kind of a small hook to a "service registry")

The onBefore call I would think belongs to the runner, any setup that is required before or with instantiation of remote() should belong to remote();
=> Launcher Serivce belongs to remote() and should called once, only if they crashed/tearDowned restarting on new remote() call?
=> Worker Service belongs to test runner and is out of scope here.

e.g. I would not start selenium-standalone-server more then once.

If I want that, I could still use the programmatically way.

// but it's late here maybe I overlooking something, for your case that would mean you could avoid the registry in global scope and use it in test scope, where you be able to choose which launcher per test(file) you want (like some with mock, some without, just with the need of load a different config in your onBefore call (https://github.com/erwinheitzman/jest-webdriverio-standalone-boilerplate/blob/03662074c76f546b87f96fd00f41b2f4897c247b/__tests__/async.ts#L7))

pretty interessted what you think about that idea

@erwinheitzman
Copy link
Member

erwinheitzman commented Jul 28, 2021

Well that's the problem, there are no hooks like you have in the wdio test runner. The reason you have the before hook and such in the wdio test runner is because we use Mocha/Jasmine/Cucumber's hooks for this.

Because WebdriverIO doesn't know anything when running programmatically, you cannot tell it to run before every test just like you would with the test runner.

Summary:

  • hooks that we control seem doable (onPrepare, onWorkerStart, etc)
  • hooks that are related to Mocha/Jasmine/Cucumber seem out of scope (before, before test, beforeScenario, etc)
  • assuming that instantiating remote multiple times would trigger the hooks multiple times as well, we could ignore it if it has already been ran before

Edit: I really appreciate this discussion and I hope this helps to shape a solution for your issue :)

@conradkirschner
Copy link
Author

conradkirschner commented Aug 1, 2021

I started but failed a bit due the fact that browser.deleteSession is not overwritable... In olden Days of JS such things where easy ...

(node:10540) UnhandledPromiseRejectionWarning: TypeError: Cannot assign to read only property 'deleteSession' of object '#<Browser>'
https://github.com/conradkirschner/webdriverio/tree/feature/remote-with-launcher-service

-> This doesn't work
https://github.com/conradkirschner/webdriverio/blob/feature/remote-with-launcher-service/packages/webdriverio/src/index.ts#L122

I would kindly ask for some help | @erwinheitzman @christian-bromann

@christian-bromann
Copy link
Member

In olden Days of JS such things where easy ...

Even in the old days you could prevent these things but it wasn't common back then.

browser.deleteSession is not overwritable

You could technically use overwriteCommand. For the core framework I don't think it is a good idea to combine service handling and commands. Therefor I suggest to build your own lib that wraps the WebdriverIO interfaces and gives you the necessary features you need. At the end of the day we build WebdriverIO also for people to extend it in their own way.

Given that @erwinheitzman and me already had concerns bringing this into the core framework I would suggest to go with the way described above. Happy to further assist.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement help wanted Issues that are free to take by anyone interested
Projects
None yet
Development

No branches or pull requests

3 participants