Electron-308 - Added electron-chromedriver as dev dependency as it is

required to run Spectron tests

Electron-308 - Updated the code as per PR review

Electron-308

1. Changed args name
2. Fixed copy config method

Electron-308 - Optimized code and added error logs
This commit is contained in:
Kiran Niranjan 2018-02-19 13:07:30 +05:30 committed by kiranniranjan
parent bd48118b89
commit 01ecf8c065
12 changed files with 163 additions and 80 deletions

View File

@ -87,6 +87,7 @@
"electron": "^1.8.2", "electron": "^1.8.2",
"electron-builder": "^13.9.0", "electron-builder": "^13.9.0",
"electron-builder-squirrel-windows": "^12.3.0", "electron-builder-squirrel-windows": "^12.3.0",
"electron-chromedriver": "^1.8.0",
"electron-packager": "^8.5.2", "electron-packager": "^8.5.2",
"electron-rebuild": "^1.5.7", "electron-rebuild": "^1.5.7",
"eslint": "^3.16.1", "eslint": "^3.16.1",

View File

@ -1,6 +1,7 @@
const Application = require('./spectronSetup'); const Application = require('./spectronSetup');
const {isMac} = require('../../js/utils/misc.js'); const {isMac} = require('../../js/utils/misc.js');
const childProcess = require('child_process'); const childProcess = require('child_process');
const constants = require('./spectronConstants');
let app = new Application({}); let app = new Application({});
let robot; let robot;
@ -20,9 +21,15 @@ describe('Tests for Always on top', () => {
getConfigPath().then((config) => { getConfigPath().then((config) => {
configPath = config; configPath = config;
done(); done();
}).catch((err) => {
console.error(constants.UNABLE_TO_GET_USER_CONFIG_PATH, err);
expect(err).toBeNull();
done();
}); });
}).catch((err) => { }).catch((err) => {
console.error(constants.UNABLE_TO_START_APPLICATION, err);
expect(err).toBeNull(); expect(err).toBeNull();
done();
}); });
}); });
}); });
@ -34,8 +41,8 @@ describe('Tests for Always on top', () => {
return require('electron').remote.app.getPath('userData'); return require('electron').remote.app.getPath('userData');
}) })
}); });
app.client.getUserDataPath().then((path) => { app.client.getUserDataPath().then((userConfigPath) => {
resolve(path.value + '/Symphony.config') resolve(userConfigPath.value)
}).catch((err) => { }).catch((err) => {
reject(err); reject(err);
}); });
@ -136,6 +143,8 @@ describe('Tests for Always on top', () => {
robot.setMouseDelay(200); robot.setMouseDelay(200);
robot.moveMouse(190, 0); robot.moveMouse(190, 0);
robot.mouseClick(); robot.mouseClick();
// Key tap 10 times as "Always on Top" is in the
// 10th position under view menu item
for (let i = 0; i < 10; i++) { for (let i = 0; i < 10; i++) {
robot.keyTap('down'); robot.keyTap('down');
} }
@ -151,6 +160,8 @@ describe('Tests for Always on top', () => {
robot.moveMouseSmooth(x, y); robot.moveMouseSmooth(x, y);
robot.mouseClick(); robot.mouseClick();
// Key tap 4 times as "Always on Top" is in the
// 4th position under window menu item
for (let i = 0; i < 4; i++) { for (let i = 0; i < 4; i++) {
robot.keyTap('down'); robot.keyTap('down');
} }

View File

@ -1,4 +1,6 @@
const Application = require('./spectronSetup'); const Application = require('./spectronSetup');
const constants = require('./spectronConstants');
let app = new Application({}); let app = new Application({});
describe('Tests for Bring to front', () => { describe('Tests for Bring to front', () => {
@ -11,7 +13,9 @@ describe('Tests for Bring to front', () => {
app = startedApp; app = startedApp;
done(); done();
}).catch((err) => { }).catch((err) => {
console.error(constants.UNABLE_TO_START_APPLICATION, err);
expect(err).toBeNull(); expect(err).toBeNull();
done();
}); });
}); });

View File

@ -1,5 +1,7 @@
const Application = require('./spectronSetup'); const Application = require('./spectronSetup');
const path = require('path'); const path = require('path');
const constants = require('./spectronConstants');
let app = new Application({}); let app = new Application({});
describe('Tests for clipboard', () => { describe('Tests for clipboard', () => {
@ -11,6 +13,10 @@ describe('Tests for clipboard', () => {
return app.startApplication().then((startedApp) => { return app.startApplication().then((startedApp) => {
app = startedApp; app = startedApp;
done(); done();
}).catch((err) => {
console.error(constants.UNABLE_TO_START_APPLICATION, err);
expect(err).toBeNull();
done();
}); });
}); });

View File

@ -1,18 +1,21 @@
const Application = require('./spectronSetup');
const constants = require('./spectronConstants');
let app = new Application({});
describe('Tests for Close', () => { describe('Tests for Close', () => {
let originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL; let originalTimeout = jasmine.DEFAULT_TIMEOUT_INTERVAL;
jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000; jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000;
let app;
beforeAll((done) => { beforeAll((done) => {
const Application = require('./spectronSetup');
app = new Application({});
return app.startApplication().then((startedApp) => { return app.startApplication().then((startedApp) => {
app = startedApp; app = startedApp;
done(); done();
}).catch((err) => { }).catch((err) => {
console.error(constants.UNABLE_TO_START_APPLICATION, err);
expect(err).toBeNull(); expect(err).toBeNull();
done();
}); });
}); });

View File

@ -1,11 +1,10 @@
const path = require('path');
const fs = require('fs');
const childProcess = require('child_process'); const childProcess = require('child_process');
const Application = require('./spectronSetup'); const Application = require('./spectronSetup');
const {isMac} = require('../../js/utils/misc'); const { isMac } = require('../../js/utils/misc');
const constants = require('./spectronConstants');
let robot; let robot;
let configPath; let configPath;
let app = new Application({}); let app = new Application({});
describe('Tests for Full screen', () => { describe('Tests for Full screen', () => {
@ -22,10 +21,14 @@ describe('Tests for Full screen', () => {
configPath = config; configPath = config;
done(); done();
}).catch((err) => { }).catch((err) => {
console.error(constants.UNABLE_TO_GET_USER_CONFIG_PATH, err);
expect(err).toBeNull(); expect(err).toBeNull();
done();
}); });
}).catch((err) => { }).catch((err) => {
console.error(constants.UNABLE_TO_START_APPLICATION, err);
expect(err).toBeNull(); expect(err).toBeNull();
done();
}); });
}); });
}); });
@ -37,8 +40,8 @@ describe('Tests for Full screen', () => {
return require('electron').remote.app.getPath('userData'); return require('electron').remote.app.getPath('userData');
}) })
}); });
app.client.getUserDataPath().then((path) => { app.client.getUserDataPath().then((userConfigPath) => {
resolve(path.value + '/Symphony.config') resolve(userConfigPath.value)
}).catch((err) => { }).catch((err) => {
reject(err); reject(err);
}); });
@ -108,6 +111,9 @@ describe('Tests for Full screen', () => {
robot.moveMouseSmooth(205, 10); robot.moveMouseSmooth(205, 10);
robot.mouseClick(); robot.mouseClick();
robot.setKeyboardDelay(100); robot.setKeyboardDelay(100);
// Key tap 8 times as "Enter Full Screen" is in the
// 8th position under view menu item
for (let i = 0; i < 8; i++) { for (let i = 0; i < 8; i++) {
robot.keyTap('down'); robot.keyTap('down');
} }

View File

@ -1,11 +1,10 @@
const path = require('path');
const fs = require('fs');
const childProcess = require('child_process'); const childProcess = require('child_process');
const Application = require('./spectronSetup'); const Application = require('./spectronSetup');
const {isMac} = require('../../js/utils/misc'); const { isMac } = require('../../js/utils/misc');
const constants = require('./spectronConstants');
let robot; let robot;
let configPath; let configPath;
let app = new Application({}); let app = new Application({});
describe('Tests for Minimize on Close', () => { describe('Tests for Minimize on Close', () => {
@ -22,10 +21,14 @@ describe('Tests for Minimize on Close', () => {
configPath = config; configPath = config;
done(); done();
}).catch((err) => { }).catch((err) => {
console.error(constants.UNABLE_TO_GET_USER_CONFIG_PATH, err);
expect(err).toBeNull(); expect(err).toBeNull();
done();
}); });
}).catch((err) => { }).catch((err) => {
console.error(constants.UNABLE_TO_START_APPLICATION, err);
expect(err).toBeNull(); expect(err).toBeNull();
done();
}); });
}); });
}); });
@ -37,8 +40,8 @@ describe('Tests for Minimize on Close', () => {
return require('electron').remote.app.getPath('userData'); return require('electron').remote.app.getPath('userData');
}) })
}); });
app.client.getUserDataPath().then((path) => { app.client.getUserDataPath().then((userConfigPath) => {
resolve(path.value + '/Symphony.config') resolve(userConfigPath.value)
}).catch((err) => { }).catch((err) => {
reject(err); reject(err);
}); });
@ -124,6 +127,8 @@ describe('Tests for Minimize on Close', () => {
robot.mouseClick(); robot.mouseClick();
robot.setKeyboardDelay(100); robot.setKeyboardDelay(100);
// Key tap 9 times as "Minimize on Close" is in the
// 9th position under view menu item
for (let i = 0; i < 9; i++) { for (let i = 0; i < 9; i++) {
robot.keyTap('down'); robot.keyTap('down');
} }
@ -148,6 +153,8 @@ describe('Tests for Minimize on Close', () => {
let y = bounds.y + 35; let y = bounds.y + 35;
robot.moveMouse(x, y); robot.moveMouse(x, y);
robot.mouseClick(); robot.mouseClick();
// Key tap 5 times as "Minimize on Close" is in the
// 5th position under Window menu item
for (let i = 0; i < 5; i++) { for (let i = 0; i < 5; i++) {
robot.keyTap('down'); robot.keyTap('down');
} }

View File

@ -1,6 +1,8 @@
const Application = require('./spectronSetup'); const Application = require('./spectronSetup');
const path = require('path'); const path = require('path');
const {isMac} = require('../../js/utils/misc'); const { isMac } = require('../../js/utils/misc');
const constants = require('./spectronConstants');
let app = new Application({}); let app = new Application({});
describe('Tests for Notification position', () => { describe('Tests for Notification position', () => {
@ -13,7 +15,9 @@ describe('Tests for Notification position', () => {
app = startedApp; app = startedApp;
done(); done();
}).catch((err) => { }).catch((err) => {
console.error(constants.UNABLE_TO_START_APPLICATION, err);
expect(err).toBeNull(); expect(err).toBeNull();
done();
}); });
}); });

View File

@ -0,0 +1,14 @@
module.exports = {
SYMPHONY_CONFIG_FILE_NAME: "/Symphony.config",
ELECTRON_GLOBAL_CONFIG_PATH_MAC: "node_modules/electron/dist/Electron.app/Contents/config",
ELECTRON_GLOBAL_CONFIG_PATH_WIN: "node_modules/electron/dist/config",
SEARCH_LIBRARY_PATH_MAC: "node_modules/electron/dist/Electron.app/Contents/library",
SEARCH_LIBRARY_PATH_WIN: "node_modules/electron/dist/library",
UNABLE_TO_START_APPLICATION: "Unable to start application error: ",
UNABLE_TO_GET_USER_CONFIG_PATH: "Unable to get user config path error: "
};

View File

@ -1,8 +1,9 @@
const Application = require('spectron').Application; const Application = require('spectron').Application;
const path = require('path'); const path = require('path');
const fs = require('fs'); const fs = require('fs');
const {isMac} = require('../../js/utils/misc'); const { isMac, isWindowsOS } = require('../../js/utils/misc');
const ncp = require('ncp').ncp; const ncp = require('ncp').ncp;
const constants = require('./spectronConstants.js');
class App { class App {
@ -15,8 +16,16 @@ class App {
this.options.args = [path.join(__dirname, '..', '..', 'js/main.js')]; this.options.args = [path.join(__dirname, '..', '..', 'js/main.js')];
} }
App.copyConfigPath(); if (isMac) {
App.copyLibraryDir(); App.copyConfigPath(constants.ELECTRON_GLOBAL_CONFIG_PATH_MAC);
App.copyLibraries(constants.SEARCH_LIBRARY_PATH_MAC);
}
if (isWindowsOS) {
App.copyConfigPath(constants.ELECTRON_GLOBAL_CONFIG_PATH_WIN);
App.copyLibraries(constants.SEARCH_LIBRARY_PATH_WIN);
}
this.app = new Application(this.options); this.app = new Application(this.options);
} }
@ -25,6 +34,7 @@ class App {
return this.app.start().then((app) => { return this.app.start().then((app) => {
return app; return app;
}).catch((err) => { }).catch((err) => {
throw new Error("Unable to start application " + err);
}); });
} }
@ -42,55 +52,64 @@ class App {
static readConfig(configPath) { static readConfig(configPath) {
if (!fs.existsSync(configPath)) { const configFilePath = configPath + constants.SYMPHONY_CONFIG_FILE_NAME;
return this.copyConfigPath();
} else { if (!fs.existsSync(configFilePath)) {
return new Promise(function (resolve) { return new Promise(function (resolve, reject) {
fs.readFile(configPath, 'utf-8', function (err, data) { App.copyConfigPath(configPath).then(() => {
fs.readFile(configFilePath, 'utf-8', function (err, data) {
if (err) { if (err) {
throw new Error("Unable to read user config file " + err); throw new Error(`Unable to read user config file at ${configFilePath} ${err}`);
} }
resolve(JSON.parse(data)); let parsedData;
try {
parsedData = JSON.parse(data);
} catch (err) {
return reject(err);
}
return resolve(parsedData);
});
}); });
}); });
}
} }
static copyConfigPath() { return new Promise(function (resolve, reject) {
fs.readFile(configFilePath, 'utf-8', function (err, data) {
if (err) {
throw new Error(`Unable to read user config file at ${configFilePath} ${err}`);
}
let parsedData;
try {
parsedData = JSON.parse(data);
} catch (err) {
reject(err);
}
resolve(parsedData);
});
});
}
static copyConfigPath(configPath) {
return new Promise((resolve) => { return new Promise((resolve) => {
if (isMac) { ncp('config', configPath, function (err) {
ncp('config', 'node_modules/electron/dist/Electron.app/Contents/config', function (err) {
if (err) { if (err) {
throw new Error("Unable to copy config file to Electron dir " + err); throw new Error("Unable to copy config file to Electron dir " + err);
} }
resolve(); return resolve();
}); });
} else {
ncp('config', 'node_modules/electron/dist/config', function (err) {
if (err) {
throw new Error("Unable to copy config file to Electron dir " + err);
}
resolve();
});
}
}) })
} }
static copyLibraryDir() { static copyLibraries(libraryPath) {
if (isMac) { return new Promise((resolve) => {
ncp('library', 'node_modules/electron/dist/Electron.app/Contents/library', function (err) { return ncp('library', libraryPath, function (err) {
if (err) { if (err) {
throw new Error("Unable to copy Swift search library dir " + err); throw new Error("Unable to copy Swift search Libraries " + err);
} }
return resolve();
}); });
} else {
ncp('library', 'node_modules/electron/dist/library', function (err) {
if (err) {
throw new Error("Unable to copy Swift search library dir " + err);
}
}); });
} }
}
} }

View File

@ -2,6 +2,8 @@ const Application = require('./spectronSetup');
const path = require('path'); const path = require('path');
const {isMac} = require('../../js/utils/misc.js'); const {isMac} = require('../../js/utils/misc.js');
const childProcess = require('child_process'); const childProcess = require('child_process');
const constants = require('./spectronConstants');
let app = new Application({}); let app = new Application({});
let robot; let robot;
@ -11,11 +13,15 @@ describe('Tests for spellChecker', () => {
jasmine.DEFAULT_TIMEOUT_INTERVAL = Application.getTimeOut(); jasmine.DEFAULT_TIMEOUT_INTERVAL = Application.getTimeOut();
beforeAll((done) => { beforeAll((done) => {
childProcess.exec(`npm rebuild robotjs --target=${process.version} --build-from-source`, function () { childProcess.exec(`npm rebuild robotjs --target=${process.version} --build-from-source`, () => {
robot = require('robotjs'); robot = require('robotjs');
app.startApplication().then((startedApp) => { app.startApplication().then((startedApp) => {
app = startedApp; app = startedApp;
done(); done();
}).catch((err) => {
console.error(constants.UNABLE_TO_START_APPLICATION, err);
expect(err).toBeNull();
done();
}); });
}); });
}); });
@ -78,35 +84,33 @@ describe('Tests for spellChecker', () => {
it('should invoke context menu ', (done) => { it('should invoke context menu ', (done) => {
if (isMac) { if (isMac) {
app.browserWindow.getBounds().then((bounds) => { const tag = app.client.$('#tag');
let x = bounds.x + 55; tag.waitForExist('#tag', 2000);
let y = bounds.y + 430; tag.moveToObject('#tag', 10, 10);
tag.rightClick('#tag', 10, 10);
robot.moveMouseSmooth(x, y); // Timeout is required for context menu to appear
robot.setMouseDelay(200); setTimeout(() => {
robot.mouseClick('left', true);
robot.mouseClick('right');
robot.setKeyboardDelay(500); robot.setKeyboardDelay(500);
robot.keyTap('down'); robot.keyTap('down');
robot.keyTap('down'); robot.keyTap('down');
robot.keyTap('enter'); robot.keyTap('enter');
done(); done();
}); }, 2000);
} else { } else {
app.browserWindow.getBounds().then((bounds) => { const tag = app.client.$('#tag');
let x = bounds.x + 55; tag.waitForExist('#tag', 2000);
let y = bounds.y + 430; tag.moveToObject('#tag', 10, 10);
tag.rightClick('#tag', 10, 10);
robot.moveMouseSmooth(x, y); // Timeout is required for context menu to appear
robot.setMouseDelay(200); setTimeout(() => {
robot.mouseClick('left', true);
robot.mouseClick('right');
robot.setKeyboardDelay(500); robot.setKeyboardDelay(500);
robot.keyTap('down'); robot.keyTap('down');
robot.keyTap('down'); robot.keyTap('down');
robot.keyTap('enter'); robot.keyTap('enter');
done(); done();
}); }, 2000);
} }
}); });

View File

@ -1,8 +1,8 @@
const path = require('path');
const fs = require('fs');
const childProcess = require('child_process'); const childProcess = require('child_process');
const Application = require('./spectronSetup'); const Application = require('./spectronSetup');
const {isMac} = require('../../js/utils/misc'); const { isMac } = require('../../js/utils/misc');
const constants = require('./spectronConstants');
let robot; let robot;
let configPath; let configPath;
@ -22,10 +22,14 @@ describe('Tests for Zoom in and Zoom out', () => {
configPath = config; configPath = config;
done(); done();
}).catch((err) => { }).catch((err) => {
console.error(constants.UNABLE_TO_GET_USER_CONFIG_PATH, err);
expect(err).toBeNull(); expect(err).toBeNull();
done();
}); });
}).catch((err) => { }).catch((err) => {
console.error(constants.UNABLE_TO_START_APPLICATION, err);
expect(err).toBeNull(); expect(err).toBeNull();
done();
}); });
}); });
}); });
@ -37,8 +41,8 @@ describe('Tests for Zoom in and Zoom out', () => {
return require('electron').remote.app.getPath('userData'); return require('electron').remote.app.getPath('userData');
}) })
}); });
app.client.getUserDataPath().then((path) => { app.client.getUserDataPath().then((userConfigPath) => {
resolve(path.value + '/Symphony.config') resolve(userConfigPath.value)
}).catch((err) => { }).catch((err) => {
reject(err); reject(err);
}); });