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

Proof of concept: calling remote interactors #178

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft

Conversation

jnicklas
Copy link
Collaborator

@jnicklas jnicklas commented Jan 29, 2022

Depends on #166

I've been unable to knock this idea out of my head. So my weekend hack was to try and see if I could actually make it work. And it kinda sorta works, with a lot of caveats! But I think it proves that the idea itself is fundamentally interesting.

Background

One of the big missing pieces of BigTest and Interactors is that Interactors currently need to be running in the same process as the test runner. This limits us a lot in terms of how interactors can be used. For example we can never have the test runner and the page under test be on different origins, which is very limiting. In many cases, calling interactor directly is good, but in some cases, it would be better to have a request/response cycle for this.

Implementation

This uses the addInteractionWrapper API to make it possible to call interactors running in a different process. Basically when writing your test, you would use interactors as you normally would, but instead of running them in the current process, the interaction is serialized and sent over a websocket connection running in another process (could be a browser!).

Try it out!

Start the server:

cd packages/remote
yarn ts-node example/server.ts

Then run the client:

cd packages/remote
yarn ts-node example/client.ts

You should see output like this:

Screenshot 2022-01-29 at 13 20 32

Note that "Some Link" is rendered in a JSDOM context running in the server!!!

Limitations

  • The implementation of the interactor must match between the client and server for this to behave as expected.
  • Multiple interactors must not have the same name
  • The server is currently running a websocket server, which is limiting since we want it to run in a browser. It should be running a websocket client as well.
  • Composed interactors are not yet implemented (but should be trivial)
  • It does not support matchers
  • It's generally a hacky pile of jank. This is not production grade stuff at all. There are any number of edge cases which will cause this to very much blow up.

@changeset-bot
Copy link

changeset-bot bot commented Jan 29, 2022

⚠️ No Changeset found

Latest commit: cdb1e6e

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@netlify
Copy link

netlify bot commented Jan 29, 2022

Deploy Preview for interactors canceled.

Name Link
🔨 Latest commit cdb1e6e
🔍 Latest deploy log https://app.netlify.com/sites/interactors/deploys/62553ffabf96e90009f2b856

@wKich
Copy link
Member

wKich commented Feb 4, 2022

@jnicklas @cowboyd I have an idea how we can bypass the first two limitations. When we get interaction in our wrapper we calculate hash from interaction name, available filters/actions, default filters values. So it's like duck typing. And do the same thing on a client for all imported interactors.

@cowboyd
Copy link
Member

cowboyd commented Feb 9, 2022

@jnicklas @cowboyd I have an idea how we can bypass the first two limitations. When we get interaction in our wrapper we calculate hash from interaction name, available filters/actions, default filters values. So it's like duck typing. And do the same thing on a client for all imported interactors.

@wKich Interesting! I think we would also need to check the arity of the action functions too, right?

@cowboyd
Copy link
Member

cowboyd commented Mar 8, 2022

This is relevant to support Playwright #191 which has its own protocol for referencing and interacting with objects in a remote page. Maybe some abstraction could be made?

@wKich
Copy link
Member

wKich commented Mar 14, 2022

Yeah, I already thought about that. But actually for the playwright we can have another solution.

We can add function exposer, ask user to put all his interactors there. That exposer exposes interactors in global namespace, so they will be available through window.Button for example or window.__INTERACTORS__.Button. Then we create helpers for the playwright, like cy.do or cy.expect in these helpers we just need to get code representation and call page.evaluate() with exposed interactors. The problem is you can't pass non-serializable things as well as in this spike.

@cowboyd
Copy link
Member

cowboyd commented Mar 15, 2022

The problem is you can't pass non-serializable things as well as in this spike.

We would need a similar mechanism for matchers

@wKich
Copy link
Member

wKich commented Mar 22, 2022

@cowboyd, yeah, we missed that point

@@ -48,6 +49,7 @@
"resolutions": {
"@definitelytyped/typescript-versions": "^0.0.40",
"@typescript-eslint/eslint-plugin": "^4.12.0",
"@effection/core": "^2.2.0",
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Unfortunately we get a version mismatch for @effection/core here unless we provide this explicit resolution. I think this might be a deeper problem in how the semver constraints in effection are set up, but I'm not sure.

@jnicklas
Copy link
Collaborator Author

Since the effection branch was merged (yay!), I've rebased and updated this PR. I've also extracted #197 out of this as a generally sensible thing to do, which shows how remote interactors can really be implemented on top of our existing interactors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants