I created an electron application that initiates a launcher window (in a renderer process) first, which then starts multiple background services. Once these background services are successfully started, it sends the message "services-running"
on its ipcRenderer
back to the main process. The main process responds by closing the launcher window and opening the main application window. The event is handled by
ipcMain.on('services-running',...)
I have already unit tested all the handlers individually and now I want to conduct integration tests on the events that pass through ipcMain
.
Here is the current structure of my integration test:
import { Application } from 'spectron';
import * as electron from "electron";
import { expect } from 'chai';
import * as chai from 'chai';
import * as chaiAsPromised from 'chai-as-promised';
let app: Application;
global.before(() => {
app = new Application({
path: "" + electron,
args: ["app/main.js"],
env: {
ELECTRON_ENABLE_LOGGING: true,
ELECTRON_ENABLE_STACK_DUMPING: true,
NODE_ENV: "integrationtest"
},
startTimeout: 20000,
chromeDriverLogPath: '../chromedriverlog.txt'
});
chai.use(chaiAsPromised);
chai.should();
});
describe('Application', () => {
before('Start Application', () => {
return app.start();
});
after(() => {
if(app && app.isRunning()){
return app.stop();
}
});
it('should initiate the launcher', async () => {
await app.client.waitUntilWindowLoaded();
return app.client.getTitle().should.eventually.equal('Launcher');
});
it('should start all services without timing out', async (done) => {
console.log('subscribed');
app.electron.remote.ipcMain.on('services-running', () => {
done();
});
});
});
The initial test passes successfully. However, the second test fails after reaching the timeout despite the event being triggered (as indicated by the 'subscribed' log output).
According to the documentation, the nodeIntegration
needs to be enabled in order to access the complete electron API with spectron. While all my renderer processes have {nodeIntegration: true}
in their respective webPreferences
, I believe this setting doesn't apply to the main process since it's a node process itself.
My primary concern is about binding to ipcMain
events and incorporating them into my assertions. Additionally, how can I determine when the launcher window closes and the main window opens?
Furthermore, I have some confusion regarding the spectron API:
In the
spectron.d.ts
file, theelectron
property of theApplication
is defined as typeElectron.AllElectron
, which is aMainInterface
containing theipcMain
property directly. My understanding leads me to believe that accessingipcMain
should be viaapp.electron.ipcMain
(however, this returns undefined). Where does 'remote' come from and why is it not visible in thespectron.d.ts
file?All methods in the
SpectronClient
returnPromise<void>
. In JavaScript examples, they chain client statements like below:
return app.client
.waitUntilWindowLoaded()
.getTitle().should.equal('Launcher');
This chaining method doesn't work in TypeScript due to inability to chain to a Promise<void>
. How does this functionality work in JavaScript?