Open davej opened 8 years ago
The parameters to spectron helpers must be JSON serializable since they are sent remotely to ChromeDriver.
So passing a function to app.electron.ipcRenderer.on
will not work correctly since it can not be serialized. This limitation needs to be explained better in the docs.
This specific API could be probably be addressed via something like #47 though
@kevinsawicki I have tried to do it in the way you did it in https://github.com/electron/spectron/pull/47 but with no luck.
t.context.app.client.executeAsync(function (requireName, done) {
var ipc = window[requireName]('electron').ipcRenderer;
ipc.on('localStorage__getAll___response', function () {
console.log('yep');
done('yhy');
});
}, t.context.app.api.requireName).then(res => console.log('output', res.value));
await app.electron.ipcRenderer.send('localStorage__getAll');
await wait(5000);
console.log(await app.client.getMainProcessLogs());
console.log(await app.client.getRenderProcessLogs());
Output:
[ '',
'getall received',
'getall answered',
'[42740:1026/164502:INFO:CONSOLE(5)] "yep", source: (5)' ]
[]
√ test » getAll (10.8s)
Unhandled Rejection: tests\functional\test.js
Error: asynchronous script timeout: result was not received in 5 seconds
execute(<Function>, "ipcRenderer", "send", localStorage__getAll, "require") - D:/projekty/meteor-desktop-localstorage/node_modules/spectron/lib/api.js:223:21
You can see that console.log('yep')
was called in the renderer logs. So the done
callback was called for sure. Why is it complaining about not receiving result for ipcRenderer", "send
. Without the part with t.context.app.client.executeAsync
it does not complain though.
It seems like it would mix those two - I mean that doing app.electron.ipcRenderer.send
influences somehow executeAsync
.
Ok, I have managed to work it out differently by sending and waiting response in the same executeAsync
.
Here is what I've worked out so far, works well and I will probably leave it at this:
t.context.app.client.addCommand('sendIpcAndWaitForResponse', function async(requireName, eventToSend, eventArgs, eventToListenTo) {
return this.executeAsync(function ($requireName, $eventToSend, $eventArgs, $eventToListenTo, done) {
const ipc = window[$requireName]('electron').ipcRenderer;
ipc.once($eventToListenTo, function eventCallback() {
done(Array.prototype.slice.call(arguments));
});
$eventArgs.unshift($eventToSend);
ipc.send.apply(ipc, $eventArgs);
}, requireName, eventToSend, eventArgs, eventToListenTo);
});
const result = await t.context.app.client
.sendIpcAndWaitForResponse(
t.context.app.api.requireName,
'ipcEventToSend',
["some", "args", "to", "send"],
'ipcEventToListenTo'
);
@kevinsawicki if you want I can add a PR with waitForIpcEvent
and sendIpcAndWaitForResponse
- just let me know and please point me to correct file in which this could be defined.
Easiest explained with code:
In the main process:
In Spectron:
The
ping
gets received by the main process and it sends thepong
without error but thepong
never gets received in Spectron.The synchronous version seems to work ok in Spectron (you just need to unwrap the promise). The following works ok: