-
Notifications
You must be signed in to change notification settings - Fork 198
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
Add integration test to check inter-frame communication #4090
Add integration test to check inter-frame communication #4090
Conversation
I have created three simpler tests the following three communication channels:
|
ebd8b2b
to
78a541b
Compare
This new integration test checks that `PortFinder`, `PortProvider` and `PortRPC` work in harmony. One change in one could lead to the others no working as planned.
78a541b
to
ccf9852
Compare
Codecov Report
@@ Coverage Diff @@
## master #4090 +/- ##
=======================================
Coverage 99.06% 99.06%
=======================================
Files 217 217
Lines 8170 8170
Branches 1918 1918
=======================================
Hits 8094 8094
Misses 76 76 Continue to review full report at Codecov.
|
We exchanged comments about the Please, let me know if you want me to using helper functions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the subclassing is OK for now. There are ways it could be abstracted, but the current implementation is easy enough to follow.
I had a suggestion regarding the grouping of the code that represents each of the different frames in the test, namely to split them into separate functions, to make it clear that they are meant to represent activities happening in different frames which run concurrently and don't share any state (except via a message channel).
Generally LGTM though.
assert.equal(response, 'pong'); | ||
done(); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The done
resolver could potentially be replaced by doing the portFinder.discover
call in the Promise callback:
const done = new Promise(resolve => {
portFinder.discover('host').then(port => {
hostRPC.connect(port);
hostRPC.call('ping', response => {
assert.equal(response, 'pong');
resolve();
});
});
});
...
return done;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great idea! Thanks!
}); | ||
}); | ||
|
||
await delay(10); // add some realism |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you clarify what you mean by realism here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Guest
can be ready before the Host
frame. If that's the case, Guest
will polls the Host
. I was trying to simulate that scenario.
portProvider.listen(); | ||
const guestRPC = new PortRPC(); | ||
|
||
// Register RPC method *before* connection |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest to remove these comments, and leave it to the PortRPC docs to explain that correct usage of the class requires calling on
before connect
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏼
destroyables.forEach(instance => instance.destroy()); | ||
}); | ||
|
||
it('enables the communication between guest-host', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To summarize what these tests are doing, each runs a bunch of concurrent activities that simulate the guest, host and sidebar roles in the inter-frame communication process. All the only communication between frames has to go via message channels (no shared variables). One way to make this structure more obvious might be to wrap each "actor" in a function and then run all the actors concurrently at the end.
it('enables ... communication', async () => {
const simulateGuest = async () => {
// Guest steps here
};
const simulateHost = async () => {
// Host steps here
};
return Promise.all([simulateGuest(), simulateHost()]);
});
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very good idea! Thanks!
const promise = new Promise(resolve => (done = resolve)); | ||
|
||
// guest frame; | ||
const portFinder1 = new PortFinder({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const portFinder1 = new PortFinder({ | |
const guestPortFinder = new PortFinder({ |
Alternatively, if you wrap each actor in a separate function, the variable names won't conflict.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I use separate functions.
|
||
it('enables the communication between sidebar-host', async () => { | ||
let done; | ||
const promise = new Promise(resolve => (done = resolve)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you are going to use this pattern, I'd suggest to let done
be the promise as it is a name of a state (similar to loaded
or completed
), and call the resolver resolveDone
. Alternatively, skip the resolver variable and just use the promise callback:
const done = new Promise(resolve => {
...
hostRPC.call('ping', response => { ...; resolve(); });
});
61a4721
to
dbc8c92
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I incorporated your feedback on the second commit.
destroyables.forEach(instance => instance.destroy()); | ||
}); | ||
|
||
it('enables the communication between guest-host', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very good idea! Thanks!
assert.equal(response, 'pong'); | ||
done(); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great idea! Thanks!
portProvider.listen(); | ||
const guestRPC = new PortRPC(); | ||
|
||
// Register RPC method *before* connection |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍🏼
const promise = new Promise(resolve => (done = resolve)); | ||
|
||
// guest frame; | ||
const portFinder1 = new PortFinder({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I use separate functions.
dbc8c92
to
80e009e
Compare
Co-authored-by: Robert Knight <robertknight@gmail.com>
80e009e
to
a49c51c
Compare
This new integration test checks that
PortFinder
,PortProvider
andPortRPC
work in harmony. A change in one could lead to the others noworking as planned.