Skip to content

Add dynamic require for driver plugins#1919

Merged
rotemmiz merged 19 commits intowix:masterfrom
ouihealth:aw-driver-plugin
Apr 22, 2020
Merged

Add dynamic require for driver plugins#1919
rotemmiz merged 19 commits intowix:masterfrom
ouihealth:aw-driver-plugin

Conversation

@awinograd
Copy link
Copy Markdown
Contributor


Description:

This PR adds support for external drivers as discussed in #1882 (comment).

"ios.sim.release": {
        "binaryPath": "...",
        "build": "...",
        "type": "my-custom-driver-package-name",
        "device": {
	  // can be pretty flexible (according to the device driver), add whatever device specification needed
        }
      },

@awinograd awinograd requested a review from rotemmiz as a code owner February 20, 2020 16:19
await this._client.connect();

const DeviceDriverClass = DEVICE_CLASSES[this._deviceConfig.type];
const DeviceDriverClass = DEVICE_CLASSES[this._deviceConfig.type] || require(this._deviceConfig.type);
Copy link
Copy Markdown
Contributor Author

@awinograd awinograd Feb 20, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing I don't like about this direct fallback to require is you get a weird error about module resolution if you have a typo for one of the built-in drivers. In other words, the if on the line below is sort of useless...

@rotemmiz, what are your thoughts about requiring third party drivers to be prefixed in the configuration?

Something like:

"ios.sim.release": {
        "binaryPath": "...",
        "build": "...",
        "type": "plugin:my-custom-driver-package-name",
        "device": {
	  // can be pretty flexible (according to the device driver), add whatever device specification needed
        }
      },
    let DeviceDriverClass = DEVICE_CLASSES[this._deviceConfig.type];
    if (!DeviceDriverClass) {
      if (this._deviceConfig.type.startsWith('plugin:')) {
            DeviceDriverClass = require(this._deviceConfig.type);
      }
      throw new Error(`'${this._deviceConfig.type}' is not supported`);
    }

@awinograd
Copy link
Copy Markdown
Contributor Author

One other thing that would be great to resolve as part of this PR is the binaryPath issue discussed in #1882 (comment).

Essentially, I want a way to avoid this line which is currently mandatory but doesn't make sense in the context of a website which doesn't have a binaryPath. (Currently I'm using binary path to specify the base web url but have to add a leading / to make it absolute and avoid this logic. e.g. /https://example.com)

this._binaryPath = this._getAbsolutePath(this._deviceConfig.binaryPath);

@rotemmiz
Copy link
Copy Markdown
Contributor

rotemmiz commented Mar 1, 2020

Re binaryPath, let's make sure it is only used where needed (push it into the drivers maybe).
We can introduce appPath in Device instead, that will be used for binaryPath in iOS/Android drivers, and for url in your driver.
WDYT?

@awinograd
Copy link
Copy Markdown
Contributor Author

@rotemmiz thanks for the direction. I just pushed a commit that pushes absolute path logic into the driver layer (removing from device).

I wasn't sure exactly how you wanted me to handle binaryPath vs appPath

Did you want to totally remove binaryPath as an option from the config (a breaking change)?

Or add a new appPath field to config that takes precedence over and deprecates binaryPath for future removal.

In the grand scheme of things, it's currently not a huge issue to keep the binaryPath naming even though it perhaps isn't as accurate for my web driver, so I'm also happy to punt on that until the next major version is on its way.

Let me know how you'd like to proceed!

@rotemmiz
Copy link
Copy Markdown
Contributor

rotemmiz commented Mar 8, 2020

Hey @awinograd, seems like a few unit tests failed, and coverage is missing as well.

@awinograd
Copy link
Copy Markdown
Contributor Author

@rotemmiz, tests + coverage fixed

@rotemmiz
Copy link
Copy Markdown
Contributor

Hey @awinograd, sorry for the delay here, I was trying to think and consult on how to proceed here.
So the things we think are still missing to make sure we handle this PR correctly are the following:

  1. A new section in documentation, explaining how to create such a plugin, and most importantly, a section about how to use one.
  2. A good integration test to make sure we don't break this on the next commit we make for Detox. So I suggest you add another project (either in examples dir on someplace else, but we just need to make sure it runs in CI as well), and add a very simple setup (a package.json, short e2e test, and an empty stub of a driver that just returns resolved promises on anything).

WDYT?

@awinograd
Copy link
Copy Markdown
Contributor Author

awinograd commented Mar 11, 2020

@rotemmiz no need to apologize! I appreciate your guidance through the PR process.

  1. Yes I can write up a doc on custom drivers
  2. Do you want me to configure the setup on jenkins, or would a script in examples/custom-driver/package.json be sufficient for you to take it and get it on jenkins?

@rotemmiz
Copy link
Copy Markdown
Contributor

Although it makes little sense to add the project to one of the platform specific test project CI builds, I believe it will be the fastest and easiest, and you'll be able to do it independently.

Try adding your new project to the list here, and see
https://github.com/wix/Detox/blob/master/scripts/demo-projects.android.sh

Need to maintain 100% coverage while not breaking prepare for drivers
whose binaryPath isn't an actual path on disk
@awinograd
Copy link
Copy Markdown
Contributor Author

@rotemmiz, sorry for the delay in getting back to this. I just pushed an example project (🤞 that the CI passes!)

Still need to work on the Doc, but wanted you to take a look at f014adc as I'm not happy with what i've done there. It's related to our discussion above (#1919 (comment)) about binaryPath. The old testing code assumes that prepare will throw if the binary path doesn't exist on disk which is an issue when binaryPath is a URL. I wasn't sure what the best path forward is, so just pushed something that passes but is sort of a hacky workaround. Open to suggestions there

@awinograd
Copy link
Copy Markdown
Contributor Author

Just put up a first pass at a new Guide around Third party drivers. I'm curious to know what areas you think may be interesting to include that i've left off. As of now, it's a pretty high level summary.

@awinograd
Copy link
Copy Markdown
Contributor Author

The CI is failing due to

19:05:05 /home/jenkins/.jenkins/workspace/detox-demo-projects-android-59-9-pr/examples/demo-puppeteer/node_modules/puppeteer/.local-chromium/linux-722234/chrome-linux/chrome: error while loading shared libraries: libXss.so.1: cannot open shared object file: No such file or directory

I see two potential solutions:

  1. Install the missing package(s)
  2. Change the demo to use a trivial, noop driver rather than detox-puppeteer

Let me know which direction you prefer. If it's (1), I'll need help

@awinograd
Copy link
Copy Markdown
Contributor Author

I went ahead an chose path (2) since it seemed like simplest way to test the actual integration without worrying about the internal plugin details. If you'd like to go down path (1) and restore examples/demo-puppeteer let me know. It's just a simple revert away

@awinograd
Copy link
Copy Markdown
Contributor Author

Most recent test failure seems unrelated to my changes

@rotemmiz
Copy link
Copy Markdown
Contributor

rotemmiz commented Apr 1, 2020

Good call going with 2, we wouldn't want detox CI to be more complex than what it already is, this demo you added is there only to showcase the API and make sure we don't break it unintentionally

@rotemmiz
Copy link
Copy Markdown
Contributor

rotemmiz commented Apr 1, 2020

Though the first error is probably not related (couldn't found the cause scrolling with my phone), the second (in demo projects build) looks related to your work

@awinograd
Copy link
Copy Markdown
Contributor Author

I see a new coveralls ci process has been added to the PR and has failed. https://coveralls.io/builds/29961248

Should I be paying attention to it?

@noomorph
Copy link
Copy Markdown
Collaborator

@awinograd, thanks for telling. I'll look into it.

Copy link
Copy Markdown
Contributor

@rotemmiz rotemmiz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect documentation writing (Expect for a small terminology note), Kudos.
I added a few notes, and we're checking why CI fails, bare with us, we will merge this ASAP.

const device = schemeDevice(configurationsMock.pathsTests, configuration);

await device.prepare();
await device.prepare({ checkBinaryPath: true });
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems to me like checkBinaryPath doesn't really belong in here, is there any function call without checkBinaryPath:true ?
If this is to separate the web driver from iOS/Android drivers, then maybe this logic should reside in the drivers themselves.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not ecstatic about how I had to get the tests passing. If I remember correctly, I was fighting against code coverage, but perhaps the real solution is to add a separate test for getAbsoluteBinaryPath

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So does this mean you can get rid of checkBinaryPath: true?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry I missed this reference. yes we can get rid of it

await device.installApp('newAppPath');

expect(driverMock.driver.installApp).toHaveBeenCalledWith(device._deviceId, 'newAppPath', undefined);
expect(driverMock.driver.installApp).toHaveBeenCalledWith(device._deviceId, 'newAppPath', device._deviceConfig.testBinaryPath);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did this change from undefined to testBinaryPath ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Previously this expectation was relying on implementation details of the Device class. Specifically, it knew that testBinaryPath was not passed along to newAppPath if prepare has not yet been called. That's because previously, the binary path instance properties were set on the instance during prepare after doing the absolute path logic I have pushed down into the driver layer.

That seemed a bit odd to me, since in all real uses of Device (as far as I'm aware) prepare will always be called before using the other methods. This method expects the testBinaryPath as the last argument, it just previously happened to not be defined yet

@@ -0,0 +1,62 @@
# Third Party Drivers

Detox comes with built-in support for running on Android and iOS by choosing a driver type in your detox configurations. For example, the following configuration uses the "ios.simulator" driver.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"as of v16.(3?)"
We need to remember to add it

@awinograd
Copy link
Copy Markdown
Contributor Author

@rotemmiz thanks for the review! I've done a first pass at addressing your comments

@awinograd awinograd requested a review from rotemmiz April 15, 2020 14:29
@rotemmiz
Copy link
Copy Markdown
Contributor

Can't yet understand why all builds failed, I will try figuring it out tomorrow morning.
Also, do we still need the checkBinaryPath flag in function calls?

@awinograd
Copy link
Copy Markdown
Contributor Author

@rotemmiz just updated the PR to remove the remaining reference to checkBinaryPath. unit tests are passing locally for me.

thanks for taking a look at the remaining failures.

@noomorph
Copy link
Copy Markdown
Collaborator

@awinograd, the issue with Coveralls was finally solved - could you please merge master in?

@awinograd
Copy link
Copy Markdown
Contributor Author

@noomorph . Sure thing. Just merged master

@awinograd
Copy link
Copy Markdown
Contributor Author

Coveralls ran but failed here.

Jenkins CI is green again!

@noomorph
Copy link
Copy Markdown
Collaborator

@awinograd, thanks for reporting. I have found why the coverage was below 70ish% and pushed the fix. Could you please merge master again? Now it should pass the required coverage.

@awinograd
Copy link
Copy Markdown
Contributor Author

merged!


// This will post which device has assigned to run a suite, which can be useful in a multiple-worker tests run.
// This is strictly optional.
jasmine.getEnv().addReporter(assignReporter);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@noomorph another thing to keep up to date with respect to jasmine deprecation

@awinograd
Copy link
Copy Markdown
Contributor Author

Anything else I can do here?

@rotemmiz rotemmiz merged commit c878093 into wix:master Apr 22, 2020
@rotemmiz
Copy link
Copy Markdown
Contributor

🥳

@awinograd
Copy link
Copy Markdown
Contributor Author

Amazing! Thanks for all of your help getting this change developed & merged! Excited to see it released officially 🎊

@rotemmiz
Copy link
Copy Markdown
Contributor

Thank you for having such persistency in having this PR perfected.
We are happy this change is in.

@d4vidi
Copy link
Copy Markdown
Contributor

d4vidi commented Apr 23, 2020

W00t! Don't forget to bump a minor version for the next release :)

@justinwyer
Copy link
Copy Markdown

Amazing stuff @awinograd this is super stuff 😍thanks so much for driving this!

@lock lock bot locked as resolved and limited conversation to collaborators May 5, 2020
@d4vidi
Copy link
Copy Markdown
Contributor

d4vidi commented Jul 19, 2020

@awinograd @justinwyer please be advised that we're about to introduce a minor yet breaking change to the plugged-in drivers in #2214. The change it subtle and we will report the details in the release itself, but it will not be release as a major version.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants