mirror of
https://github.com/finos/SymphonyElectron.git
synced 2024-11-24 09:50:51 -06:00
test: Spectron (Initial commit) (#838)
* Spectron - Initial commit * Spectron - Only run unit tests on travis * Spectron - Update npm script to copy config and refactor * Spectron - Update readme * Spectron - update test cases * Spectron - Merge upstream Spectron * Spectron - Update spectron to 10.0.0 and fix issues * Spectron - rename travis file * Spectron - install linux specific dependency * Spectron - Fix indentation * Spectron - Fix indentation * Spectron - Remove unwanted script * fix typo
This commit is contained in:
parent
e29e76f558
commit
873badf389
3
.github/workflows/ci.yml
vendored
3
.github/workflows/ci.yml
vendored
@ -19,6 +19,9 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
- run: npm config set package-lock false
|
- run: npm config set package-lock false
|
||||||
|
- name: install linux dependency
|
||||||
|
if: startsWith(matrix.os,'ubuntu')
|
||||||
|
run: sudo apt-get install libxtst-dev
|
||||||
- run: npm install
|
- run: npm install
|
||||||
- run: npm test
|
- run: npm test
|
||||||
env:
|
env:
|
||||||
|
39
.travis.yml
Normal file
39
.travis.yml
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
env:
|
||||||
|
global:
|
||||||
|
- ELECTRON_QA="true"
|
||||||
|
- npm config set package-lock false
|
||||||
|
|
||||||
|
os:
|
||||||
|
- osx
|
||||||
|
|
||||||
|
compiler:
|
||||||
|
- gcc
|
||||||
|
|
||||||
|
language: node_js
|
||||||
|
|
||||||
|
node_js:
|
||||||
|
- '12.13.0'
|
||||||
|
|
||||||
|
addons:
|
||||||
|
chrome: stable
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- xvfb
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi
|
||||||
|
|
||||||
|
install:
|
||||||
|
- export DISPLAY=':99.0'
|
||||||
|
- Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
|
||||||
|
- npm install
|
||||||
|
|
||||||
|
script:
|
||||||
|
- node --version
|
||||||
|
- npm --version
|
||||||
|
- npm run rebuild
|
||||||
|
- npm run test:spectron
|
||||||
|
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- node_modules
|
24
appveyor.yml
Normal file
24
appveyor.yml
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
build: off
|
||||||
|
|
||||||
|
os: unstable
|
||||||
|
|
||||||
|
platform:
|
||||||
|
- x86
|
||||||
|
- x64
|
||||||
|
|
||||||
|
skip_tags: false
|
||||||
|
|
||||||
|
environment:
|
||||||
|
nodejs_version: "12"
|
||||||
|
|
||||||
|
cache:
|
||||||
|
- node_modules -> package.json
|
||||||
|
|
||||||
|
install:
|
||||||
|
- ps: Install-Product node $env:nodejs_version
|
||||||
|
- npm install
|
||||||
|
|
||||||
|
test_script:
|
||||||
|
- node --version
|
||||||
|
- npm --version
|
||||||
|
- npm run test
|
@ -24,8 +24,7 @@
|
|||||||
|
|
||||||
## Run demo:
|
## Run demo:
|
||||||
- npm install
|
- npm install
|
||||||
- npm run demo-win (for windows)
|
- npm run demo (runs platform specific commands)
|
||||||
- npm run demo-mac (for mac osx)
|
|
||||||
|
|
||||||
Remember to set this.origin to '*' in app-bridge.ts when running the demo. Search
|
Remember to set this.origin to '*' in app-bridge.ts when running the demo. Search
|
||||||
for // DEMO-APP: and comment that line back in. Make sure to comment it out again
|
for // DEMO-APP: and comment that line back in. Make sure to comment it out again
|
||||||
@ -104,13 +103,23 @@ before you commit.
|
|||||||
- To change the start url (i.e., pod url), edit config/Symphony.config and change 'url' variable. if no protocol provided, then https will be added.
|
- To change the start url (i.e., pod url), edit config/Symphony.config and change 'url' variable. if no protocol provided, then https will be added.
|
||||||
- The installer will include file config/Symphony.config next to executable. Changes in this file will effect all users.
|
- The installer will include file config/Symphony.config next to executable. Changes in this file will effect all users.
|
||||||
|
|
||||||
## Tests and Code Coverage
|
## Tests
|
||||||
|
- Use `npm test` to run all the tests
|
||||||
|
|
||||||
|
### Unit tests and Code Coverage
|
||||||
- [Jest framework](http://facebook.github.io/jest/) is used to run tests
|
- [Jest framework](http://facebook.github.io/jest/) is used to run tests
|
||||||
- Use `npm test` to run unit tests
|
- Use `npm run test:unit` to run unit tests
|
||||||
- Code coverage reports are placed in [coverage](../../out/coverage) directory
|
- Code coverage reports are placed in [coverage](../../out/coverage) directory
|
||||||
- To check the test run report, see the [dist](../../out) directory
|
- To check the test run report, see the [dist](../../out) directory
|
||||||
- See the [tests](./tests) directory to find all the unit tests
|
- See the [tests](./tests) directory to find all the unit tests
|
||||||
|
|
||||||
|
### Spectron Tests
|
||||||
|
- [AVA](https://github.com/avajs/ava) is used to run Spectron tests
|
||||||
|
- Use `npm run test:spectron` to run spectron tests
|
||||||
|
- To compile spectron tests `npm run compile:spec`
|
||||||
|
- To run specific test use example: `npm run test:spectron -- --match=spell*` runs only spellchecker related tests
|
||||||
|
- Spectron - Application logs can be found in `~/Library/Logs/Electron/`
|
||||||
|
|
||||||
## Logging
|
## Logging
|
||||||
- Local logging is enabled for dev environments using the module [electron-log](https://www.npmjs.com/package/electron-log)
|
- Local logging is enabled for dev environments using the module [electron-log](https://www.npmjs.com/package/electron-log)
|
||||||
- On macOS, the logs are stored under `~/Library/Logs/<app name>/log.log`
|
- On macOS, the logs are stored under `~/Library/Logs/<app name>/log.log`
|
||||||
|
3559
package-lock.json
generated
3559
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
45
package.json
45
package.json
@ -11,19 +11,31 @@
|
|||||||
"main": "lib/src/app/init.js",
|
"main": "lib/src/app/init.js",
|
||||||
"types": "lib/src/app/init.d.ts",
|
"types": "lib/src/app/init.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"browserify-preload": "browserify -o lib/src/renderer/_preload-main.js -x electron --insert-global-vars=__filename,__dirname lib/src/renderer/preload-main.js && npm run browserify-preload-component",
|
"browserify": "run-s browserify-*",
|
||||||
|
"browserify-preload": "browserify -o lib/src/renderer/_preload-main.js -x electron --insert-global-vars=__filename,__dirname lib/src/renderer/preload-main.js",
|
||||||
"browserify-preload-component": "browserify -o lib/src/renderer/_preload-component.js -x electron --insert-global-vars=__filename,__dirname lib/src/renderer/preload-component.js",
|
"browserify-preload-component": "browserify -o lib/src/renderer/_preload-component.js -x electron --insert-global-vars=__filename,__dirname lib/src/renderer/preload-component.js",
|
||||||
"compile": "npm run lint && gulp build",
|
"compile": "run-s lint compile:*",
|
||||||
|
"compile:project": "gulp build",
|
||||||
|
"compile:spec": "tsc -p tsconfig.spec.json",
|
||||||
|
"compile:robot": "npm rebuild --build-from-source robotjs",
|
||||||
"dev": "npm run prebuild && cross-env ELECTRON_DEV=true electron .",
|
"dev": "npm run prebuild && cross-env ELECTRON_DEV=true electron .",
|
||||||
"demo-win": "npm run prebuild && cross-env ELECTRON_DEV=true electron . --url=file:///src/demo/index.html",
|
"demo": "run-os",
|
||||||
"demo-mac": "npm run prebuild && cross-env ELECTRON_DEV=true electron . --url=file://$(pwd)/src/demo/index.html",
|
"demo:win32": "npm run prebuild && cross-env ELECTRON_DEV=true electron . --url=file:///src/demo/index.html",
|
||||||
"lint": "tslint --project tsconfig.json",
|
"demo:darwin": "npm run prebuild && cross-env ELECTRON_DEV=true electron . --url=file://$(pwd)/src/demo/index.html",
|
||||||
|
"lint": "run-s lint:*",
|
||||||
|
"lint:project": "tslint --project tsconfig.json",
|
||||||
|
"lint:spec": "tslint --project tsconfig.spec.json",
|
||||||
"packed-linux": "npm run prebuild && npm run test && ./node_modules/.bin/electron-builder build --linux",
|
"packed-linux": "npm run prebuild && npm run test && ./node_modules/.bin/electron-builder build --linux",
|
||||||
"packed-mac": "npm run unpacked-mac && packagesbuild -v installer/mac/symphony-mac-packager.pkgproj",
|
"packed-mac": "npm run unpacked-mac && packagesbuild -v installer/mac/symphony-mac-packager.pkgproj",
|
||||||
"prebuild": "npm run compile && npm run rebuild && npm run browserify-preload",
|
"prebuild": "run-s compile rebuild browserify",
|
||||||
"rebuild": "electron-rebuild -f",
|
"rebuild": "electron-rebuild -f",
|
||||||
"start": "npm run compile && npm run browserify-preload && cross-env ELECTRON_DEV=true electron .",
|
"start": "run-s compile browserify && cross-env ELECTRON_DEV=true electron .",
|
||||||
"test": "npm run lint && cross-env ELECTRON_QA=true jest --config jest-config.json --runInBand --detectOpenHandles",
|
"test": "run-s lint test:unit",
|
||||||
|
"test:unit": "cross-env ELECTRON_QA=true jest --config jest-config.json --runInBand --detectOpenHandles",
|
||||||
|
"test:spectron": "npm run copy && run-s lint compile browserify && npx ava --verbose --serial",
|
||||||
|
"copy": "run-os",
|
||||||
|
"copy:darwin": "ncp config 'node_modules/electron/dist/Electron.app/Contents/config'",
|
||||||
|
"copy:win32": "ncp config node_modules\\electron\\dist\\config",
|
||||||
"unpacked-mac": "npm run prebuild && npm run test && ./node_modules/.bin/electron-builder build --mac --dir",
|
"unpacked-mac": "npm run prebuild && npm run test && ./node_modules/.bin/electron-builder build --mac --dir",
|
||||||
"unpacked-win": "npm run prebuild && npm run test && node_modules\\.bin\\electron-builder build --win --x64 --dir",
|
"unpacked-win": "npm run prebuild && npm run test && node_modules\\.bin\\electron-builder build --win --x64 --dir",
|
||||||
"unpacked-win-x86": "npm run prebuild && npm run test && node_modules\\.bin\\electron-builder build --win --ia32 --dir"
|
"unpacked-win-x86": "npm run prebuild && npm run test && node_modules\\.bin\\electron-builder build --win --ia32 --dir"
|
||||||
@ -105,6 +117,7 @@
|
|||||||
"@types/react": "16.8.3",
|
"@types/react": "16.8.3",
|
||||||
"@types/react-dom": "16.0.9",
|
"@types/react-dom": "16.0.9",
|
||||||
"@types/ref-napi": "1.4.0",
|
"@types/ref-napi": "1.4.0",
|
||||||
|
"ava": "2.4.0",
|
||||||
"browserify": "16.2.3",
|
"browserify": "16.2.3",
|
||||||
"cross-env": "5.2.0",
|
"cross-env": "5.2.0",
|
||||||
"del": "3.0.0",
|
"del": "3.0.0",
|
||||||
@ -123,7 +136,12 @@
|
|||||||
"jest": "23.6.0",
|
"jest": "23.6.0",
|
||||||
"jest-html-reporter": "2.4.2",
|
"jest-html-reporter": "2.4.2",
|
||||||
"less": "3.8.1",
|
"less": "3.8.1",
|
||||||
"node-abi": "^2.14.0",
|
"ncp": "2.0.0",
|
||||||
|
"node-abi": "^2.15.0",
|
||||||
|
"npm-run-all": "^4.1.5",
|
||||||
|
"robotjs": "0.6.0",
|
||||||
|
"run-script-os": "1.0.7",
|
||||||
|
"spectron": "10.0.1",
|
||||||
"ts-jest": "23.10.5",
|
"ts-jest": "23.10.5",
|
||||||
"tslint": "5.11.0",
|
"tslint": "5.11.0",
|
||||||
"typescript": "3.1.1"
|
"typescript": "3.1.1"
|
||||||
@ -149,5 +167,14 @@
|
|||||||
"screen-snippet": "git+https://github.com/symphonyoss/ScreenSnippet2.git#v1.0.6",
|
"screen-snippet": "git+https://github.com/symphonyoss/ScreenSnippet2.git#v1.0.6",
|
||||||
"screen-share-indicator-frame": "git+https://github.com/symphonyoss/ScreenShareIndicatorFrame.git#v1.4.3",
|
"screen-share-indicator-frame": "git+https://github.com/symphonyoss/ScreenShareIndicatorFrame.git#v1.4.3",
|
||||||
"swift-search": "2.0.2"
|
"swift-search": "2.0.2"
|
||||||
|
},
|
||||||
|
"ava": {
|
||||||
|
"failFast": true,
|
||||||
|
"files": [
|
||||||
|
"lib/spectron/**/*.spec.js"
|
||||||
|
],
|
||||||
|
"sources": [
|
||||||
|
"lib/src/**/*.js"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
47
spectron/about-app.spec.ts
Normal file
47
spectron/about-app.spec.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import test from 'ava';
|
||||||
|
import * as robot from 'robotjs';
|
||||||
|
import { Application } from 'spectron';
|
||||||
|
import { robotActions } from './fixtures/robot-actions';
|
||||||
|
import { loadURL, podUrl, sleep, startApplication, stopApplication, Timeouts } from './fixtures/spectron-setup';
|
||||||
|
|
||||||
|
let app;
|
||||||
|
|
||||||
|
test.before(async (t) => {
|
||||||
|
app = await startApplication() as Application;
|
||||||
|
t.true(app.isRunning());
|
||||||
|
|
||||||
|
await loadURL(app, podUrl);
|
||||||
|
await app.client.waitUntilWindowLoaded(Timeouts.fiveSec);
|
||||||
|
|
||||||
|
await sleep(Timeouts.fiveSec);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.after.always(async () => {
|
||||||
|
await stopApplication(app);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('about-app: verify about application feature', async (t) => {
|
||||||
|
robotActions.clickAppMenu();
|
||||||
|
robot.keyTap('down');
|
||||||
|
robot.keyTap('enter');
|
||||||
|
|
||||||
|
// wait for about window to load
|
||||||
|
await sleep(Timeouts.halfSec);
|
||||||
|
await app.client.windowByIndex(1);
|
||||||
|
await app.client.waitUntilWindowLoaded(Timeouts.fiveSec);
|
||||||
|
t.truthy(await app.browserWindow.getTitle(), 'About Symphony');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('about-app: verify copy button with few data validation', async (t) => {
|
||||||
|
await sleep(Timeouts.oneSec);
|
||||||
|
await app.client.click('.AboutApp-copy-button');
|
||||||
|
const clipboard = JSON.parse(await app.client.electron.remote.clipboard.readText());
|
||||||
|
|
||||||
|
t.log(clipboard);
|
||||||
|
t.true(clipboard.hasOwnProperty('appName'));
|
||||||
|
t.true(clipboard.hasOwnProperty('clientVersion'));
|
||||||
|
t.true(clipboard.hasOwnProperty('sfeVersion'));
|
||||||
|
t.true(clipboard.hasOwnProperty('sdaVersion'));
|
||||||
|
t.true(clipboard.hasOwnProperty('sdaBuildNumber'));
|
||||||
|
robotActions.closeWindow();
|
||||||
|
});
|
50
spectron/fixtures/robot-actions.ts
Normal file
50
spectron/fixtures/robot-actions.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import * as robot from 'robotjs';
|
||||||
|
import { isMac } from '../../src/common/env';
|
||||||
|
import { Timeouts } from './spectron-setup';
|
||||||
|
|
||||||
|
class RobotActions {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
robot.setKeyboardDelay(Timeouts.oneSec);
|
||||||
|
robot.setMouseDelay(Timeouts.oneSec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes window via keyboard action
|
||||||
|
*/
|
||||||
|
public closeWindow(): void {
|
||||||
|
const modifier = isMac ? [ 'command' ] : [ 'control' ];
|
||||||
|
robot.keyToggle('w', 'down', modifier);
|
||||||
|
robot.keyToggle('w', 'up', modifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes the application fullscreen via keyboard
|
||||||
|
*/
|
||||||
|
public toggleFullscreen(): void {
|
||||||
|
robot.keyToggle('f', 'down', [ 'command', 'control' ]);
|
||||||
|
robot.keyToggle('f', 'up', [ 'command', 'control' ]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Click the App menu
|
||||||
|
*/
|
||||||
|
public clickAppMenu(point?: Electron.Point): void {
|
||||||
|
if (isMac) {
|
||||||
|
robot.moveMouse(83, 14);
|
||||||
|
robot.mouseClick();
|
||||||
|
} else {
|
||||||
|
if (!point) {
|
||||||
|
throw new Error('browser window points are required');
|
||||||
|
}
|
||||||
|
robot.moveMouse(point.x + 10, point.y + 14);
|
||||||
|
robot.mouseClick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const robotActions = new RobotActions();
|
||||||
|
|
||||||
|
export {
|
||||||
|
robotActions,
|
||||||
|
};
|
97
spectron/fixtures/spectron-setup.ts
Normal file
97
spectron/fixtures/spectron-setup.ts
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
import * as path from 'path';
|
||||||
|
import { Application, BasicAppSettings } from 'spectron';
|
||||||
|
|
||||||
|
export const podUrl = 'https://corporate.symphony.com';
|
||||||
|
|
||||||
|
export enum Timeouts {
|
||||||
|
halfSec = 500,
|
||||||
|
oneSec = 1000,
|
||||||
|
threeSec = 3000,
|
||||||
|
fiveSec = 5000,
|
||||||
|
tenSec = 10000,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the electron executable path
|
||||||
|
*/
|
||||||
|
export const getElectronPath = (): string => {
|
||||||
|
let electronPath = path.join(__dirname, '..', '..', '..', 'node_modules', '.bin', 'electron');
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
electronPath += '.cmd';
|
||||||
|
}
|
||||||
|
return electronPath;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the demo application html path
|
||||||
|
*/
|
||||||
|
export const getDemoFilePath = (): string => {
|
||||||
|
return `file://${path.join(__dirname, '..', '..', '..', '/src/demo/index.html')}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns app init file
|
||||||
|
*/
|
||||||
|
export const getArgs = (): string[] => {
|
||||||
|
return [ path.join(__dirname, '..', '..', '/src/app/init.js') ];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the application
|
||||||
|
* @param application
|
||||||
|
*/
|
||||||
|
export const stopApplication = async (application): Promise<Application | undefined> => {
|
||||||
|
if (!application || !application.isRunning()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return await application.stop();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts and returns the application instance
|
||||||
|
* @param shouldLoadDemoApp {Boolean}
|
||||||
|
* @param options {BasicAppSettings}
|
||||||
|
*/
|
||||||
|
export const startApplication = async (
|
||||||
|
shouldLoadDemoApp: boolean = false,
|
||||||
|
options: BasicAppSettings = {
|
||||||
|
path: getElectronPath(),
|
||||||
|
args: getArgs(),
|
||||||
|
},
|
||||||
|
): Promise<Application> => {
|
||||||
|
// loads demo page correctly
|
||||||
|
if (shouldLoadDemoApp && options.args) {
|
||||||
|
options.args.push(`. --url=file://${getDemoFilePath()}`);
|
||||||
|
}
|
||||||
|
const application = new Application(options);
|
||||||
|
await application.start();
|
||||||
|
return application;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sleep function for tests that needs to wait
|
||||||
|
* @param ms
|
||||||
|
*/
|
||||||
|
export const sleep = (ms) => {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
setTimeout(resolve, ms);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the url with try catch due to an issue in Spectron frame work
|
||||||
|
* https://github.com/electron-userland/spectron/issues/493
|
||||||
|
* @param app
|
||||||
|
* @param url
|
||||||
|
*/
|
||||||
|
export const loadURL = async (app: Application, url: string): Promise<void> => {
|
||||||
|
try {
|
||||||
|
return await app.browserWindow.loadURL(url);
|
||||||
|
} catch (error) {
|
||||||
|
const errorIsNavigatedError: boolean = error.message.includes('Inspected target navigated or closed');
|
||||||
|
|
||||||
|
if (!errorIsNavigatedError) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
34
spectron/full-screen.spec.ts
Normal file
34
spectron/full-screen.spec.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import test from 'ava';
|
||||||
|
import * as robot from 'robotjs';
|
||||||
|
import { Application } from 'spectron';
|
||||||
|
import { robotActions } from './fixtures/robot-actions';
|
||||||
|
|
||||||
|
import {
|
||||||
|
getDemoFilePath, loadURL,
|
||||||
|
sleep,
|
||||||
|
startApplication,
|
||||||
|
stopApplication,
|
||||||
|
Timeouts,
|
||||||
|
} from './fixtures/spectron-setup';
|
||||||
|
|
||||||
|
let app;
|
||||||
|
|
||||||
|
test.before(async (t) => {
|
||||||
|
app = await startApplication() as Application;
|
||||||
|
t.true(app.isRunning());
|
||||||
|
});
|
||||||
|
|
||||||
|
test.after.always(async () => {
|
||||||
|
await stopApplication(app);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('fullscreen: verify application full screen feature', async (t) => {
|
||||||
|
await loadURL(app, getDemoFilePath());
|
||||||
|
await app.client.waitUntilWindowLoaded(Timeouts.fiveSec);
|
||||||
|
robotActions.toggleFullscreen();
|
||||||
|
t.true(await app.browserWindow.isFullScreen());
|
||||||
|
|
||||||
|
await sleep(Timeouts.halfSec);
|
||||||
|
robot.keyTap('escape');
|
||||||
|
t.false(await app.browserWindow.isFullScreen());
|
||||||
|
});
|
34
spectron/minimize.spec.ts
Normal file
34
spectron/minimize.spec.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import test from 'ava';
|
||||||
|
import { Application } from 'spectron';
|
||||||
|
import { robotActions } from './fixtures/robot-actions';
|
||||||
|
|
||||||
|
import { startApplication, stopApplication } from './fixtures/spectron-setup';
|
||||||
|
|
||||||
|
let app;
|
||||||
|
|
||||||
|
test.before(async (t) => {
|
||||||
|
app = await startApplication() as Application;
|
||||||
|
t.true(app.isRunning());
|
||||||
|
});
|
||||||
|
|
||||||
|
test.after.always(async () => {
|
||||||
|
await stopApplication(app);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('minimize: verify application minimize / maximize feature', async (t) => {
|
||||||
|
const win = app.browserWindow;
|
||||||
|
win.minimize();
|
||||||
|
t.true(await win.isMinimized());
|
||||||
|
|
||||||
|
win.restore();
|
||||||
|
t.true(await win.isVisible());
|
||||||
|
});
|
||||||
|
|
||||||
|
test('minimize: verify application to be minimized with keyboard accelerator', async (t) => {
|
||||||
|
const win = app.browserWindow;
|
||||||
|
robotActions.closeWindow();
|
||||||
|
t.false(await win.isVisible());
|
||||||
|
|
||||||
|
win.restore();
|
||||||
|
t.true(await win.isVisible());
|
||||||
|
});
|
47
spectron/notification.spec.ts
Normal file
47
spectron/notification.spec.ts
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import test from 'ava';
|
||||||
|
import { Application } from 'spectron';
|
||||||
|
|
||||||
|
import { getDemoFilePath, loadURL, sleep, startApplication, stopApplication, Timeouts } from './fixtures/spectron-setup';
|
||||||
|
|
||||||
|
let app;
|
||||||
|
|
||||||
|
test.before(async (t) => {
|
||||||
|
app = await startApplication(true) as Application;
|
||||||
|
t.true(app.isRunning());
|
||||||
|
});
|
||||||
|
|
||||||
|
test.after.always(async () => {
|
||||||
|
await stopApplication(app);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Verify is the application is running', async (t) => {
|
||||||
|
t.true(app.isRunning());
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Verify notification window is created', async (t) => {
|
||||||
|
await loadURL(app, getDemoFilePath());
|
||||||
|
await app.client.waitUntilWindowLoaded(Timeouts.fiveSec);
|
||||||
|
await app.client.click('#notf');
|
||||||
|
|
||||||
|
await sleep(Timeouts.oneSec);
|
||||||
|
t.timeout(10000);
|
||||||
|
t.is(await app.client.getWindowCount(), 2);
|
||||||
|
await app.client.windowByIndex(1);
|
||||||
|
await app.client.click('.close');
|
||||||
|
|
||||||
|
await sleep(2000);
|
||||||
|
await app.client.windowByIndex(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Verify notification window is hidden', async (t) => {
|
||||||
|
await app.client.click('#notf');
|
||||||
|
|
||||||
|
await sleep(Timeouts.oneSec);
|
||||||
|
t.timeout(Timeouts.fiveSec);
|
||||||
|
await app.client.windowByIndex(1);
|
||||||
|
await app.client.click('.close');
|
||||||
|
|
||||||
|
await sleep(2000);
|
||||||
|
await app.client.windowByIndex(0);
|
||||||
|
t.is(await app.client.getWindowCount(), 2);
|
||||||
|
});
|
56
spectron/screen-picker.spec.ts
Normal file
56
spectron/screen-picker.spec.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import test from 'ava';
|
||||||
|
import * as robot from 'robotjs';
|
||||||
|
import { Application } from 'spectron';
|
||||||
|
|
||||||
|
import {
|
||||||
|
getDemoFilePath, loadURL,
|
||||||
|
sleep,
|
||||||
|
startApplication,
|
||||||
|
stopApplication,
|
||||||
|
Timeouts,
|
||||||
|
} from './fixtures/spectron-setup';
|
||||||
|
|
||||||
|
let app;
|
||||||
|
|
||||||
|
export const openScreenPicker = async (window) => {
|
||||||
|
if (!window) {
|
||||||
|
throw new Error('openScreenPicker: must be called with Application');
|
||||||
|
}
|
||||||
|
await window.client.scroll(125, 1000);
|
||||||
|
await sleep(Timeouts.halfSec);
|
||||||
|
await window.client.click('#get-sources');
|
||||||
|
await window.client.waitUntilWindowLoaded(Timeouts.fiveSec);
|
||||||
|
};
|
||||||
|
|
||||||
|
test.before(async (t) => {
|
||||||
|
app = await startApplication() as Application;
|
||||||
|
t.true(app.isRunning());
|
||||||
|
});
|
||||||
|
|
||||||
|
test.after.always(async () => {
|
||||||
|
await stopApplication(app);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('screen-picker: verify screen-picker close button', async (t) => {
|
||||||
|
await loadURL(app, getDemoFilePath());
|
||||||
|
await app.client.waitUntilWindowLoaded(Timeouts.fiveSec);
|
||||||
|
await openScreenPicker(app);
|
||||||
|
|
||||||
|
await sleep(Timeouts.halfSec);
|
||||||
|
t.is(await app.client.getWindowCount(), 2);
|
||||||
|
await app.client.windowByIndex(1);
|
||||||
|
await app.client.click('.ScreenPicker-x-button');
|
||||||
|
await sleep(Timeouts.halfSec);
|
||||||
|
t.is(await app.client.getWindowCount(), 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('screen-picker: verify screen-picker escape keyboard actions', async (t) => {
|
||||||
|
await app.client.windowByIndex(0);
|
||||||
|
await openScreenPicker(app);
|
||||||
|
|
||||||
|
await sleep(Timeouts.halfSec);
|
||||||
|
t.is(await app.client.getWindowCount(), 2);
|
||||||
|
robot.keyTap('escape');
|
||||||
|
await sleep(Timeouts.halfSec);
|
||||||
|
t.is(await app.client.getWindowCount(), 1);
|
||||||
|
});
|
68
spectron/screen-sharing-indicator.spec.ts
Normal file
68
spectron/screen-sharing-indicator.spec.ts
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import test from 'ava';
|
||||||
|
import * as robot from 'robotjs';
|
||||||
|
import { Application } from 'spectron';
|
||||||
|
|
||||||
|
import {
|
||||||
|
getDemoFilePath, loadURL,
|
||||||
|
sleep,
|
||||||
|
startApplication,
|
||||||
|
stopApplication,
|
||||||
|
Timeouts,
|
||||||
|
} from './fixtures/spectron-setup';
|
||||||
|
|
||||||
|
let app;
|
||||||
|
|
||||||
|
export const openScreenPicker = async (window) => {
|
||||||
|
if (!window) {
|
||||||
|
throw new Error('openScreenPicker: must be called with Application');
|
||||||
|
}
|
||||||
|
await window.client.scroll(125, 1000);
|
||||||
|
await sleep(Timeouts.halfSec);
|
||||||
|
await window.client.click('#get-sources');
|
||||||
|
await window.client.waitUntilWindowLoaded(Timeouts.fiveSec);
|
||||||
|
};
|
||||||
|
|
||||||
|
test.before(async (t) => {
|
||||||
|
app = await startApplication() as Application;
|
||||||
|
t.true(app.isRunning());
|
||||||
|
});
|
||||||
|
|
||||||
|
test.after.always(async () => {
|
||||||
|
await stopApplication(app);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('screen-sharing-indicator: verify screen sharing indicator with frame is shown', async (t) => {
|
||||||
|
await loadURL(app, getDemoFilePath());
|
||||||
|
await app.client.waitUntilWindowLoaded(Timeouts.fiveSec);
|
||||||
|
await openScreenPicker(app);
|
||||||
|
robot.setKeyboardDelay(2000);
|
||||||
|
|
||||||
|
await sleep(Timeouts.halfSec);
|
||||||
|
t.is(await app.client.getWindowCount(), 2);
|
||||||
|
await app.client.windowByIndex(1);
|
||||||
|
// will select the entire screen option in the picker
|
||||||
|
robot.keyTap('right');
|
||||||
|
robot.keyTap('left');
|
||||||
|
robot.keyTap('enter');
|
||||||
|
|
||||||
|
await sleep(2000);
|
||||||
|
t.is(await app.client.getWindowCount(), 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('screen-sharing-indicator: verify screen sharing indicator title', async (t) => {
|
||||||
|
// including the screen sharing frame
|
||||||
|
await app.client.windowByIndex(1);
|
||||||
|
await app.client.waitUntilWindowLoaded(Timeouts.fiveSec);
|
||||||
|
|
||||||
|
const indicatorTitle = await app.browserWindow.getTitle();
|
||||||
|
if (indicatorTitle !== 'Screen Sharing Indicator - Symphony') {
|
||||||
|
await app.client.windowByIndex(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
await app.client.click('.stop-sharing-button');
|
||||||
|
await app.client.windowByIndex(0);
|
||||||
|
await sleep(Timeouts.halfSec);
|
||||||
|
// verify both frame and indicator are closed
|
||||||
|
// when stop button is clicked
|
||||||
|
t.is(await app.client.getWindowCount(), 1);
|
||||||
|
});
|
37
spectron/spell-checker.spec.ts
Normal file
37
spectron/spell-checker.spec.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import test from 'ava';
|
||||||
|
import * as robot from 'robotjs';
|
||||||
|
|
||||||
|
import { Application } from 'spectron';
|
||||||
|
|
||||||
|
import { getDemoFilePath, loadURL, startApplication, stopApplication, Timeouts } from './fixtures/spectron-setup';
|
||||||
|
|
||||||
|
let app;
|
||||||
|
|
||||||
|
test.before(async (t) => {
|
||||||
|
app = await startApplication() as Application;
|
||||||
|
t.true(app.isRunning());
|
||||||
|
});
|
||||||
|
|
||||||
|
test.after.always(async () => {
|
||||||
|
await stopApplication(app);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('spell-checker: verify application spell checking feature', async (t) => {
|
||||||
|
robot.setKeyboardDelay(Timeouts.oneSec);
|
||||||
|
const missSpelledWord = 'teest ';
|
||||||
|
|
||||||
|
await loadURL(app, getDemoFilePath());
|
||||||
|
await app.client.waitUntilWindowLoaded(Timeouts.fiveSec);
|
||||||
|
await app.client.electron.remote.clipboard.writeText(missSpelledWord);
|
||||||
|
await app.client.click('#tag');
|
||||||
|
await app.client.webContents.paste();
|
||||||
|
await app.client.waitForValue('#tag', Timeouts.fiveSec);
|
||||||
|
|
||||||
|
t.is(await app.client.getValue('#tag'), missSpelledWord);
|
||||||
|
|
||||||
|
await app.client.rightClick('#tag', 10, 10);
|
||||||
|
robot.keyTap('down');
|
||||||
|
robot.keyTap('enter');
|
||||||
|
|
||||||
|
t.not(await app.client.getValue('#tag'), missSpelledWord);
|
||||||
|
});
|
@ -1,7 +1,7 @@
|
|||||||
import { app } from 'electron';
|
import { app } from 'electron';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
|
||||||
import { isDevEnv } from '../common/env';
|
import { isDevEnv, isNodeEnv } from '../common/env';
|
||||||
import { logger } from '../common/logger';
|
import { logger } from '../common/logger';
|
||||||
import { getCommandLineArgs } from '../common/utils';
|
import { getCommandLineArgs } from '../common/utils';
|
||||||
import { appStats } from './stats';
|
import { appStats } from './stats';
|
||||||
@ -11,7 +11,9 @@ const userDataPathArg: string | null = getCommandLineArgs(process.argv, '--userD
|
|||||||
const userDataPath = userDataPathArg && userDataPathArg.substring(userDataPathArg.indexOf('=') + 1);
|
const userDataPath = userDataPathArg && userDataPathArg.substring(userDataPathArg.indexOf('=') + 1);
|
||||||
|
|
||||||
// force sandbox: true for all BrowserWindow instances.
|
// force sandbox: true for all BrowserWindow instances.
|
||||||
|
if (!isNodeEnv) {
|
||||||
app.enableSandbox();
|
app.enableSandbox();
|
||||||
|
}
|
||||||
|
|
||||||
// need to set this explicitly if using Squirrel
|
// need to set this explicitly if using Squirrel
|
||||||
// https://www.electron.build/configuration/configuration#Configuration-squirrelWindows
|
// https://www.electron.build/configuration/configuration#Configuration-squirrelWindows
|
||||||
|
@ -6,7 +6,7 @@ import * as path from 'path';
|
|||||||
import { format, parse } from 'url';
|
import { format, parse } from 'url';
|
||||||
|
|
||||||
import { apiName, WindowTypes } from '../common/api-interface';
|
import { apiName, WindowTypes } from '../common/api-interface';
|
||||||
import { isDevEnv, isMac, isWindowsOS } from '../common/env';
|
import { isDevEnv, isMac, isNodeEnv, isWindowsOS } from '../common/env';
|
||||||
import { i18n, LocaleType } from '../common/i18n';
|
import { i18n, LocaleType } from '../common/i18n';
|
||||||
import { logger } from '../common/logger';
|
import { logger } from '../common/logger';
|
||||||
import { getCommandLineArgs, getGuid } from '../common/utils';
|
import { getCommandLineArgs, getGuid } from '../common/utils';
|
||||||
@ -102,7 +102,6 @@ export class WindowHandler {
|
|||||||
this.windows = {};
|
this.windows = {};
|
||||||
this.contextIsolation = contextIsolation || false;
|
this.contextIsolation = contextIsolation || false;
|
||||||
this.backgroundThrottling = !customFlags.disableThrottling;
|
this.backgroundThrottling = !customFlags.disableThrottling;
|
||||||
this.contextIsolation = contextIsolation || false;
|
|
||||||
this.isCustomTitleBar = isWindowsOS && this.config.isCustomTitleBar === CloudConfigDataTypes.ENABLED;
|
this.isCustomTitleBar = isWindowsOS && this.config.isCustomTitleBar === CloudConfigDataTypes.ENABLED;
|
||||||
this.windowOpts = {
|
this.windowOpts = {
|
||||||
...this.getWindowOpts({
|
...this.getWindowOpts({
|
||||||
@ -781,6 +780,7 @@ export class WindowHandler {
|
|||||||
titleBarStyle: 'customButtonsOnHover',
|
titleBarStyle: 'customButtonsOnHover',
|
||||||
minimizable: false,
|
minimizable: false,
|
||||||
maximizable: false,
|
maximizable: false,
|
||||||
|
title: 'Screen Sharing Indicator - Symphony',
|
||||||
}, {
|
}, {
|
||||||
devTools: false,
|
devTools: false,
|
||||||
}), ...{winKey: streamId},
|
}), ...{winKey: streamId},
|
||||||
@ -1083,9 +1083,9 @@ export class WindowHandler {
|
|||||||
private getWindowOpts(windowOpts: Electron.BrowserWindowConstructorOptions, webPreferences: Electron.WebPreferences): ICustomBrowserWindowConstructorOpts {
|
private getWindowOpts(windowOpts: Electron.BrowserWindowConstructorOptions, webPreferences: Electron.WebPreferences): ICustomBrowserWindowConstructorOpts {
|
||||||
const defaultPreferencesOpts = {
|
const defaultPreferencesOpts = {
|
||||||
...{
|
...{
|
||||||
sandbox: true,
|
sandbox: !isNodeEnv,
|
||||||
nodeIntegration: false,
|
nodeIntegration: isNodeEnv,
|
||||||
contextIsolation: this.contextIsolation,
|
contextIsolation: isNodeEnv ? false : this.contextIsolation,
|
||||||
backgroundThrottling: this.backgroundThrottling,
|
backgroundThrottling: this.backgroundThrottling,
|
||||||
}, ...webPreferences,
|
}, ...webPreferences,
|
||||||
};
|
};
|
||||||
|
@ -7,7 +7,7 @@ import * as path from 'path';
|
|||||||
import { format, parse } from 'url';
|
import { format, parse } from 'url';
|
||||||
import { apiName } from '../common/api-interface';
|
import { apiName } from '../common/api-interface';
|
||||||
|
|
||||||
import { isDevEnv, isLinux, isMac } from '../common/env';
|
import { isDevEnv, isLinux, isMac, isNodeEnv } from '../common/env';
|
||||||
import { i18n, LocaleType } from '../common/i18n';
|
import { i18n, LocaleType } from '../common/i18n';
|
||||||
import { logger } from '../common/logger';
|
import { logger } from '../common/logger';
|
||||||
import { getGuid } from '../common/utils';
|
import { getGuid } from '../common/utils';
|
||||||
@ -122,6 +122,8 @@ export const createComponentWindow = (
|
|||||||
width: 300,
|
width: 300,
|
||||||
...opts,
|
...opts,
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
|
sandbox: !isNodeEnv,
|
||||||
|
nodeIntegration: isNodeEnv,
|
||||||
preload: path.join(__dirname, '../renderer/_preload-component.js'),
|
preload: path.join(__dirname, '../renderer/_preload-component.js'),
|
||||||
devTools: false,
|
devTools: false,
|
||||||
},
|
},
|
||||||
|
@ -259,12 +259,16 @@
|
|||||||
const ssfNotificationHandler = new window.ssf.Notification(notf.title, notf);
|
const ssfNotificationHandler = new window.ssf.Notification(notf.title, notf);
|
||||||
const onclick = (event) => {
|
const onclick = (event) => {
|
||||||
event.target.close();
|
event.target.close();
|
||||||
|
if (!process.env.NODE_ENV) {
|
||||||
alert('notification clicked: ' + event.target.data.hello);
|
alert('notification clicked: ' + event.target.data.hello);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
ssfNotificationHandler.addEventListener('click', onclick);
|
ssfNotificationHandler.addEventListener('click', onclick);
|
||||||
|
|
||||||
const onclose = () => {
|
const onclose = () => {
|
||||||
|
if (!process.env.NODE_ENV) {
|
||||||
alert('notification closed');
|
alert('notification closed');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
ssfNotificationHandler.addEventListener('close', onclose);
|
ssfNotificationHandler.addEventListener('close', onclose);
|
||||||
|
|
||||||
@ -669,6 +673,7 @@
|
|||||||
if (event.type === 'stopRequested') {
|
if (event.type === 'stopRequested') {
|
||||||
stream.getVideoTracks().forEach(t => t.stop());
|
stream.getVideoTracks().forEach(t => t.stop());
|
||||||
document.getElementById('video').srcObject = null;
|
document.getElementById('video').srcObject = null;
|
||||||
|
ssf.closeScreenSharingIndicator(stream.id)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -4,6 +4,7 @@ import { config } from '../app/config-handler';
|
|||||||
import { createComponentWindow, windowExists } from '../app/window-utils';
|
import { createComponentWindow, windowExists } from '../app/window-utils';
|
||||||
import { AnimationQueue } from '../common/animation-queue';
|
import { AnimationQueue } from '../common/animation-queue';
|
||||||
import { apiName, INotificationData, NotificationActions } from '../common/api-interface';
|
import { apiName, INotificationData, NotificationActions } from '../common/api-interface';
|
||||||
|
import { isNodeEnv } from '../common/env';
|
||||||
import { logger } from '../common/logger';
|
import { logger } from '../common/logger';
|
||||||
import NotificationHandler from './notification-handler';
|
import NotificationHandler from './notification-handler';
|
||||||
|
|
||||||
@ -428,8 +429,8 @@ class Notification extends NotificationHandler {
|
|||||||
acceptFirstMouse: true,
|
acceptFirstMouse: true,
|
||||||
title: 'Notification - Symphony',
|
title: 'Notification - Symphony',
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
sandbox: true,
|
sandbox: !isNodeEnv,
|
||||||
nodeIntegration: false,
|
nodeIntegration: isNodeEnv,
|
||||||
devTools: true,
|
devTools: true,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
39
travis.yml
Normal file
39
travis.yml
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
env:
|
||||||
|
global:
|
||||||
|
- ELECTRON_QA="true"
|
||||||
|
- npm config set package-lock false
|
||||||
|
|
||||||
|
os:
|
||||||
|
- osx
|
||||||
|
|
||||||
|
compiler:
|
||||||
|
- gcc
|
||||||
|
|
||||||
|
language: node_js
|
||||||
|
|
||||||
|
node_js:
|
||||||
|
- '12.13.0'
|
||||||
|
|
||||||
|
addons:
|
||||||
|
chrome: stable
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- xvfb
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi
|
||||||
|
|
||||||
|
install:
|
||||||
|
- export DISPLAY=':99.0'
|
||||||
|
- Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
|
||||||
|
- npm install
|
||||||
|
|
||||||
|
script:
|
||||||
|
- node --version
|
||||||
|
- npm --version
|
||||||
|
- npm run rebuild
|
||||||
|
- npm run test:spectron
|
||||||
|
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- node_modules
|
14
tsconfig.spec.json
Normal file
14
tsconfig.spec.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "lib"
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"spectron/**/*"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules/**",
|
||||||
|
"src",
|
||||||
|
"spec"
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user