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

[🐛 Bug]: launchChrome() adds -- before every arg, making it impossible to pass positional args to electron #12128

Closed
3 tasks done
lerouxb opened this issue Jan 30, 2024 · 12 comments
Labels
Bug 🐛 Needs Triaging ⏳ No one has looked into the issue yet

Comments

@lerouxb
Copy link

lerouxb commented Jan 30, 2024

Have you read the Contributing Guidelines on issues?

WebdriverIO Version

latest

Node.js Version

latest

Mode

Standalone Mode

Which capabilities are you using?

capabilities: {
      browserName: 'chromium',
      'goog:chromeOptions': {
        binary: '/some/path',
        args: ['mongodb://whatever'], // this is forced by webdriverio to become --mongodb://whatever
      },
}

What happened?

Electron happens to be node, so you can allow your app's executable to be used as a CLI by advanced users. Or for it to be scriptable.

Our app allows you to pass a connection string on the command-line and then it would automatically connect to that database. Then administrators can set up a script or shortcut or whatever for their users.

But this is made impossible to test because launchChrome() prepends -- to every arg that doesn't already have it here:

const chromeOptionsArgs = (chromeOptions.args || []).map((arg) => (
arg.startsWith('--') ? arg : `--${arg}`
))

What is your expected behavior?

To be able to pass positional args to chromium, ie. electron. Maybe at least a way to disable this behaviour?

How to reproduce the bug.

    capabilities: {
      browserName: 'chromium',
      'goog:chromeOptions': {
        binary: '/some/path',
        args: ['mongodb://whatever'],
      },
}

Relevant log output

In the app that it is passed as `--mongodb://whatever`:


[
    '/Users/leroux.bodenstein/mongo/compass/node_modules/electron/dist/Electron.app/Contents/MacOS/Electron',
    '--allow-pre-commit-input',
    '--app=/Users/leroux.bodenstein/mongo/compass/packages/compass',
    '--atlasServiceBackendPreset=atlas-dev',
    '--disable-background-networking',
    '--disable-background-timer-throttling',
    '--disable-backgrounding-occluded-windows',
    '--disable-breakpad',
    '--disable-client-side-phishing-detection',
    '--disable-component-extensions-with-background-pages',
    '--disable-default-apps',
    '--disable-dev-shm-usage',
    '--disable-extensions',
    '--disable-features=site-per-process,TranslateUI,BlinkGenPropertyTrees',
    '--disable-gpu',
    '--disable-hang-monitor',
    '--disable-ipc-flooding-protection',
    '--disable-popup-blocking',
    '--disable-prompt-on-repost',
    '--disable-renderer-backgrounding',
    '--disable-sync',
    '--enable-automation',
    '--enable-features=NetworkService,NetworkServiceInProcess',
    '--enable-logging',
    '--force-fieldtrials=*BackgroundTracing/default/',
    '--ignore-additional-command-line-flags',
    '--log-level=0',
    '--media-router=0',
    '--metrics-recording-only',
    '--mongodb://localhost:27091/test',
    '--mute-audio',
    '--no-default-browser-check',
    '--no-first-run',
    '--no-sandbox',
    '--no-service-autorun',
    '--password-store=basic',
    '--remote-debugging-port=0',
    '--test-type=webdriver',
    '--use-mock-keychain',
    '--user-data-dir=/var/folders/gh/r8_dbd8s6mj6v_f60zz0bmr00000gp/T/user-data-dir-1hldaq68b-1'
  ]

Code of Conduct

  • I agree to follow this project's Code of Conduct

Is there an existing issue for this?

  • I have searched the existing issues
@lerouxb lerouxb added Bug 🐛 Needs Triaging ⏳ No one has looked into the issue yet labels Jan 30, 2024
@christian-bromann
Copy link
Member

Any reason you are using the devtools package here rather than the WDIO testrunner with the Electron service? We have been deprecating the devtools automation package and will remove it in v9. The WebDriver protocol is the better alternative here using getPuppeteer for CDP access.

That said, feel free to raise a PR with a bug fix but ultimately my recommendation is to remove the automationProtocol option and use WebDriver for this. Wdyt?

@lerouxb
Copy link
Author

lerouxb commented Jan 31, 2024

I can't fit what I'm doing here into a testrunner. I want a script that uses a browser automatically and to me the benefit of webdriverio is that it is a library that I can use to do const browser = await getMeABrowser(blah) and it manages getting chromedriver, geckodriver or whatever set up and then returns an object that I can use to remote control a browser with some convenience methods on that browser object and on element objects that papers over some differences and makes it easy, idiomatic and convenient to make the browser (or electron app) do things and return stuff.

In a sense I could use puppeteer, but that's chrome only and I've had no luck getting that to work with electron cross-platform over the years. Similar thing with playwrite - probably a good reason electron took that out of their recommendations on their website. I could use the webdriver protocol manually, but then I still have to duplicate a lot of code that's already done in webdriverio.

It is your project and I can't and don't want to tell you what you should be doing with it, but it feels like webdriverio shouldn't (primarily) be a testrunner. There are already lots of test runners. Is there a library that just does what I outlined above? Maybe I'm misunderstanding and there's already a better thing in webdriverio I can use programmatically (ie not via a wdio config file) that I can use to do this?

I've looked at the wdio.conf.ts way again (just ran through the latest version's getting started to get back up to speed) and I think the main thing that I'm missing is that I need to be in full control of the lines of code that create and close the browser. We have test cases that start and close the app multiple times in one test, for example. Or we control two copies at once. One could even be the electron app, one the browser one. The configuration for what we're starting the electron app with is totally variable because we test with different startup options or env vars set, that sort of thing. Just very tricky to do that in a static configuration and without control of the lifecycle.

In short: Will there be a way to use webdriverio v9 onwards where browser is not a global variable?

@lerouxb
Copy link
Author

lerouxb commented Jan 31, 2024

ultimately my recommendation is to remove the automationProtocol option and use WebDriver for this.

I'm not following. I don't have automationProtocol set. Does that default to puppeteer? I'm pretty sure the default is webdriver and I'm already using webdriver there. I also don't have the devtools package installed which the documentation seems to imply would be required: https://webdriver.io/docs/configuration/#automationprotocol

@lerouxb
Copy link
Author

lerouxb commented Jan 31, 2024

Oh the code that adds the -- I linked to is in the devtools package. I don't understand why that's being added, then. I'll have to do some more debugging. I can't immediately find any other places where the chrome args are messed with..

@lerouxb
Copy link
Author

lerouxb commented Jan 31, 2024

I'm stumped. I've set automationProtocol to 'webdriverio' explicitly and everything still works as expected (which it should because I was already using the webdriverio protocol) so in theory that packages/devtools code shouldn't be hit yet something is still prepending -- to every chrome arg that doesn't already have it.

@lerouxb
Copy link
Author

lerouxb commented Jan 31, 2024

I never figured out what's changing the args, but I found a workaround: I'm pointing binary to a shell script that executes electron with the extra positional args I want.

I suppose if I run into problems I can't work around with remote() I could cobble together my own using wdio-utils (to start webdriver) and wdio-protocols (to get the browser & element objects).

@christian-bromann
Copy link
Member

@lerouxb thanks for your feedback.

I remember we had a conversation before on this which let me to raise #12091. Running with the testrunner has for us the advantage that we can easily tap into a lot of hooks that help us manage the state of the integration between Electron and the browser instance. I totally get that you like to be able to use it without it so I created this issue: webdriverio-community/wdio-electron-service#412

It is your project and I can't and don't want to tell you what you should be doing with it, but it feels like webdriverio shouldn't (primarily) be a testrunner. There are already lots of test runners. Is there a library that just does what I outlined above

It's not my project either 😉 We certainly don't want to dictate how you should use WebdriverIO however as mentioned before the plugins currently require the testrunner context to access all the various hooks available. It seems like the Electron service could life without the testrunner but other service can't as they expect a test lifecycle.

Maybe I'm misunderstanding and there's already a better thing in webdriverio I can use programmatically (ie not via a wdio config file) that I can use to do this?

You can run webdriverio programmatically and call all the service and launcher hooks yourself. It is a bit hacky which is why I raised the issue above.

I think the main thing that I'm missing is that I need to be in full control of the lines of code that create and close the browser. We have test cases that start and close the app multiple times in one test, for example. Or we control two copies at once.

You can do this in the testrunner context too, as you can spin up more instances using the remote command within a testrunner test. Restarting the application with different parameters is possible after we landed the improvements on the reload command.

In short: Will there be a way to use webdriverio v9 onwards where browser is not a global variable?

Making browser a global variable is just a convenience for users, you can already disable this in v8. The testrunner will always manage starting the browser for you based on the configuration capabilities and I think this is a good think and what most users want to do. You have some interesting and not unusual use cases that we can work on improving to make it possible within the testrunner. You totally can run your own setup.

I'm not following. I don't have automationProtocol set. Does that default to puppeteer?

You have been pointing to a code line in the devtools package which we run when you have automationProtocol set to "devtools".

I can't immediately find any other places where the chrome args are messed with..

It is possible that Chromedriver messes with it since you can pass in these args with -- and without and it both works.

I'm stumped. I've set automationProtocol to 'webdriverio' explicitly

webdriverio is not a valid value for automationProtocol. It should be either webdriver or devtools.

@lerouxb
Copy link
Author

lerouxb commented Feb 1, 2024

webdriverio is not a valid value for automationProtocol. It should be either webdriver or devtools.

yes sorry - typo in this comment. It is 'webdriver' and I'm pretty sure of that because TypeScript would complain loudly ;)

I also suspected that it might be chromedriver messing with the args, but haven't been able to prove it yet. My workaround of pointing binary to a script seems to work, though.

One other use case I thought of: Suppose you just want to write a script that uses a browser to sign in and click around a finicky site so you can pull some data out of a page. Or just use a weird UI programmatically in a cron job to click a button. It makes sense to me to be able to use webdriver plus the plugins programmatically.

Btw, I don't know if multi-remote is what I'm looking for. I might want different browsers or electron in series or multiple of the same one at once. (ie. I do something in one browser and then something appears as a result in another). Or I export a user's data in the browser, then start up another one with a new fresh user data directory to be sure it is a different new user with no data on disk (probably an electron app being tested) and then import that data there.

Also not sure about reconfiguring. You'd start an electron browser with some set of ENV vars and command line args only to immediately throw it away and start another one with a different setup and args? Seems less than ideal and more complicated than just creating a client with a customised options parameter.

@christian-bromann
Copy link
Member

I might want different browsers or electron in series or multiple of the same one at once.

Yes, that is exactly that kind of scenario multiremote was build for. The thing is that you define its capabilities once for your whole suite and don't have much freedom adding a browser or removing one sometime within a test.

Seems less than ideal and more complicated than just creating a client with a customised options parameter.

What kind interface or ideal workflow do you have in mind?

@lerouxb
Copy link
Author

lerouxb commented Feb 2, 2024

I think keep the frameworky parts as it is, but just make it so that you can also use everything via a function like remote(). ie. make all the services/plugins usable from there. Then someone can still write a script like:

#!/usr/bin/env node

const { remote } = require('webdriverio');

async function run() {
  const browser = await remote(/* everything needed to connect to electron or chrome or firefox or whatever */);
  // do stuff with browser or browser.electron or whatever here
}

run().then(() => console.log('done')).catch((err) => console.error(err));

(Didn't test that, but hopefully you get the idea.)

Then users can still use wdio.conf.js or they can use webdriverio from a script or they can plug it into whatever weird edge use case they want. I imagine that would require some refactoring but is hopefully doable.

@goosewobbler
Copy link
Contributor

goosewobbler commented May 8, 2024

@lerouxb FYI we released a standalone mode for the Electron Service in 6.5.0 based on this conversation.

@lerouxb
Copy link
Author

lerouxb commented May 8, 2024

@goosewobbler That's nice! Checking it out. Thanks for the ping.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug 🐛 Needs Triaging ⏳ No one has looked into the issue yet
Projects
None yet
Development

No branches or pull requests

3 participants