Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Mock Native API in your E2E test

joe_re
November 06, 2017

Mock Native API in your E2E test

ElectronMeetup in Tokyo LT (https://connpass.com/event/69473/)

How to run spectron E2E test in case of using Native API in your specs.

joe_re

November 06, 2017
Tweet

More Decks by joe_re

Other Decks in Technology

Transcript

  1. Today, I talk about spectron E2E test in case of

    using 'Native API' in your spec.
  2. What is Spectron? E2E Testing tool for Electron appplication. You

    can call ElectronAPI in your spec via ChromeDriver and WebDriver.io.
  3. Example const app = new spectron.Application({ path: 'path/to/your/app' }); describe('application

    launch', function () { this.timeout(10000); beforeEach(function () { return app.start(); }); afterEach(function () { return app.stop(); }); it('shows an initial window', function () { return app.client.getWindowCount().then(function (count) { assert.equal(count, 1); }); }); });
  4. Strong Points You can access any DOM via Webdriver.io. You

    can call any Electron API in your spec. No need setup script.(use Chromium inside Electron) Support CI services.(Travis, AppVeyor, etc)
  5. Spectron is nice. But it can't access Native API. (latest

    v3.7.2) So it can't mock Menu, Dialog, etc modules... https://github.com/electron/spectron/issues/94
  6. This is simple solution, but ugly... if (process.env.NODE_ENV === "production")

    { // production code here } else { // test code here }
  7. Usage spectron­fake­menu const Application = require('spectron').Application; const fakeMenu = require('spectron-fake-menu');

    const app = new Application({ path: electron, args: [ path.join(__dirname, '.') ] }); fakeMenu.apply(app); // apply fake menu await app.start(); fakeMenu.clickMenu('Config'); // 'Config' Menu click fakeMenu.clickMenu('File', 'CloseTab'); // File->CloseTab Menu click spectron­fake­dialog const Application = require('spectron').Application; const fakeDialog = require('spectron-fake-dialog'); const app = new Application({ path: electron, args: [ path.join(__dirname, '.') ] }); fakeDialog.apply(app); await app.start(); fakeDialog.mock([ { method: 'showOpenDialog', value: ['faked.txt'] } ])); // write your specs
  8. How do they work? Electron provides '­­require' option same as

    Node.js. It can preload a module before run main script. These modules inject extra IPC and provide API which call or mock Native API inside your specs.
  9. Implementation(spectron­fake­dialog) const path = require('path'); let _app = null; function

    apply(app) { _app = app; _app.args.unshift(path.join(__dirname, 'preload.js')); _app.args.unshift('--require'); return _app; } function mock(options) { return _app.electron.ipcRenderer.sendSync('SPECTRON_FAKE_DIALOG/SEND', options); } module.exports = { apply, mock };
  10. Implementation(spectron­fake­dialog) preload script const { dialog, ipcMain, BrowserWindow } =

    require('electron'); //... some logics for creating mocked function ... function fake(options) { options.forEach(v => { if (dialog[v.method]) { dialog[v.method] = mockFunction.bind(null, v.value); } else { throw new Error(`can't find ${v.method} on dialog module.`); } }); } ipcMain.on('SPECTRON_FAKE_DIALOG/SEND', (e, options) => { fake(options); e.returnValue = true; });