replace Spectron by Playwright
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -43,6 +43,8 @@ testem.log
|
|||||||
/e2e/*.js
|
/e2e/*.js
|
||||||
!/e2e/protractor.conf.js
|
!/e2e/protractor.conf.js
|
||||||
/e2e/*.map
|
/e2e/*.map
|
||||||
|
/e2e/tracing
|
||||||
|
/e2e/screenshots
|
||||||
|
|
||||||
# System Files
|
# System Files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|||||||
@@ -3,9 +3,6 @@ import * as path from 'path';
|
|||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as url from 'url';
|
import * as url from 'url';
|
||||||
|
|
||||||
// Initialize remote module
|
|
||||||
require('@electron/remote/main').initialize();
|
|
||||||
|
|
||||||
let win: BrowserWindow = null;
|
let win: BrowserWindow = null;
|
||||||
const args = process.argv.slice(1),
|
const args = process.argv.slice(1),
|
||||||
serve = args.some(val => val === '--serve');
|
serve = args.some(val => val === '--serve');
|
||||||
@@ -25,7 +22,6 @@ function createWindow(): BrowserWindow {
|
|||||||
nodeIntegration: true,
|
nodeIntegration: true,
|
||||||
allowRunningInsecureContent: (serve) ? true : false,
|
allowRunningInsecureContent: (serve) ? true : false,
|
||||||
contextIsolation: false, // false if you want to run e2e test with Spectron
|
contextIsolation: false, // false if you want to run e2e test with Spectron
|
||||||
enableRemoteModule : true // true if you want to run e2e test with Spectron or use remote module in renderer context (ie. Angular)
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
18
app/package-lock.json
generated
18
app/package-lock.json
generated
@@ -1,13 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "angular-electron",
|
"name": "angular-electron",
|
||||||
"version": "10.1.0",
|
"version": "10.1.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1
|
||||||
"requires": true,
|
}
|
||||||
"dependencies": {
|
|
||||||
"@electron/remote": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@electron/remote/-/remote-1.2.0.tgz",
|
|
||||||
"integrity": "sha512-C774t2DFVJsa+dxU9Gc2nYzylRZoJ79I0Sxrh8T9cN69fBkntfGbyBEQiD9UfZopqL0CYLzk1anY2Ywhql6h1w=="
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,7 +3,5 @@
|
|||||||
"version": "10.1.0",
|
"version": "10.1.0",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {}
|
||||||
"@electron/remote": "1.2.0"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
const APPLICATION = require('spectron').Application;
|
|
||||||
const ELECTRON_PATH = require('electron'); // Require Electron from the binaries included in node_modules.
|
|
||||||
const PATH = require('path');
|
|
||||||
|
|
||||||
export default function setup(): void {
|
|
||||||
beforeEach(async function() {
|
|
||||||
this.app = new APPLICATION({
|
|
||||||
// Your electron path can be any binary
|
|
||||||
// i.e for OSX an example path could be '/Applications/MyApp.app/Contents/MacOS/MyApp'
|
|
||||||
// But for the sake of the example we fetch it from our node_modules.
|
|
||||||
path: ELECTRON_PATH,
|
|
||||||
// The following line tells spectron to look and use the main.js file
|
|
||||||
// and the package.json located in app folder.
|
|
||||||
args: [PATH.join(__dirname, '../app/main.js'), PATH.join(__dirname, '../app/package.json')],
|
|
||||||
webdriverOptions: {}
|
|
||||||
});
|
|
||||||
|
|
||||||
await this.app.start();
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(async function() {
|
|
||||||
if (this.app && this.app.isRunning()) {
|
|
||||||
await this.app.stop();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
import { expect } from 'chai';
|
|
||||||
import { SpectronClient } from 'spectron';
|
|
||||||
|
|
||||||
import commonSetup from './common-setup';
|
|
||||||
|
|
||||||
describe('angular-electron App', function() {
|
|
||||||
|
|
||||||
commonSetup.apply(this);
|
|
||||||
|
|
||||||
let client: SpectronClient;
|
|
||||||
|
|
||||||
beforeEach(function() {
|
|
||||||
client = this.app.client;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('creates initial windows', async function() {
|
|
||||||
const count = await client.getWindowCount();
|
|
||||||
expect(count).to.equal(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should display message saying App works !', async function() {
|
|
||||||
const elem = await client.$('app-home h1');
|
|
||||||
const text = await elem.getText();
|
|
||||||
expect(text).to.equal('App works !');
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
58
e2e/main.spec.ts
Normal file
58
e2e/main.spec.ts
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import { BrowserContext, ElectronApplication, Page, _electron as electron } from 'playwright';
|
||||||
|
import { test, expect } from '@playwright/test';
|
||||||
|
const PATH = require('path');
|
||||||
|
|
||||||
|
test.describe('Check Home Page', async () => {
|
||||||
|
let app: ElectronApplication;
|
||||||
|
let firstWindow: Page;
|
||||||
|
let context: BrowserContext;
|
||||||
|
|
||||||
|
test.beforeAll( async () => {
|
||||||
|
app = await electron.launch({ args: [PATH.join(__dirname, '../app/main.js'), PATH.join(__dirname, '../app/package.json')] });
|
||||||
|
context = app.context();
|
||||||
|
await context.tracing.start({ screenshots: true, snapshots: true });
|
||||||
|
firstWindow = await app.firstWindow();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Launch electron app', async () => {
|
||||||
|
|
||||||
|
const windowState: { isVisible: boolean; isDevToolsOpened: boolean; isCrashed: boolean } = await app.evaluate(async (process) => {
|
||||||
|
const mainWindow = process.BrowserWindow.getAllWindows()[0];
|
||||||
|
|
||||||
|
const getState = () => ({
|
||||||
|
isVisible: mainWindow.isVisible(),
|
||||||
|
isDevToolsOpened: mainWindow.webContents.isDevToolsOpened(),
|
||||||
|
isCrashed: mainWindow.webContents.isCrashed(),
|
||||||
|
});
|
||||||
|
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
if (mainWindow.isVisible()) {
|
||||||
|
resolve(getState());
|
||||||
|
} else {
|
||||||
|
mainWindow.once('ready-to-show', () => setTimeout(() => resolve(getState()), 0));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(windowState.isVisible).toBeTruthy();
|
||||||
|
expect(windowState.isDevToolsOpened).toBeFalsy();
|
||||||
|
expect(windowState.isCrashed).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Check Home Page design', async ({ browserName}) => {
|
||||||
|
// Uncomment if you change the design of Home Page in order to create a new screenshot
|
||||||
|
const screenshot = await firstWindow.screenshot({ path: '/tmp/home.png' });
|
||||||
|
expect(screenshot).toMatchSnapshot(`home-${browserName}.png`);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Check title', async () => {
|
||||||
|
const elem = await firstWindow.$('app-home h1');
|
||||||
|
const text = await elem.innerText();
|
||||||
|
expect(text).toBe('App works !');
|
||||||
|
});
|
||||||
|
|
||||||
|
test.afterAll( async () => {
|
||||||
|
await context.tracing.stop({ path: 'e2e/tracing/trace.zip' });
|
||||||
|
await app.close();
|
||||||
|
});
|
||||||
|
});
|
||||||
BIN
e2e/main.spec.ts-snapshots/home-chromium-win32.png
Normal file
BIN
e2e/main.spec.ts-snapshots/home-chromium-win32.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 317 KiB |
19
e2e/playwright.config.ts
Normal file
19
e2e/playwright.config.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/** @type {import('@playwright/test').PlaywrightTestConfig} */
|
||||||
|
const config = {
|
||||||
|
testDir: '.',
|
||||||
|
timeout: 45000,
|
||||||
|
outputDir: './screenshots',
|
||||||
|
use: {
|
||||||
|
headless: false,
|
||||||
|
viewport: { width: 1280, height: 720 },
|
||||||
|
launchOptions: {
|
||||||
|
slowMo: 1000,
|
||||||
|
},
|
||||||
|
trace: 'on',
|
||||||
|
},
|
||||||
|
expect: {
|
||||||
|
toMatchSnapshot: { threshold: 0.2 },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = config;
|
||||||
@@ -1,14 +1,13 @@
|
|||||||
{
|
{
|
||||||
"extends": "../tsconfig.json",
|
"extends": "../tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "../out-tsc/e2e",
|
"outDir": "../out-tsc/e2e",
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"types": [
|
"types": [
|
||||||
"mocha",
|
"node"
|
||||||
"node"
|
]
|
||||||
]
|
},
|
||||||
},
|
"include": [
|
||||||
"include": [
|
"**.spec.ts"
|
||||||
"**.ts"
|
],
|
||||||
]
|
}
|
||||||
}
|
|
||||||
|
|||||||
2560
package-lock.json
generated
2560
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
17
package.json
17
package.json
@@ -13,7 +13,7 @@
|
|||||||
"electron",
|
"electron",
|
||||||
"nodejs",
|
"nodejs",
|
||||||
"typescript",
|
"typescript",
|
||||||
"spectron",
|
"playwright",
|
||||||
"eslint",
|
"eslint",
|
||||||
"sass",
|
"sass",
|
||||||
"windows",
|
"windows",
|
||||||
@@ -36,7 +36,8 @@
|
|||||||
"electron:build": "npm run build:prod && electron-builder build --publish=never",
|
"electron:build": "npm run build:prod && electron-builder build --publish=never",
|
||||||
"test": "ng test --watch=false",
|
"test": "ng test --watch=false",
|
||||||
"test:watch": "ng test",
|
"test:watch": "ng test",
|
||||||
"e2e": "npm run build:prod && cross-env TS_NODE_PROJECT='e2e/tsconfig.e2e.json' mocha --timeout 300000 --require ts-node/register e2e/**/*.e2e.ts",
|
"e2e": "npm run build:prod && playwright test -c e2e/playwright.config.ts e2e/",
|
||||||
|
"e2e:show-trace": "playwright show-trace e2e/tracing/trace.zip",
|
||||||
"version": "conventional-changelog -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md",
|
"version": "conventional-changelog -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md",
|
||||||
"lint": "ng lint"
|
"lint": "ng lint"
|
||||||
},
|
},
|
||||||
@@ -49,7 +50,6 @@
|
|||||||
"@angular/platform-browser": "12.1.2",
|
"@angular/platform-browser": "12.1.2",
|
||||||
"@angular/platform-browser-dynamic": "12.1.2",
|
"@angular/platform-browser-dynamic": "12.1.2",
|
||||||
"@angular/router": "12.1.2",
|
"@angular/router": "12.1.2",
|
||||||
"@electron/remote": "1.2.0",
|
|
||||||
"rxjs": "~6.6.0",
|
"rxjs": "~6.6.0",
|
||||||
"tslib": "^2.1.0",
|
"tslib": "^2.1.0",
|
||||||
"zone.js": "~0.11.4"
|
"zone.js": "~0.11.4"
|
||||||
@@ -66,17 +66,15 @@
|
|||||||
"@angular/compiler-cli": "12.1.2",
|
"@angular/compiler-cli": "12.1.2",
|
||||||
"@ngx-translate/core": "13.0.0",
|
"@ngx-translate/core": "13.0.0",
|
||||||
"@ngx-translate/http-loader": "6.0.0",
|
"@ngx-translate/http-loader": "6.0.0",
|
||||||
|
"@playwright/test": "1.16.3",
|
||||||
"@types/jasmine": "3.8.1",
|
"@types/jasmine": "3.8.1",
|
||||||
"@types/jasminewd2": "2.0.10",
|
"@types/jasminewd2": "2.0.10",
|
||||||
"@types/mocha": "8.2.3",
|
|
||||||
"@types/node": "16.3.3",
|
"@types/node": "16.3.3",
|
||||||
"@typescript-eslint/eslint-plugin": "4.28.3",
|
"@typescript-eslint/eslint-plugin": "4.28.3",
|
||||||
"@typescript-eslint/parser": "4.28.3",
|
"@typescript-eslint/parser": "4.28.3",
|
||||||
"chai": "4.3.4",
|
|
||||||
"conventional-changelog-cli": "2.1.1",
|
"conventional-changelog-cli": "2.1.1",
|
||||||
"cross-env": "7.0.3",
|
"electron": "15.3.1",
|
||||||
"electron": "13.3.0",
|
"electron-builder": "22.13.1",
|
||||||
"electron-builder": "22.11.9",
|
|
||||||
"electron-reload": "1.5.0",
|
"electron-reload": "1.5.0",
|
||||||
"eslint": "7.30.0",
|
"eslint": "7.30.0",
|
||||||
"eslint-plugin-import": "2.23.4",
|
"eslint-plugin-import": "2.23.4",
|
||||||
@@ -89,10 +87,9 @@
|
|||||||
"karma-electron": "7.0.0",
|
"karma-electron": "7.0.0",
|
||||||
"karma-jasmine": "4.0.1",
|
"karma-jasmine": "4.0.1",
|
||||||
"karma-jasmine-html-reporter": "1.7.0",
|
"karma-jasmine-html-reporter": "1.7.0",
|
||||||
"mocha": "9.0.2",
|
|
||||||
"nan": "2.14.2",
|
"nan": "2.14.2",
|
||||||
"npm-run-all": "4.1.5",
|
"npm-run-all": "4.1.5",
|
||||||
"spectron": "15.0.0",
|
"playwright": "1.16.3",
|
||||||
"ts-node": "10.1.0",
|
"ts-node": "10.1.0",
|
||||||
"typescript": "~4.2.0",
|
"typescript": "~4.2.0",
|
||||||
"wait-on": "5.0.1",
|
"wait-on": "5.0.1",
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { Injectable } from '@angular/core';
|
|||||||
// If you import a module but never use any of the imported values other than as TypeScript types,
|
// If you import a module but never use any of the imported values other than as TypeScript types,
|
||||||
// the resulting javascript file will look as if you never imported the module at all.
|
// the resulting javascript file will look as if you never imported the module at all.
|
||||||
import { ipcRenderer, webFrame } from 'electron';
|
import { ipcRenderer, webFrame } from 'electron';
|
||||||
import * as remote from '@electron/remote';
|
|
||||||
import * as childProcess from 'child_process';
|
import * as childProcess from 'child_process';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
|
|
||||||
@@ -13,7 +12,6 @@ import * as fs from 'fs';
|
|||||||
export class ElectronService {
|
export class ElectronService {
|
||||||
ipcRenderer: typeof ipcRenderer;
|
ipcRenderer: typeof ipcRenderer;
|
||||||
webFrame: typeof webFrame;
|
webFrame: typeof webFrame;
|
||||||
remote: typeof remote;
|
|
||||||
childProcess: typeof childProcess;
|
childProcess: typeof childProcess;
|
||||||
fs: typeof fs;
|
fs: typeof fs;
|
||||||
|
|
||||||
@@ -30,10 +28,9 @@ export class ElectronService {
|
|||||||
this.childProcess = window.require('child_process');
|
this.childProcess = window.require('child_process');
|
||||||
this.fs = window.require('fs');
|
this.fs = window.require('fs');
|
||||||
|
|
||||||
// If you want to use a NodeJS 3rd party deps in Renderer process (like @electron/remote),
|
// If you want to use a NodeJS 3rd party deps in Renderer process,
|
||||||
// it must be declared in dependencies of both package.json (in root and app folders)
|
// ipcRenderer.invoke can serve many common use cases.
|
||||||
// If you want to use remote object in renderer process, please set enableRemoteModule to true in main.ts
|
// https://www.electronjs.org/docs/latest/api/ipc-renderer#ipcrendererinvokechannel-args
|
||||||
this.remote = window.require('@electron/remote');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,46 +1,45 @@
|
|||||||
// Karma configuration file, see link for more information
|
// Karma configuration file, see link for more information
|
||||||
// https://karma-runner.github.io/0.13/config/configuration-file.html
|
// https://karma-runner.github.io/0.13/config/configuration-file.html
|
||||||
|
|
||||||
module.exports = function (config) {
|
module.exports = function (config) {
|
||||||
config.set({
|
config.set({
|
||||||
basePath: '',
|
basePath: '',
|
||||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||||
plugins: [
|
plugins: [
|
||||||
require('karma-jasmine'),
|
require('karma-jasmine'),
|
||||||
require('karma-electron'),
|
require('karma-electron'),
|
||||||
require('karma-jasmine-html-reporter'),
|
require('karma-jasmine-html-reporter'),
|
||||||
require('karma-coverage-istanbul-reporter'),
|
require('karma-coverage-istanbul-reporter'),
|
||||||
require('@angular-devkit/build-angular/plugins/karma')
|
require('@angular-devkit/build-angular/plugins/karma')
|
||||||
],
|
],
|
||||||
client:{
|
client:{
|
||||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||||
},
|
},
|
||||||
coverageIstanbulReporter: {
|
coverageIstanbulReporter: {
|
||||||
dir: require('path').join(__dirname, '../coverage'),
|
dir: require('path').join(__dirname, '../coverage'),
|
||||||
reports: [ 'html', 'lcovonly' ],
|
reports: [ 'html', 'lcovonly' ],
|
||||||
fixWebpackSourcePaths: true
|
fixWebpackSourcePaths: true
|
||||||
},
|
},
|
||||||
reporters: ['progress', 'kjhtml'],
|
reporters: ['progress', 'kjhtml'],
|
||||||
port: 9876,
|
port: 9876,
|
||||||
colors: true,
|
colors: true,
|
||||||
logLevel: config.LOG_INFO,
|
logLevel: config.LOG_INFO,
|
||||||
browsers: ['AngularElectron'],
|
browsers: ['AngularElectron'],
|
||||||
customLaunchers: {
|
customLaunchers: {
|
||||||
AngularElectron: {
|
AngularElectron: {
|
||||||
base: 'Electron',
|
base: 'Electron',
|
||||||
flags: [
|
flags: [
|
||||||
'--remote-debugging-port=9222'
|
'--remote-debugging-port=9222'
|
||||||
],
|
],
|
||||||
browserWindowOptions: {
|
browserWindowOptions: {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true,
|
||||||
nodeIntegrationInSubFrames: true,
|
nodeIntegrationInSubFrames: true,
|
||||||
allowRunningInsecureContent: true,
|
allowRunningInsecureContent: true,
|
||||||
enableRemoteModule: true,
|
contextIsolation: false
|
||||||
contextIsolation: false
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
};
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
import 'core-js/es/reflect';
|
import 'zone.js';
|
||||||
import 'zone.js';
|
|
||||||
|
|||||||
Reference in New Issue
Block a user