[MM-38875] Migrate E2E testing to Playwright, re-enable tests (#1800)
* WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * WIP * [MM-38875] Migrate E2E testing to Playwright, re-enable tests * Add functionality to map view names to Playwright windows * Added search box test * Added robot.js for automating key presses * Add test using key strokes to navigate menu * Reload test and added webcontentsid to test helper * Check Ctrl+Shift+R as well * oops * Reorganize Co-authored-by: Mattermod <mattermod@users.noreply.github.com>
This commit is contained in:
parent
bd0d9df7e3
commit
c53e897bfd
|
@ -65,7 +65,7 @@ commands:
|
|||
default: ""
|
||||
steps:
|
||||
- run: wget -qO - https://download.opensuse.org/repositories/Emulators:/Wine:/Debian/xUbuntu_18.04/Release.key | apt-key add -
|
||||
- run: apt-get update || true && apt-get install ca-certificates && apt-get update && apt-get -y install << parameters.apt_opts >>
|
||||
- run: apt-get update || true && apt-get install -y ca-certificates libxtst-dev libpng++-dev && apt-get update && apt-get -y install << parameters.apt_opts >>
|
||||
|
||||
update_image:
|
||||
description: "Update image"
|
||||
|
@ -76,7 +76,7 @@ commands:
|
|||
steps:
|
||||
- update_base_image:
|
||||
apt_opts: << parameters.apt_opts >>
|
||||
- run: npm ci
|
||||
- run: PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm ci
|
||||
|
||||
win_make:
|
||||
description: "Run mattermost's makefile.ps1 on ./scripts/"
|
||||
|
|
2975
package-lock.json
generated
2975
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -28,6 +28,7 @@
|
|||
"build:main": "webpack-cli --bail --config webpack.config.main.js",
|
||||
"build:renderer": "webpack-cli --bail --config webpack.config.renderer.js",
|
||||
"build-prod": "npm-run-all build:*",
|
||||
"build-robotjs": "npm rebuild --runtime=electron --target=14.1.0 --disturl=https://atom.io/download/atom-shell --abi=83",
|
||||
"start": "electron dist/ --disable-dev-mode",
|
||||
"restart": "npm run build && npm run start",
|
||||
"storybook": "start-storybook -p 9001 -c src/.storybook",
|
||||
|
@ -38,7 +39,8 @@
|
|||
"watch:main": "node scripts/watch_main_and_preload.js",
|
||||
"watch:renderer": "webpack-dev-server --config webpack.config.renderer.js",
|
||||
"test": "npm-run-all lint:js test:unit test:e2e",
|
||||
"test:e2e": "cross-env NODE_ENV=test npm-run-all build test:e2e:build test:e2e:run",
|
||||
"test:e2e": "cross-env NODE_ENV=test npm-run-all build build-robotjs test:e2e:build test:e2e:run",
|
||||
"test:e2e:nobuild": "cross-env NODE_ENV=test npm-run-all test:e2e:build test:e2e:run",
|
||||
"test:e2e:build": "webpack-cli --bail --config webpack.config.test.js",
|
||||
"test:e2e:run": "electron-mocha -r @babel/register --reporter mocha-circleci-reporter dist/tests/e2e_bundle.js",
|
||||
"test:unit": "npm-run-all test:unit:build test:unit:run",
|
||||
|
@ -111,9 +113,10 @@
|
|||
"mocha": "^5.2.0",
|
||||
"mocha-circleci-reporter": "0.0.3",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"playwright": "^1.15.2",
|
||||
"robotjs": "^0.6.0",
|
||||
"sass-loader": "^10.2.0",
|
||||
"shebang-loader": "^0.0.1",
|
||||
"spectron": "^15.0.0",
|
||||
"style-loader": "^2.0.0",
|
||||
"typescript": "^4.3.4",
|
||||
"url-loader": "^1.1.2",
|
||||
|
|
|
@ -100,3 +100,6 @@ export const BROWSER_HISTORY_PUSH = 'browser-history-push';
|
|||
export const APP_LOGGED_IN = 'app-logged-in';
|
||||
|
||||
export const GET_AVAILABLE_SPELL_CHECKER_LANGUAGES = 'get-available-spell-checker-languages';
|
||||
|
||||
export const GET_VIEW_NAME = 'get-view-name';
|
||||
export const GET_VIEW_WEBCONTENTS_ID = 'get-view-webcontents-id';
|
||||
|
|
|
@ -51,6 +51,7 @@ export function displayMention(title: string, body: string, channel: {id: string
|
|||
});
|
||||
|
||||
mention.on('click', () => {
|
||||
log.info('notification click', serverName, mention);
|
||||
if (serverName) {
|
||||
windowManager.switchTab(serverName, TAB_MESSAGING);
|
||||
webcontents.send('notification-clicked', {channel, teamId, url});
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
/* eslint-disable no-magic-numbers */
|
||||
|
||||
import {ipcRenderer, webFrame} from 'electron';
|
||||
import {contextBridge, ipcRenderer, webFrame} from 'electron';
|
||||
|
||||
// I've filed an issue in electron-log https://github.com/megahertz/electron-log/issues/267
|
||||
// we'll be able to use it again if there is a workaround for the 'os' import
|
||||
|
@ -23,6 +23,8 @@ import {
|
|||
CLOSE_TEAMS_DROPDOWN,
|
||||
BROWSER_HISTORY_PUSH,
|
||||
APP_LOGGED_IN,
|
||||
GET_VIEW_NAME,
|
||||
GET_VIEW_WEBCONTENTS_ID,
|
||||
} from 'common/communication';
|
||||
|
||||
const UNREAD_COUNT_INTERVAL = 1000;
|
||||
|
@ -36,6 +38,13 @@ let shouldSendNotifications;
|
|||
|
||||
console.log('Preload initialized');
|
||||
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
contextBridge.exposeInMainWorld('testHelper', {
|
||||
getViewName: () => ipcRenderer.invoke(GET_VIEW_NAME),
|
||||
getWebContentsId: () => ipcRenderer.invoke(GET_VIEW_WEBCONTENTS_ID),
|
||||
});
|
||||
}
|
||||
|
||||
ipcRenderer.invoke('get-app-version').then(({name, version}) => {
|
||||
appVersion = version;
|
||||
appName = name;
|
||||
|
|
|
@ -77,13 +77,11 @@ export class MattermostView extends EventEmitter {
|
|||
this.options = Object.assign({}, options);
|
||||
this.options.webPreferences = {
|
||||
nativeWindowOpen: true,
|
||||
contextIsolation: process.env.NODE_ENV !== 'test',
|
||||
preload,
|
||||
additionalArguments: [
|
||||
`version=${app.getVersion()}`,
|
||||
`appName=${app.name}`,
|
||||
],
|
||||
nodeIntegration: process.env.NODE_ENV === 'test',
|
||||
...options.webPreferences,
|
||||
};
|
||||
this.isVisible = false;
|
||||
|
@ -273,12 +271,7 @@ export class MattermostView extends EventEmitter {
|
|||
}
|
||||
|
||||
getWebContents = () => {
|
||||
if (this.status === Status.READY) {
|
||||
return this.view.webContents;
|
||||
} else if (this.window) {
|
||||
return this.window.webContents; // if it's not ready you are looking at the renderer process
|
||||
}
|
||||
return WindowManager.getMainWindow()?.webContents;
|
||||
}
|
||||
|
||||
handleInputEvents = (_: Event, input: Input) => {
|
||||
|
|
|
@ -32,9 +32,7 @@ export class ModalView<T, T2> {
|
|||
log.info(`preloading with ${preload}`);
|
||||
this.view = new BrowserView({webPreferences: {
|
||||
nativeWindowOpen: true,
|
||||
contextIsolation: process.env.NODE_ENV !== 'test',
|
||||
preload,
|
||||
nodeIntegration: process.env.NODE_ENV === 'test',
|
||||
|
||||
// Workaround for this issue: https://github.com/electron/electron/issues/30993
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
|
|
|
@ -46,9 +46,7 @@ export default class TeamDropdownView {
|
|||
const preload = getLocalPreload('dropdown.js');
|
||||
this.view = new BrowserView({webPreferences: {
|
||||
nativeWindowOpen: true,
|
||||
contextIsolation: process.env.NODE_ENV !== 'test',
|
||||
preload,
|
||||
nodeIntegration: process.env.NODE_ENV === 'test',
|
||||
|
||||
// Workaround for this issue: https://github.com/electron/electron/issues/30993
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
|
|
|
@ -295,8 +295,6 @@ export class ViewManager {
|
|||
const urlView = new BrowserView({
|
||||
webPreferences: {
|
||||
nativeWindowOpen: true,
|
||||
contextIsolation: process.env.NODE_ENV !== 'test',
|
||||
nodeIntegration: process.env.NODE_ENV === 'test',
|
||||
|
||||
// Workaround for this issue: https://github.com/electron/electron/issues/30993
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
|
|
|
@ -169,8 +169,6 @@ const generateNewWindowListener = (getServersFunction: () => TeamWithTabs[], spe
|
|||
center: true,
|
||||
webPreferences: {
|
||||
nativeWindowOpen: true,
|
||||
nodeIntegration: process.env.NODE_ENV === 'test',
|
||||
contextIsolation: process.env.NODE_ENV !== 'test',
|
||||
spellcheck: (typeof spellcheck === 'undefined' ? true : spellcheck),
|
||||
},
|
||||
});
|
||||
|
|
|
@ -80,8 +80,6 @@ function createMainWindow(config: CombinedConfig, options: {linuxAppIcon: string
|
|||
backgroundColor: '#fff', // prevents blurry text: https://electronjs.org/docs/faq#the-font-looks-blurry-what-is-this-and-what-can-i-do
|
||||
webPreferences: {
|
||||
nativeWindowOpen: true,
|
||||
nodeIntegration: process.env.NODE_ENV === 'test',
|
||||
contextIsolation: process.env.NODE_ENV !== 'test',
|
||||
disableBlinkFeatures: 'Auxclick',
|
||||
preload,
|
||||
spellcheck,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// See LICENSE.txt for license information.
|
||||
|
||||
import path from 'path';
|
||||
import {app, BrowserWindow, nativeImage, systemPreferences, ipcMain, IpcMainEvent} from 'electron';
|
||||
import {app, BrowserWindow, nativeImage, systemPreferences, ipcMain, IpcMainEvent, IpcMainInvokeEvent} from 'electron';
|
||||
import log from 'electron-log';
|
||||
|
||||
import {CombinedConfig} from 'types/config';
|
||||
|
@ -18,6 +18,8 @@ import {
|
|||
UPDATE_SHORTCUT_MENU,
|
||||
BROWSER_HISTORY_PUSH,
|
||||
APP_LOGGED_IN,
|
||||
GET_VIEW_NAME,
|
||||
GET_VIEW_WEBCONTENTS_ID,
|
||||
} from 'common/communication';
|
||||
import urlUtils from 'common/utils/url';
|
||||
|
||||
|
@ -54,6 +56,8 @@ ipcMain.on(REACT_APP_INITIALIZED, handleReactAppInitialized);
|
|||
ipcMain.on(LOADING_SCREEN_ANIMATION_FINISHED, handleLoadingScreenAnimationFinished);
|
||||
ipcMain.on(BROWSER_HISTORY_PUSH, handleBrowserHistoryPush);
|
||||
ipcMain.on(APP_LOGGED_IN, handleAppLoggedIn);
|
||||
ipcMain.handle(GET_VIEW_NAME, handleGetViewName);
|
||||
ipcMain.handle(GET_VIEW_WEBCONTENTS_ID, handleGetWebContentsId);
|
||||
|
||||
export function setConfig(data: CombinedConfig) {
|
||||
if (data) {
|
||||
|
@ -585,3 +589,11 @@ export function getCurrentTeamName() {
|
|||
function handleAppLoggedIn(event: IpcMainEvent, viewName: string) {
|
||||
status.viewManager?.reloadViewIfNeeded(viewName);
|
||||
}
|
||||
|
||||
function handleGetViewName(event: IpcMainInvokeEvent) {
|
||||
return getViewNameByWebContentsId(event.sender.id);
|
||||
}
|
||||
function handleGetWebContentsId(event: IpcMainInvokeEvent) {
|
||||
return event.sender.id;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,11 +7,13 @@ const fs = require('fs');
|
|||
|
||||
const path = require('path');
|
||||
|
||||
const Application = require('spectron').Application;
|
||||
const {_electron: electron} = require('playwright');
|
||||
const chai = require('chai');
|
||||
const {ipcRenderer} = require('electron');
|
||||
|
||||
const {SHOW_SETTINGS_WINDOW} = require('../../src/common/communication');
|
||||
|
||||
const {asyncSleep} = require('./utils');
|
||||
chai.should();
|
||||
|
||||
const sourceRootDir = path.join(__dirname, '../..');
|
||||
|
@ -47,27 +49,61 @@ module.exports = {
|
|||
});
|
||||
},
|
||||
|
||||
cleanDataDir() {
|
||||
try {
|
||||
fs.rmdirSync(userDataDir, {recursive: true});
|
||||
} catch (err) {
|
||||
if (err.code !== 'ENOENT') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(err);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
createTestUserDataDir() {
|
||||
if (!fs.existsSync(userDataDir)) {
|
||||
fs.mkdirSync(userDataDir);
|
||||
}
|
||||
},
|
||||
|
||||
getSpectronApp() {
|
||||
async getApp() {
|
||||
const options = {
|
||||
path: electronBinaryPath,
|
||||
executablePath: electronBinaryPath,
|
||||
args: [`${path.join(sourceRootDir, 'dist')}`, `--data-dir=${userDataDir}`, '--disable-dev-mode'],
|
||||
chromeDriverArgs: [],
|
||||
};
|
||||
if (process.env.MM_DEBUG_SETTINGS) {
|
||||
options.chromeDriverLogPath = './chromedriverlog.txt';
|
||||
|
||||
// if (process.env.MM_DEBUG_SETTINGS) {
|
||||
// options.chromeDriverLogPath = './chromedriverlog.txt';
|
||||
// }
|
||||
// if (process.platform === 'darwin' || process.platform === 'linux') {
|
||||
// // on a mac, debbuging port might conflict with other apps
|
||||
// // this changes the default debugging port so chromedriver can run without issues.
|
||||
// options.chromeDriverArgs.push('remote-debugging-port=9222');
|
||||
//}
|
||||
return electron.launch(options).then(async (app) => {
|
||||
// Make sure the app has time to fully load
|
||||
await asyncSleep(1000);
|
||||
return app;
|
||||
});
|
||||
},
|
||||
|
||||
async getServerMap(app) {
|
||||
const map = {};
|
||||
await Promise.all(app.windows().map(async (win) => {
|
||||
return win.evaluate(async () => {
|
||||
if (!window.testHelper) {
|
||||
return null;
|
||||
}
|
||||
if (process.platform === 'darwin' || process.platform === 'linux') {
|
||||
// on a mac, debbuging port might conflict with other apps
|
||||
// this changes the default debugging port so chromedriver can run without issues.
|
||||
options.chromeDriverArgs.push('remote-debugging-port=9222');
|
||||
const name = await window.testHelper.getViewName();
|
||||
const webContentsId = await window.testHelper.getWebContentsId();
|
||||
return {viewName: name, webContentsId};
|
||||
}).then((result) => {
|
||||
if (result) {
|
||||
map[result.viewName] = {win, webContentsId: result.webContentsId};
|
||||
}
|
||||
return new Application(options);
|
||||
});
|
||||
}));
|
||||
return map;
|
||||
},
|
||||
|
||||
addClientCommands(client) {
|
||||
|
|
|
@ -2,153 +2,50 @@
|
|||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
// TODO: Commenting out until Spectron is upgraded for Electron v14
|
||||
'use strict';
|
||||
|
||||
// 'use strict';
|
||||
const env = require('../modules/environment');
|
||||
|
||||
// const fs = require('fs');
|
||||
describe('application', function desc() {
|
||||
this.timeout(30000);
|
||||
|
||||
// const env = require('../modules/environment');
|
||||
beforeEach(async () => {
|
||||
env.createTestUserDataDir();
|
||||
env.cleanTestConfig();
|
||||
this.app = await env.getApp();
|
||||
});
|
||||
|
||||
// describe('application', function desc() {
|
||||
// this.timeout(30000);
|
||||
afterEach(async () => {
|
||||
if (this.app) {
|
||||
await this.app.close();
|
||||
}
|
||||
});
|
||||
|
||||
// beforeEach(() => {
|
||||
// env.createTestUserDataDir();
|
||||
// env.cleanTestConfig();
|
||||
// this.app = env.getSpectronApp();
|
||||
// return this.app.start();
|
||||
// });
|
||||
it('should show the new server modal when no servers exist', async () => {
|
||||
const newServerModal = this.app.windows().find((window) => window.url().includes('newServer'));
|
||||
const modalTitle = await newServerModal.innerText('#newServerModal .modal-title');
|
||||
modalTitle.should.equal('Add Server');
|
||||
});
|
||||
|
||||
// afterEach(async () => {
|
||||
// if (this.app && this.app.isRunning()) {
|
||||
// await this.app.stop();
|
||||
// }
|
||||
// });
|
||||
it('should show no servers configured in dropdown when no servers exist', async () => {
|
||||
const mainWindow = this.app.windows().find((window) => window.url().includes('index'));
|
||||
const dropdownButtonText = await mainWindow.innerText('.TeamDropdownButton');
|
||||
dropdownButtonText.should.equal('No servers configured');
|
||||
});
|
||||
|
||||
// // it('should show two windows if there is no config file', async () => {
|
||||
// // await this.app.client.waitUntilWindowLoaded();
|
||||
// // const count = await this.app.client.getWindowCount();
|
||||
// // count.should.equal(2);
|
||||
// // const opened = await this.app.browserWindow.isDevToolsOpened();
|
||||
// // opened.should.be.false;
|
||||
it('should be stopped when the app instance already exists', (done) => {
|
||||
const secondApp = env.getApp();
|
||||
|
||||
// // const visible = await this.app.browserWindow.isVisible();
|
||||
// // visible.should.be.true;
|
||||
// // });
|
||||
|
||||
// if (process.platform === 'darwin') {
|
||||
// it.skip('should show closed window with cmd+tab', async () => {
|
||||
// // Unable to utilize Command key press due to: https://bugs.chromium.org/p/chromedriver/issues/detail?id=3023#c2
|
||||
// await this.app.client.waitUntilWindowLoaded();
|
||||
// await this.app.client.keys(['Meta', 'w']);
|
||||
// let visible = await this.app.browserWindow.isVisible();
|
||||
// visible.should.be.false;
|
||||
|
||||
// this.app.client.keys(['Meta', 'Tab']);
|
||||
// visible = await this.app.browserWindow.isVisible();
|
||||
// visible.should.be.true;
|
||||
// });
|
||||
// }
|
||||
|
||||
// it.skip('should restore window bounds', async () => {
|
||||
// // bounds seems to be incorrectly calculated in some environments
|
||||
// // - Windows 10: OK
|
||||
// // - CircleCI: NG
|
||||
// const expectedBounds = {x: 100, y: 200, width: 300, height: 400};
|
||||
// fs.writeFileSync(env.boundsInfoPath, JSON.stringify(expectedBounds));
|
||||
// await this.app.restart();
|
||||
// const bounds = await this.app.browserWindow.getBounds();
|
||||
// bounds.should.deep.equal(expectedBounds);
|
||||
// });
|
||||
|
||||
// it('should NOT restore window bounds if the origin is located on outside of viewarea', async () => {
|
||||
// // bounds seems to be incorrectly calculated in some environments (e.g. CircleCI)
|
||||
// // - Windows 10: OK
|
||||
// // - CircleCI: NG
|
||||
// fs.writeFileSync(env.boundsInfoPath, JSON.stringify({x: -100000, y: 200, width: 300, height: 400}));
|
||||
// await this.app.restart();
|
||||
// let bounds = await this.app.browserWindow.getBounds();
|
||||
// bounds.x.should.satisfy((x) => (x > -10000));
|
||||
|
||||
// fs.writeFileSync(env.boundsInfoPath, JSON.stringify({x: 100, y: 200000, width: 300, height: 400}));
|
||||
// await this.app.restart();
|
||||
// bounds = await this.app.browserWindow.getBounds();
|
||||
// bounds.y.should.satisfy((y) => (y < 10000));
|
||||
// });
|
||||
|
||||
// // it('should show settings.html when there is no config file', async () => {
|
||||
// // await this.app.client.waitUntilWindowLoaded();
|
||||
// // await this.app.client.pause(1000);
|
||||
// // const url = await this.app.client.getUrl();
|
||||
// // url.should.match(/\/settings.html$/);
|
||||
|
||||
// // const existing = await this.app.client.isExisting('#newServerModal');
|
||||
// // existing.should.equal(true);
|
||||
// // });
|
||||
|
||||
// // it('should show index.html when there is config file', async () => {
|
||||
// // const config = {
|
||||
// // version: 2,
|
||||
// // teams: [{
|
||||
// // name: 'example',
|
||||
// // url: env.mattermostURL,
|
||||
// // order: 0,
|
||||
// // }, {
|
||||
// // name: 'github',
|
||||
// // url: 'https://github.com/',
|
||||
// // order: 1,
|
||||
// // }],
|
||||
// // showTrayIcon: false,
|
||||
// // trayIconTheme: 'light',
|
||||
// // minimizeToTray: false,
|
||||
// // notifications: {
|
||||
// // flashWindow: 0,
|
||||
// // bounceIcon: false,
|
||||
// // bounceIconType: 'informational',
|
||||
// // },
|
||||
// // showUnreadBadge: true,
|
||||
// // useSpellChecker: true,
|
||||
// // enableHardwareAcceleration: true,
|
||||
// // autostart: true,
|
||||
// // darkMode: false,
|
||||
// // };
|
||||
// // fs.writeFileSync(env.configFilePath, JSON.stringify(config));
|
||||
// // await this.app.restart();
|
||||
|
||||
// // const url = await this.app.client.getUrl();
|
||||
// // url.should.match(/\/index.html$/);
|
||||
// // });
|
||||
|
||||
// // it('should upgrade v0 config file', async () => {
|
||||
// // const Config = require('../../src/common/config').default;
|
||||
// // const newConfig = new Config(env.configFilePath);
|
||||
// // const oldConfig = {
|
||||
// // url: env.mattermostURL,
|
||||
// // };
|
||||
// // fs.writeFileSync(env.configFilePath, JSON.stringify(oldConfig));
|
||||
// // await this.app.restart();
|
||||
|
||||
// // const url = await this.app.client.getUrl();
|
||||
// // url.should.match(/\/index.html$/);
|
||||
|
||||
// // const str = fs.readFileSync(env.configFilePath, 'utf8');
|
||||
// // const upgradedConfig = JSON.parse(str);
|
||||
// // upgradedConfig.version.should.equal(newConfig.defaultData.version);
|
||||
// // });
|
||||
|
||||
// // it.skip('should be stopped when the app instance already exists', (done) => {
|
||||
// // const secondApp = env.getSpectronApp();
|
||||
|
||||
// // // In the correct case, 'start().then' is not called.
|
||||
// // // So need to use setTimeout in order to finish this test.
|
||||
// // const timer = setTimeout(() => {
|
||||
// // done();
|
||||
// // }, 3000);
|
||||
// // secondApp.start().then(() => {
|
||||
// // clearTimeout(timer);
|
||||
// // return secondApp.stop();
|
||||
// // }).then(() => {
|
||||
// // done(new Error('Second app instance exists'));
|
||||
// // });
|
||||
// });
|
||||
// In the correct case, 'start().then' is not called.
|
||||
// So need to use setTimeout in order to finish this test.
|
||||
const timer = setTimeout(() => {
|
||||
done();
|
||||
}, 3000);
|
||||
secondApp.then(() => {
|
||||
clearTimeout(timer);
|
||||
return secondApp.close();
|
||||
}).then(() => {
|
||||
done(new Error('Second app instance exists'));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,8 +5,10 @@
|
|||
|
||||
const fs = require('fs');
|
||||
|
||||
const http = require('http');
|
||||
const path = require('path');
|
||||
const robot = require('robotjs');
|
||||
|
||||
// const http = require('http');
|
||||
// const path = require('path');
|
||||
|
||||
const env = require('../../modules/environment');
|
||||
const {asyncSleep} = require('../../modules/utils');
|
||||
|
@ -15,15 +17,51 @@ describe('renderer/index.html', function desc() {
|
|||
this.timeout(30000);
|
||||
|
||||
const config = {
|
||||
version: 2,
|
||||
version: 3,
|
||||
teams: [{
|
||||
name: 'example',
|
||||
url: env.mattermostURL,
|
||||
order: 0,
|
||||
tabs: [
|
||||
{
|
||||
name: 'TAB_MESSAGING',
|
||||
order: 0,
|
||||
isOpen: true,
|
||||
},
|
||||
{
|
||||
name: 'TAB_FOCALBOARD',
|
||||
order: 1,
|
||||
isOpen: true,
|
||||
},
|
||||
{
|
||||
name: 'TAB_PLAYBOOKS',
|
||||
order: 2,
|
||||
isOpen: true,
|
||||
},
|
||||
],
|
||||
lastActiveTab: 0,
|
||||
}, {
|
||||
name: 'github',
|
||||
url: 'https://github.com/',
|
||||
order: 1,
|
||||
tabs: [
|
||||
{
|
||||
name: 'TAB_MESSAGING',
|
||||
order: 0,
|
||||
isOpen: true,
|
||||
},
|
||||
{
|
||||
name: 'TAB_FOCALBOARD',
|
||||
order: 1,
|
||||
isOpen: true,
|
||||
},
|
||||
{
|
||||
name: 'TAB_PLAYBOOKS',
|
||||
order: 2,
|
||||
isOpen: true,
|
||||
},
|
||||
],
|
||||
lastActiveTab: 0,
|
||||
}],
|
||||
showTrayIcon: false,
|
||||
trayIconTheme: 'light',
|
||||
|
@ -38,178 +76,123 @@ describe('renderer/index.html', function desc() {
|
|||
enableHardwareAcceleration: true,
|
||||
autostart: true,
|
||||
darkMode: false,
|
||||
lastActiveTeam: 0,
|
||||
spellCheckerLocales: [],
|
||||
};
|
||||
|
||||
const serverPort = 8181;
|
||||
|
||||
before(() => {
|
||||
function serverCallback(req, res) {
|
||||
res.writeHead(200, {
|
||||
'Content-Type': 'text/html',
|
||||
});
|
||||
res.end(fs.readFileSync(path.resolve(env.sourceRootDir, 'test/modules/test.html'), 'utf-8'));
|
||||
}
|
||||
this.server = http.createServer(serverCallback).listen(serverPort, '127.0.0.1');
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
env.createTestUserDataDir();
|
||||
env.cleanTestConfig();
|
||||
fs.writeFileSync(env.configFilePath, JSON.stringify(config));
|
||||
await asyncSleep(1000);
|
||||
this.app = env.getSpectronApp();
|
||||
await this.app.start();
|
||||
this.app = await env.getApp();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (this.app && this.app.isRunning()) {
|
||||
await this.app.stop();
|
||||
if (this.app) {
|
||||
await this.app.close();
|
||||
}
|
||||
});
|
||||
|
||||
after((done) => {
|
||||
this.server.close(done);
|
||||
it('should set src of browser view from config file', async () => {
|
||||
const firstServer = this.app.windows().find((window) => window.url() === config.teams[0].url);
|
||||
const secondServer = this.app.windows().find((window) => window.url() === config.teams[1].url);
|
||||
|
||||
firstServer.should.not.be.null;
|
||||
secondServer.should.not.be.null;
|
||||
});
|
||||
|
||||
// it('should set src of webview from config file', async () => {
|
||||
// const src0 = await this.app.client.getAttribute('#mattermostView0', 'src');
|
||||
// src0.should.equal(config.teams[0].url);
|
||||
it('should set name of menu item from config file', async () => {
|
||||
const mainWindow = this.app.windows().find((window) => window.url().includes('index'));
|
||||
const dropdownView = this.app.windows().find((window) => window.url().includes('dropdown'));
|
||||
await mainWindow.click('.TeamDropdownButton');
|
||||
const firstMenuItem = await dropdownView.innerText('.TeamDropdown button.TeamDropdown__button:nth-child(1) span');
|
||||
const secondMenuItem = await dropdownView.innerText('.TeamDropdown button.TeamDropdown__button:nth-child(2) span');
|
||||
|
||||
// const src1 = await this.app.client.getAttribute('#mattermostView1', 'src');
|
||||
// src1.should.equal(config.teams[1].url);
|
||||
firstMenuItem.should.equal(config.teams[0].name);
|
||||
secondMenuItem.should.equal(config.teams[1].name);
|
||||
});
|
||||
|
||||
// const existing = await this.app.client.isExisting('#mattermostView2');
|
||||
// existing.should.be.false;
|
||||
// });
|
||||
it('should only show dropdown when button is clicked', async () => {
|
||||
const mainWindow = await this.app.firstWindow();
|
||||
const browserWindow = await this.app.browserWindow(mainWindow);
|
||||
const mainView = this.app.windows().find((window) => window.url().includes('index'));
|
||||
|
||||
// it('should set name of tab from config file', async () => {
|
||||
// const tabName0 = await this.app.client.getText('#teamTabItem0');
|
||||
// tabName0.should.equal(config.teams[0].name);
|
||||
let dropdownHeight = await browserWindow.evaluate((window) => window.getBrowserViews().find((view) => view.webContents.getURL().includes('dropdown')).getBounds().height);
|
||||
dropdownHeight.should.equal(0);
|
||||
|
||||
// const tabName1 = await this.app.client.getText('#teamTabItem1');
|
||||
// tabName1.should.equal(config.teams[1].name);
|
||||
// });
|
||||
await mainView.click('.TeamDropdownButton');
|
||||
dropdownHeight = await browserWindow.evaluate((window) => window.getBrowserViews().find((view) => view.webContents.getURL().includes('dropdown')).getBounds().height);
|
||||
dropdownHeight.should.be.greaterThan(0);
|
||||
|
||||
// it('should show only the selected team', () => {
|
||||
// return this.app.client.
|
||||
// waitForVisible('#mattermostView0', 2000).
|
||||
// waitForVisible('#mattermostView1', 2000, true).
|
||||
// click('#teamTabItem1').
|
||||
// waitForVisible('#mattermostView1', 2000).
|
||||
// waitForVisible('#mattermostView0', 2000, true);
|
||||
// });
|
||||
await mainView.click('.TabBar');
|
||||
dropdownHeight = await browserWindow.evaluate((window) => window.getBrowserViews().find((view) => view.webContents.getURL().includes('dropdown')).getBounds().height);
|
||||
dropdownHeight.should.equal(0);
|
||||
});
|
||||
|
||||
// validation now prevents incorrect url's from being used
|
||||
// it.skip('should show error when using incorrect URL', async () => {
|
||||
// this.timeout(30000);
|
||||
// fs.writeFileSync(env.configFilePath, JSON.stringify({
|
||||
// version: 2,
|
||||
// teams: [{
|
||||
// name: 'error_1',
|
||||
// url: 'http://false',
|
||||
// order: 0,
|
||||
// }],
|
||||
// }));
|
||||
// await this.app.restart();
|
||||
// return this.app.client.
|
||||
// waitForVisible('#mattermostView0-fail', 20000);
|
||||
// });
|
||||
it('should show only the selected team', async () => {
|
||||
const mainWindow = await this.app.firstWindow();
|
||||
const browserWindow = await this.app.browserWindow(mainWindow);
|
||||
|
||||
// it('shouldn\'t set window title by using webview\'s one', async () => {
|
||||
// fs.writeFileSync(env.configFilePath, JSON.stringify({
|
||||
// version: 2,
|
||||
// teams: [{
|
||||
// name: 'title_test',
|
||||
// url: `http://localhost:${serverPort}`,
|
||||
// order: 0,
|
||||
// }],
|
||||
// }));
|
||||
// await this.app.restart();
|
||||
// await this.app.client.pause(2000);
|
||||
// const windowTitle = await this.app.browserWindow.getTitle();
|
||||
// windowTitle.should.equal('Mattermost Desktop App');
|
||||
// });
|
||||
let firstViewIsAttached = await browserWindow.evaluate((window, url) => Boolean(window.getBrowserViews().find((view) => view.webContents.getURL() === url)), env.mattermostURL);
|
||||
firstViewIsAttached.should.be.true;
|
||||
let secondViewIsAttached = await browserWindow.evaluate((window) => Boolean(window.getBrowserViews().find((view) => view.webContents.getURL() === 'https://github.com/')));
|
||||
secondViewIsAttached.should.be.false;
|
||||
|
||||
// Skip because it's very unstable in CI
|
||||
// it.skip('should update window title when the activated tab\'s title is updated', async () => {
|
||||
// fs.writeFileSync(env.configFilePath, JSON.stringify({
|
||||
// version: 2,
|
||||
// teams: [{
|
||||
// name: 'title_test_0',
|
||||
// url: `http://localhost:${serverPort}`,
|
||||
// order: 0,
|
||||
// }, {
|
||||
// name: 'title_test_1',
|
||||
// url: `http://localhost:${serverPort}`,
|
||||
// order: 1,
|
||||
// }],
|
||||
// }));
|
||||
// await this.app.restart();
|
||||
// await this.app.client.pause(500);
|
||||
const mainView = this.app.windows().find((window) => window.url().includes('index'));
|
||||
const dropdownView = this.app.windows().find((window) => window.url().includes('dropdown'));
|
||||
await mainView.click('.TeamDropdownButton');
|
||||
await dropdownView.click('.TeamDropdown button.TeamDropdown__button:nth-child(2)');
|
||||
|
||||
// // Note: Indices of webview are correct.
|
||||
// // Somehow they are swapped.
|
||||
// await this.app.client.
|
||||
// windowByIndex(2).
|
||||
// execute(() => {
|
||||
// document.title = 'Title 0';
|
||||
// });
|
||||
// await this.app.client.windowByIndex(0).pause(500);
|
||||
// let windowTitle = await this.app.browserWindow.getTitle();
|
||||
// windowTitle.should.equal('Title 0');
|
||||
firstViewIsAttached = await browserWindow.evaluate((window, url) => Boolean(window.getBrowserViews().find((view) => view.webContents.getURL() === url)), env.mattermostURL);
|
||||
firstViewIsAttached.should.be.false;
|
||||
secondViewIsAttached = await browserWindow.evaluate((window) => Boolean(window.getBrowserViews().find((view) => view.webContents.getURL() === 'https://github.com/')));
|
||||
secondViewIsAttached.should.be.true;
|
||||
});
|
||||
|
||||
// await this.app.client.
|
||||
// windowByIndex(1).
|
||||
// execute(() => {
|
||||
// document.title = 'Title 1';
|
||||
// });
|
||||
// await this.app.client.windowByIndex(0).pause(500);
|
||||
// windowTitle = await this.app.browserWindow.getTitle();
|
||||
// windowTitle.should.equal('Title 0');
|
||||
// });
|
||||
it('should open the new server prompt after clicking the add button', async () => {
|
||||
const mainWindow = this.app.windows().find((window) => window.url().includes('index'));
|
||||
const dropdownView = this.app.windows().find((window) => window.url().includes('dropdown'));
|
||||
await mainWindow.click('.TeamDropdownButton');
|
||||
await dropdownView.click('.TeamDropdown__button.addServer');
|
||||
|
||||
// Skip because it's very unstable in CI
|
||||
// it.skip('should update window title when a tab is selected', async () => {
|
||||
// fs.writeFileSync(env.configFilePath, JSON.stringify({
|
||||
// version: 2,
|
||||
// teams: [{
|
||||
// name: 'title_test_0',
|
||||
// url: `http://localhost:${serverPort}`,
|
||||
// order: 0,
|
||||
// }, {
|
||||
// name: 'title_test_1',
|
||||
// url: `http://localhost:${serverPort}`,
|
||||
// order: 1,
|
||||
// }],
|
||||
// }));
|
||||
// await this.app.restart();
|
||||
const newServerModal = await this.app.waitForEvent('window', {
|
||||
predicate: (window) => window.url().includes('newServer'),
|
||||
});
|
||||
const modalTitle = await newServerModal.innerText('#newServerModal .modal-title');
|
||||
modalTitle.should.equal('Add Server');
|
||||
});
|
||||
|
||||
// // Note: Indices of webview are correct.
|
||||
// // Somehow they are swapped.
|
||||
// await this.app.client.pause(500);
|
||||
it('should switch to servers when keyboard shortcuts are pressed', async () => {
|
||||
const mainWindow = this.app.windows().find((window) => window.url().includes('index'));
|
||||
|
||||
// await this.app.client.
|
||||
// windowByIndex(2).
|
||||
// execute(() => {
|
||||
// document.title = 'Title 0';
|
||||
// });
|
||||
// await this.app.client.
|
||||
// windowByIndex(1).
|
||||
// execute(() => {
|
||||
// document.title = 'Title 1';
|
||||
// });
|
||||
// await this.app.client.windowByIndex(0).pause(500);
|
||||
let dropdownButtonText = await mainWindow.innerText('.TeamDropdownButton');
|
||||
dropdownButtonText.should.equal('example');
|
||||
|
||||
// let windowTitle = await this.app.browserWindow.getTitle();
|
||||
// windowTitle.should.equal('Title 0');
|
||||
robot.keyTap('2', ['control', 'shift']);
|
||||
dropdownButtonText = await mainWindow.innerText('.TeamDropdownButton');
|
||||
dropdownButtonText.should.equal('github');
|
||||
|
||||
// await this.app.client.click('#teamTabItem1').pause(500);
|
||||
// windowTitle = await this.app.browserWindow.getTitle();
|
||||
// windowTitle.should.equal('Title 1');
|
||||
// });
|
||||
robot.keyTap('1', ['control', 'shift']);
|
||||
dropdownButtonText = await mainWindow.innerText('.TeamDropdownButton');
|
||||
dropdownButtonText.should.equal('example');
|
||||
});
|
||||
|
||||
// it('should open the new server prompt after clicking the add button', async () => {
|
||||
// // See settings_test for specs that cover the actual prompt
|
||||
// await this.app.client.click('#addServerButton').pause(500);
|
||||
// const isModalExisting = await this.app.client.isExisting('#newServerModal');
|
||||
// isModalExisting.should.be.true;
|
||||
// });
|
||||
if (process.platform !== 'darwin') {
|
||||
it('should open the 3 dot menu with Alt', async () => {
|
||||
const mainWindow = this.app.windows().find((window) => window.url().includes('index'));
|
||||
mainWindow.should.not.be.null;
|
||||
|
||||
// Settings window should open if Alt works
|
||||
robot.keyTap('alt');
|
||||
robot.keyTap('enter');
|
||||
robot.keyTap('f');
|
||||
robot.keyTap('s');
|
||||
robot.keyTap('enter');
|
||||
const settingsWindow = await this.app.waitForEvent('window', {
|
||||
predicate: (window) => window.url().includes('settings'),
|
||||
});
|
||||
settingsWindow.should.not.be.null;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
266
test/specs/browser/modal_test.js
Normal file
266
test/specs/browser/modal_test.js
Normal file
|
@ -0,0 +1,266 @@
|
|||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
const env = require('../../modules/environment');
|
||||
const {asyncSleep} = require('../../modules/utils');
|
||||
|
||||
describe('modals', function desc() {
|
||||
this.timeout(30000);
|
||||
|
||||
const config = {
|
||||
version: 3,
|
||||
teams: [{
|
||||
name: 'example',
|
||||
url: env.mattermostURL,
|
||||
order: 0,
|
||||
tabs: [
|
||||
{
|
||||
name: 'TAB_MESSAGING',
|
||||
order: 0,
|
||||
isOpen: true,
|
||||
},
|
||||
{
|
||||
name: 'TAB_FOCALBOARD',
|
||||
order: 1,
|
||||
isOpen: true,
|
||||
},
|
||||
{
|
||||
name: 'TAB_PLAYBOOKS',
|
||||
order: 2,
|
||||
isOpen: true,
|
||||
},
|
||||
],
|
||||
lastActiveTab: 0,
|
||||
}, {
|
||||
name: 'github',
|
||||
url: 'https://github.com/',
|
||||
order: 1,
|
||||
tabs: [
|
||||
{
|
||||
name: 'TAB_MESSAGING',
|
||||
order: 0,
|
||||
isOpen: true,
|
||||
},
|
||||
{
|
||||
name: 'TAB_FOCALBOARD',
|
||||
order: 1,
|
||||
isOpen: true,
|
||||
},
|
||||
{
|
||||
name: 'TAB_PLAYBOOKS',
|
||||
order: 2,
|
||||
isOpen: true,
|
||||
},
|
||||
],
|
||||
lastActiveTab: 0,
|
||||
}],
|
||||
showTrayIcon: false,
|
||||
trayIconTheme: 'light',
|
||||
minimizeToTray: false,
|
||||
notifications: {
|
||||
flashWindow: 0,
|
||||
bounceIcon: false,
|
||||
bounceIconType: 'informational',
|
||||
},
|
||||
showUnreadBadge: true,
|
||||
useSpellChecker: true,
|
||||
enableHardwareAcceleration: true,
|
||||
autostart: true,
|
||||
darkMode: false,
|
||||
lastActiveTeam: 0,
|
||||
spellCheckerLocales: [],
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
env.createTestUserDataDir();
|
||||
env.cleanTestConfig();
|
||||
fs.writeFileSync(env.configFilePath, JSON.stringify(config));
|
||||
await asyncSleep(1000);
|
||||
this.app = await env.getApp();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (this.app) {
|
||||
await this.app.close();
|
||||
}
|
||||
});
|
||||
|
||||
describe('RemoveServerModal', () => {
|
||||
let removeServerView;
|
||||
|
||||
beforeEach(async () => {
|
||||
const mainView = this.app.windows().find((window) => window.url().includes('index'));
|
||||
const dropdownView = this.app.windows().find((window) => window.url().includes('dropdown'));
|
||||
await mainView.click('.TeamDropdownButton');
|
||||
await dropdownView.hover('.TeamDropdown .TeamDropdown__button:nth-child(1)');
|
||||
await dropdownView.click('.TeamDropdown .TeamDropdown__button:nth-child(1) button.TeamDropdown__button-remove');
|
||||
|
||||
removeServerView = await this.app.waitForEvent('window', {
|
||||
predicate: (window) => window.url().includes('removeServer'),
|
||||
});
|
||||
});
|
||||
|
||||
it('should remove existing team on click Remove', async () => {
|
||||
await removeServerView.click('button:has-text("Remove")');
|
||||
await asyncSleep(1000);
|
||||
|
||||
const expectedConfig = JSON.parse(JSON.stringify(config.teams.slice(1)));
|
||||
expectedConfig.forEach((value) => {
|
||||
value.order--;
|
||||
});
|
||||
|
||||
const savedConfig = JSON.parse(fs.readFileSync(env.configFilePath, 'utf8'));
|
||||
savedConfig.teams.should.deep.equal(expectedConfig);
|
||||
});
|
||||
|
||||
it('should NOT remove existing team on click Cancel', async () => {
|
||||
await removeServerView.click('button:has-text("Cancel")');
|
||||
await asyncSleep(1000);
|
||||
|
||||
const savedConfig = JSON.parse(fs.readFileSync(env.configFilePath, 'utf8'));
|
||||
savedConfig.teams.should.deep.equal(config.teams);
|
||||
});
|
||||
|
||||
it('should disappear on click Close', async () => {
|
||||
await removeServerView.click('button.close');
|
||||
await asyncSleep(1000);
|
||||
const existing = Boolean(await this.app.windows().find((window) => window.url().includes('removeServer')));
|
||||
existing.should.be.false;
|
||||
});
|
||||
|
||||
it('should disappear on click background', async () => {
|
||||
await removeServerView.click('.modal', {position: {x: 20, y: 20}});
|
||||
await asyncSleep(1000);
|
||||
const existing = Boolean(await this.app.windows().find((window) => window.url().includes('removeServer')));
|
||||
existing.should.be.false;
|
||||
});
|
||||
});
|
||||
|
||||
describe('NewTeamModal', () => {
|
||||
let newServerView;
|
||||
|
||||
beforeEach(async () => {
|
||||
const mainView = this.app.windows().find((window) => window.url().includes('index'));
|
||||
const dropdownView = this.app.windows().find((window) => window.url().includes('dropdown'));
|
||||
await mainView.click('.TeamDropdownButton');
|
||||
await dropdownView.click('.TeamDropdown .TeamDropdown__button.addServer');
|
||||
newServerView = await this.app.waitForEvent('window', {
|
||||
predicate: (window) => window.url().includes('newServer'),
|
||||
});
|
||||
|
||||
// wait for autofocus to finish
|
||||
await asyncSleep(500);
|
||||
});
|
||||
|
||||
it('should open the new server modal', async () => {
|
||||
const existing = Boolean(await this.app.windows().find((window) => window.url().includes('newServer')));
|
||||
existing.should.be.true;
|
||||
});
|
||||
|
||||
it('should close the window after clicking cancel', async () => {
|
||||
await newServerView.click('#cancelNewServerModal');
|
||||
await asyncSleep(1000);
|
||||
const existing = Boolean(await this.app.windows().find((window) => window.url().includes('newServer')));
|
||||
existing.should.be.false;
|
||||
});
|
||||
|
||||
it('should not be valid if no team name has been set', async () => {
|
||||
await newServerView.click('#saveNewServerModal');
|
||||
const existing = await newServerView.isVisible('#teamNameInput.is-invalid');
|
||||
existing.should.be.true;
|
||||
});
|
||||
|
||||
it('should not be valid if no server address has been set', async () => {
|
||||
await newServerView.click('#saveNewServerModal');
|
||||
const existing = await newServerView.isVisible('#teamUrlInput.is-invalid');
|
||||
existing.should.be.true;
|
||||
});
|
||||
|
||||
describe('Valid server name', async () => {
|
||||
beforeEach(async () => {
|
||||
await newServerView.type('#teamNameInput', 'TestTeam');
|
||||
await newServerView.click('#saveNewServerModal');
|
||||
});
|
||||
|
||||
it('should not be marked invalid', async () => {
|
||||
const existing = await newServerView.isVisible('#teamNameInput.is-invalid');
|
||||
existing.should.be.false;
|
||||
});
|
||||
|
||||
it('should not be possible to click save', async () => {
|
||||
const disabled = await newServerView.getAttribute('#saveNewServerModal', 'disabled');
|
||||
(disabled === '').should.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
describe('Valid server url', () => {
|
||||
beforeEach(async () => {
|
||||
await newServerView.type('#teamUrlInput', 'http://example.org');
|
||||
await newServerView.click('#saveNewServerModal');
|
||||
});
|
||||
|
||||
it('should be valid', async () => {
|
||||
const existing = await newServerView.isVisible('#teamUrlInput.is-invalid');
|
||||
existing.should.be.false;
|
||||
});
|
||||
|
||||
it('should not be possible to click save', async () => {
|
||||
const disabled = await newServerView.getAttribute('#saveNewServerModal', 'disabled');
|
||||
(disabled === '').should.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
it('should not be valid if an invalid server address has been set', async () => {
|
||||
await newServerView.type('#teamUrlInput', 'superInvalid url');
|
||||
await newServerView.click('#saveNewServerModal');
|
||||
const existing = await newServerView.isVisible('#teamUrlInput.is-invalid');
|
||||
existing.should.be.true;
|
||||
});
|
||||
|
||||
describe('Valid Team Settings', () => {
|
||||
beforeEach(async () => {
|
||||
await newServerView.type('#teamUrlInput', 'http://example.org');
|
||||
await newServerView.type('#teamNameInput', 'TestTeam');
|
||||
});
|
||||
|
||||
it('should be possible to click add', async () => {
|
||||
const disabled = await newServerView.getAttribute('#saveNewServerModal', 'disabled');
|
||||
(disabled === null).should.be.true;
|
||||
});
|
||||
|
||||
it('should add the team to the config file', async () => {
|
||||
await newServerView.click('#saveNewServerModal');
|
||||
await asyncSleep(1000);
|
||||
const existing = Boolean(await this.app.windows().find((window) => window.url().includes('newServer')));
|
||||
existing.should.be.false;
|
||||
|
||||
const savedConfig = JSON.parse(fs.readFileSync(env.configFilePath, 'utf8'));
|
||||
savedConfig.teams.should.deep.contain({
|
||||
name: 'TestTeam',
|
||||
url: 'http://example.org',
|
||||
order: 2,
|
||||
tabs: [
|
||||
{
|
||||
name: 'TAB_MESSAGING',
|
||||
order: 0,
|
||||
isOpen: true,
|
||||
},
|
||||
{
|
||||
name: 'TAB_FOCALBOARD',
|
||||
order: 1,
|
||||
},
|
||||
{
|
||||
name: 'TAB_PLAYBOOKS',
|
||||
order: 2,
|
||||
},
|
||||
],
|
||||
lastActiveTab: 0,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -4,529 +4,265 @@
|
|||
|
||||
// TODO: fix test with new settings window
|
||||
|
||||
// 'use strict';
|
||||
|
||||
// const fs = require('fs');
|
||||
|
||||
// const env = require('../../modules/environment');
|
||||
// const {asyncSleep} = require('../../modules/utils');
|
||||
|
||||
// describe('renderer/settings.html', function desc() {
|
||||
// this.timeout(30000);
|
||||
|
||||
// const config = {
|
||||
// version: 2,
|
||||
// teams: [{
|
||||
// name: 'example',
|
||||
// url: env.mattermostURL,
|
||||
// order: 0,
|
||||
// }, {
|
||||
// name: 'github',
|
||||
// url: 'https://github.com/',
|
||||
// order: 1,
|
||||
// }],
|
||||
// showTrayIcon: false,
|
||||
// trayIconTheme: 'light',
|
||||
// minimizeToTray: false,
|
||||
// notifications: {
|
||||
// flashWindow: 0,
|
||||
// bounceIcon: false,
|
||||
// bounceIconType: 'informational',
|
||||
// },
|
||||
// showUnreadBadge: true,
|
||||
// useSpellChecker: true,
|
||||
// enableHardwareAcceleration: true,
|
||||
// autostart: true,
|
||||
// darkMode: false,
|
||||
// };
|
||||
|
||||
// beforeEach(async () => {
|
||||
// fs.writeFileSync(env.configFilePath, JSON.stringify(config));
|
||||
// await asyncSleep(1000);
|
||||
// this.app = env.getSpectronApp();
|
||||
// await this.app.start();
|
||||
// });
|
||||
|
||||
// afterEach(async () => {
|
||||
// if (this.app && this.app.isRunning()) {
|
||||
// await this.app.stop();
|
||||
// }
|
||||
// });
|
||||
|
||||
// describe('Close button', async () => {
|
||||
// // it.skip('should show index.html when it\'s clicked', async () => {
|
||||
// // env.addClientCommands(this.app.client);
|
||||
// // await this.app.client.
|
||||
// // loadSettingsPage().
|
||||
// // click('#btnClose').
|
||||
// // pause(1000);
|
||||
// // const url = await this.app.client.getUrl();
|
||||
// // url.should.match(/\/index.html(\?.+)?$/);
|
||||
// // });
|
||||
|
||||
// it('should be disabled when the number of servers is zero', async () => {
|
||||
// await this.app.stop();
|
||||
// env.cleanTestConfig();
|
||||
// await this.app.start();
|
||||
|
||||
// await this.app.client.waitUntilWindowLoaded().
|
||||
// waitForVisible('#newServerModal', 10000).
|
||||
// click('#cancelNewServerModal');
|
||||
// let isCloseButtonEnabled = await this.app.client.isEnabled('#btnClose');
|
||||
// isCloseButtonEnabled.should.equal(false);
|
||||
|
||||
// await this.app.client.
|
||||
// waitForVisible('#newServerModal', true).
|
||||
// pause(250).
|
||||
// click('#addNewServer').
|
||||
// waitForVisible('#newServerModal').
|
||||
// setValue('#teamNameInput', 'TestTeam').
|
||||
// pause(100).
|
||||
// setValue('#teamUrlInput', 'http://example.org').
|
||||
// click('#saveNewServerModal').
|
||||
// waitForVisible('#newServerModal', true).
|
||||
// waitForVisible('#serversSaveIndicator').
|
||||
// waitForVisible('#serversSaveIndicator', 10000, true); // at least 2500 ms to disappear
|
||||
// isCloseButtonEnabled = await this.app.client.isEnabled('#btnClose');
|
||||
// isCloseButtonEnabled.should.equal(true);
|
||||
// });
|
||||
// });
|
||||
|
||||
// it('should show NewServerModal after all servers are removed', async () => {
|
||||
// const modalTitleSelector = '.modal-title=Remove Server';
|
||||
// env.addClientCommands(this.app.client);
|
||||
// await this.app.client.
|
||||
// loadSettingsPage().
|
||||
// click('=Remove').
|
||||
// waitForVisible(modalTitleSelector).
|
||||
// element('.modal-dialog').click('.btn=Remove').
|
||||
// pause(500).
|
||||
// click('=Remove').
|
||||
// waitForVisible(modalTitleSelector).
|
||||
// element('.modal-dialog').click('.btn=Remove').
|
||||
// pause(500);
|
||||
// const isModalExisting = await this.app.client.isExisting('#newServerModal');
|
||||
// isModalExisting.should.be.true;
|
||||
// });
|
||||
|
||||
// // describe('Server list', () => {
|
||||
// // it.skip('should open the corresponding tab when a server list item is clicked', async () => {
|
||||
// // env.addClientCommands(this.app.client);
|
||||
// // await this.app.client.
|
||||
// // loadSettingsPage().
|
||||
// // click('h4=example').
|
||||
// // pause(1000).
|
||||
// // waitUntilWindowLoaded();
|
||||
// // let indexURL = await this.app.client.getUrl();
|
||||
// // indexURL.should.match(/\/index.html(\?.+)?$/);
|
||||
|
||||
// // let isView0Visible = await this.app.client.isVisible('#mattermostView0');
|
||||
// // isView0Visible.should.be.true;
|
||||
|
||||
// // let isView1Visible = await this.app.client.isVisible('#mattermostView1');
|
||||
// // isView1Visible.should.be.false;
|
||||
|
||||
// // await this.app.client.
|
||||
// // loadSettingsPage().
|
||||
// // click('h4=github').
|
||||
// // pause(1000).
|
||||
// // waitUntilWindowLoaded();
|
||||
// // indexURL = await this.app.client.getUrl();
|
||||
// // indexURL.should.match(/\/index.html(\?.+)?$/);
|
||||
|
||||
// // isView0Visible = await this.app.client.isVisible('#mattermostView0');
|
||||
// // isView0Visible.should.be.false;
|
||||
|
||||
// // isView1Visible = await this.app.client.isVisible('#mattermostView1');
|
||||
// // isView1Visible.should.be.true;
|
||||
// // });
|
||||
// // });
|
||||
|
||||
// describe('Options', () => {
|
||||
// // describe.skip('Hide Menu Bar', () => {
|
||||
// // it('should appear on win32 or linux', async () => {
|
||||
// // const expected = (process.platform === 'win32' || process.platform === 'linux');
|
||||
// // env.addClientCommands(this.app.client);
|
||||
// // await this.app.client.loadSettingsPage();
|
||||
// // const existing = await this.app.client.isExisting('#inputHideMenuBar');
|
||||
// // existing.should.equal(expected);
|
||||
// // });
|
||||
|
||||
// // [true, false].forEach((v) => {
|
||||
// // env.shouldTest(it, env.isOneOf(['win32', 'linux']))(`should be saved and loaded: ${v}`, async () => {
|
||||
// // env.addClientCommands(this.app.client);
|
||||
// // await this.app.client.
|
||||
// // loadSettingsPage().
|
||||
// // scroll('#inputHideMenuBar');
|
||||
// // const isSelected = await this.app.client.isSelected('#inputHideMenuBar');
|
||||
// // if (isSelected !== v) {
|
||||
// // await this.app.client.click('#inputHideMenuBar');
|
||||
// // }
|
||||
|
||||
// // await this.app.client.
|
||||
// // pause(600).
|
||||
// // click('#btnClose').
|
||||
// // pause(1000);
|
||||
|
||||
// // const savedConfig = JSON.parse(fs.readFileSync(env.configFilePath, 'utf8'));
|
||||
// // savedConfig.hideMenuBar.should.equal(v);
|
||||
|
||||
// // let autoHide = await this.app.browserWindow.isMenuBarAutoHide();
|
||||
// // autoHide.should.equal(v);
|
||||
|
||||
// // // confirm actual behavior
|
||||
// // await this.app.restart();
|
||||
// // env.addClientCommands(this.app.client);
|
||||
|
||||
// // autoHide = await this.app.browserWindow.isMenuBarAutoHide();
|
||||
// // autoHide.should.equal(v);
|
||||
|
||||
// // await this.app.loadSettingsPage();
|
||||
// // autoHide = await this.app.client.isSelected('#inputHideMenuBar');
|
||||
// // autoHide.should.equal(v);
|
||||
// // });
|
||||
// // });
|
||||
// // });
|
||||
|
||||
// describe('Start app on login', () => {
|
||||
// it('should appear on win32 or linux', async () => {
|
||||
// const expected = (process.platform === 'win32' || process.platform === 'linux');
|
||||
// env.addClientCommands(this.app.client);
|
||||
// await this.app.client.loadSettingsPage();
|
||||
// const existing = await this.app.client.isExisting('#inputAutoStart');
|
||||
// existing.should.equal(expected);
|
||||
// });
|
||||
// });
|
||||
|
||||
// describe('Show icon in menu bar / notification area', () => {
|
||||
// it('should appear on darwin or linux', async () => {
|
||||
// const expected = (process.platform === 'darwin' || process.platform === 'linux');
|
||||
// env.addClientCommands(this.app.client);
|
||||
// await this.app.client.loadSettingsPage();
|
||||
// const existing = await this.app.client.isExisting('#inputShowTrayIcon');
|
||||
// existing.should.equal(expected);
|
||||
// });
|
||||
|
||||
// describe('Save tray icon setting on mac', () => {
|
||||
// env.shouldTest(it, env.isOneOf(['darwin', 'linux']))('should be saved when it\'s selected', async () => {
|
||||
// env.addClientCommands(this.app.client);
|
||||
// await this.app.browserWindow.setSize(1024, 768); // Resize the window to click the element
|
||||
// await this.app.client.
|
||||
// loadSettingsPage().
|
||||
// click('#inputShowTrayIcon').
|
||||
// waitForAppOptionsAutoSaved();
|
||||
|
||||
// let config0 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8'));
|
||||
// config0.showTrayIcon.should.true;
|
||||
|
||||
// await this.app.client.
|
||||
// click('#inputShowTrayIcon').
|
||||
// waitForAppOptionsAutoSaved();
|
||||
|
||||
// config0 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8'));
|
||||
// config0.showTrayIcon.should.false;
|
||||
// });
|
||||
// });
|
||||
|
||||
// describe('Save tray icon theme on linux', () => {
|
||||
// env.shouldTest(it, process.platform === 'linux')('should be saved when it\'s selected', async () => {
|
||||
// env.addClientCommands(this.app.client);
|
||||
// await this.app.browserWindow.setSize(1024, 768); // Resize the window to click the element
|
||||
// await this.app.client.
|
||||
// loadSettingsPage().
|
||||
// click('#inputShowTrayIcon').
|
||||
// click('input[value="dark"]').
|
||||
// pause(700); // wait auto-save
|
||||
|
||||
// const config0 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8'));
|
||||
// config0.trayIconTheme.should.equal('dark');
|
||||
|
||||
// await this.app.client.
|
||||
// click('input[value="light"]').
|
||||
// pause(700); // wait auto-save
|
||||
|
||||
// const config1 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8'));
|
||||
// config1.trayIconTheme.should.equal('light');
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
|
||||
// describe('Leave app running in notification area when application window is closed', () => {
|
||||
// it('should appear on linux', async () => {
|
||||
// const expected = (process.platform === 'linux');
|
||||
// env.addClientCommands(this.app.client);
|
||||
// await this.app.client.loadSettingsPage();
|
||||
// const existing = await this.app.client.isExisting('#inputMinimizeToTray');
|
||||
// existing.should.equal(expected);
|
||||
// });
|
||||
// });
|
||||
|
||||
// // describe.skip('Toggle window visibility when clicking on the tray icon', () => {
|
||||
// // it('should appear on win32', async () => {
|
||||
// // const expected = (process.platform === 'win32');
|
||||
// // env.addClientCommands(this.app.client);
|
||||
// // await this.app.client.loadSettingsPage();
|
||||
// // const existing = await this.app.client.isExisting('#inputToggleWindowOnTrayIconClick');
|
||||
// // existing.should.equal(expected);
|
||||
// // });
|
||||
// // });
|
||||
|
||||
// describe('Flash app window and taskbar icon when a new message is received', () => {
|
||||
// it('should appear on win32 and linux', async () => {
|
||||
// const expected = (process.platform === 'win32' || process.platform === 'linux');
|
||||
// env.addClientCommands(this.app.client);
|
||||
// await this.app.client.loadSettingsPage();
|
||||
// const existing = await this.app.client.isExisting('#inputflashWindow');
|
||||
// existing.should.equal(expected);
|
||||
// });
|
||||
// });
|
||||
|
||||
// describe('Show red badge on taskbar icon to indicate unread messages', () => {
|
||||
// it('should appear on darwin or win32', async () => {
|
||||
// const expected = (process.platform === 'darwin' || process.platform === 'win32');
|
||||
// env.addClientCommands(this.app.client);
|
||||
// await this.app.client.loadSettingsPage();
|
||||
// const existing = await this.app.client.isExisting('#inputShowUnreadBadge');
|
||||
// existing.should.equal(expected);
|
||||
// });
|
||||
// });
|
||||
|
||||
// describe('Check spelling', () => {
|
||||
// it('should appear and be selectable', async () => {
|
||||
// env.addClientCommands(this.app.client);
|
||||
// await this.app.client.loadSettingsPage();
|
||||
// const existing = await this.app.client.isExisting('#inputSpellChecker');
|
||||
// existing.should.equal(true);
|
||||
|
||||
// const selected = await this.app.client.isSelected('#inputSpellChecker');
|
||||
// selected.should.equal(true);
|
||||
|
||||
// const windowBounds = await this.app.browserWindow.getBounds();
|
||||
// const inputLocation = await this.app.client.getLocation('#inputSpellChecker');
|
||||
// const offset = (inputLocation.y - windowBounds.height) + 100;
|
||||
|
||||
// await this.app.client.
|
||||
// scroll(0, offset).
|
||||
// click('#inputSpellChecker').
|
||||
// pause(5000);
|
||||
// const config1 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8'));
|
||||
// config1.useSpellChecker.should.equal(false);
|
||||
// });
|
||||
// });
|
||||
|
||||
// describe('Enable GPU hardware acceleration', () => {
|
||||
// it('should save selected option', async () => {
|
||||
// const ID_INPUT_ENABLE_HARDWARE_ACCELERATION = '#inputEnableHardwareAcceleration';
|
||||
// env.addClientCommands(this.app.client);
|
||||
// await this.app.client.
|
||||
// loadSettingsPage().
|
||||
// waitForExist(ID_INPUT_ENABLE_HARDWARE_ACCELERATION, 5000).
|
||||
// scroll(ID_INPUT_ENABLE_HARDWARE_ACCELERATION);
|
||||
// const selected = await this.app.client.isSelected(ID_INPUT_ENABLE_HARDWARE_ACCELERATION);
|
||||
// selected.should.equal(true); // default is true
|
||||
|
||||
// await this.app.client.click(ID_INPUT_ENABLE_HARDWARE_ACCELERATION).
|
||||
// waitForVisible('#appOptionsSaveIndicator', 5000).
|
||||
// waitForVisible('#appOptionsSaveIndicator', 5000, true); // at least 2500 ms to disappear
|
||||
// const config0 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8'));
|
||||
// config0.enableHardwareAcceleration.should.equal(false);
|
||||
|
||||
// await this.app.client.click(ID_INPUT_ENABLE_HARDWARE_ACCELERATION).
|
||||
// waitForVisible('#appOptionsSaveIndicator', 5000).
|
||||
// waitForVisible('#appOptionsSaveIndicator', 5000, true); // at least 2500 ms to disappear
|
||||
// const config1 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8'));
|
||||
// config1.enableHardwareAcceleration.should.equal(true);
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
|
||||
// describe('RemoveServerModal', () => {
|
||||
// const modalTitleSelector = '.modal-title=Remove Server';
|
||||
|
||||
// beforeEach(async () => {
|
||||
// env.addClientCommands(this.app.client);
|
||||
// await this.app.client.loadSettingsPage();
|
||||
// const existing = await this.app.client.isExisting(modalTitleSelector);
|
||||
// existing.should.be.false;
|
||||
|
||||
// const visible = await this.app.client.isVisible(modalTitleSelector);
|
||||
// visible.should.be.false;
|
||||
|
||||
// await this.app.client.
|
||||
// click('=Remove').
|
||||
// waitForVisible(modalTitleSelector);
|
||||
// });
|
||||
|
||||
// it('should remove existing team on click Remove', async () => {
|
||||
// await this.app.client.
|
||||
// element('.modal-dialog').click('.btn=Remove').
|
||||
// waitForExist(modalTitleSelector, 5000, true);
|
||||
|
||||
// await this.app.client.waitForVisible('#serversSaveIndicator', 10000, true);
|
||||
|
||||
// const expectedConfig = JSON.parse(JSON.stringify(config.teams.slice(1)));
|
||||
// expectedConfig.forEach((value) => {
|
||||
// value.order--;
|
||||
// });
|
||||
|
||||
// const savedConfig = JSON.parse(fs.readFileSync(env.configFilePath, 'utf8'));
|
||||
// savedConfig.teams.should.deep.equal(expectedConfig);
|
||||
// });
|
||||
|
||||
// it('should NOT remove existing team on click Cancel', async () => {
|
||||
// await this.app.client.
|
||||
// element('.modal-dialog').click('.btn=Cancel').
|
||||
// waitForExist(modalTitleSelector, 5000, true);
|
||||
|
||||
// await this.app.client.waitForVisible('#serversSaveIndicator', 10000, true);
|
||||
|
||||
// const savedConfig = JSON.parse(fs.readFileSync(env.configFilePath, 'utf8'));
|
||||
// savedConfig.teams.should.deep.equal(config.teams);
|
||||
// });
|
||||
|
||||
// it('should disappear on click Close', async () => {
|
||||
// await this.app.client.
|
||||
// element('.modal-dialog').click('button.close').
|
||||
// waitForVisible(modalTitleSelector, 10000, true);
|
||||
// const existing = await this.app.client.isExisting(modalTitleSelector);
|
||||
// existing.should.be.false;
|
||||
// });
|
||||
|
||||
// it('should disappear on click background', async () => {
|
||||
// await this.app.browserWindow.setSize(1024, 768); // Resize the window to click the center of <body>
|
||||
// await this.app.client.
|
||||
// click('body').
|
||||
// waitForVisible(modalTitleSelector, 10000, true);
|
||||
// const existing = await this.app.client.isExisting(modalTitleSelector);
|
||||
// existing.should.be.false;
|
||||
// });
|
||||
// });
|
||||
|
||||
// describe('NewTeamModal', () => {
|
||||
// beforeEach(() => {
|
||||
// env.addClientCommands(this.app.client);
|
||||
// return this.app.client.
|
||||
// loadSettingsPage().
|
||||
// click('#addNewServer').
|
||||
// pause(1000);
|
||||
// });
|
||||
|
||||
// it('should open the new server modal', () => {
|
||||
// return this.app.client.isExisting('#newServerModal').then((existing) => {
|
||||
// existing.should.be.true;
|
||||
// });
|
||||
// });
|
||||
|
||||
// it('should close the window after clicking cancel', () => {
|
||||
// return this.app.client.
|
||||
// click('#cancelNewServerModal').
|
||||
// waitForExist('#newServerModal', 10000, true).
|
||||
// isExisting('#newServerModal').then((existing) => {
|
||||
// existing.should.be.false;
|
||||
// });
|
||||
// });
|
||||
|
||||
// it('should not be valid if no team name has been set', () => {
|
||||
// return this.app.client.
|
||||
// click('#saveNewServerModal').
|
||||
// waitForExist('.has-error #teamNameInput', 10000).
|
||||
// isExisting('.has-error #teamNameInput').then((existing) => {
|
||||
// existing.should.be.true;
|
||||
// });
|
||||
// });
|
||||
|
||||
// it('should not be valid if no server address has been set', () => {
|
||||
// return this.app.client.
|
||||
// click('#saveNewServerModal').
|
||||
// waitForExist('.has-error #teamUrlInput', 10000).
|
||||
// isExisting('.has-error #teamUrlInput').then((existing) => {
|
||||
// existing.should.be.true;
|
||||
// });
|
||||
// });
|
||||
|
||||
// describe('Valid server name', () => {
|
||||
// beforeEach(() => {
|
||||
// return this.app.client.
|
||||
// setValue('#teamNameInput', 'TestTeam').
|
||||
// click('#saveNewServerModal');
|
||||
// });
|
||||
|
||||
// it('should not be marked invalid', () => {
|
||||
// return this.app.client.
|
||||
// isExisting('.has-error #teamNameInput').then((existing) => {
|
||||
// existing.should.be.false;
|
||||
// });
|
||||
// });
|
||||
|
||||
// it('should not be possible to click save', () => {
|
||||
// return this.app.client.
|
||||
// getAttribute('#saveNewServerModal', 'disabled').then((disabled) => {
|
||||
// disabled.should.equal('true');
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
|
||||
// describe('Valid server url', () => {
|
||||
// beforeEach(() => {
|
||||
// return this.app.client.
|
||||
// setValue('#teamUrlInput', 'http://example.org').
|
||||
// click('#saveNewServerModal');
|
||||
// });
|
||||
|
||||
// it('should be valid', () => {
|
||||
// return this.app.client.
|
||||
// isExisting('.has-error #teamUrlInput').then((existing) => {
|
||||
// existing.should.be.false;
|
||||
// });
|
||||
// });
|
||||
|
||||
// it('should not be possible to click save', () => {
|
||||
// return this.app.client.
|
||||
// getAttribute('#saveNewServerModal', 'disabled').then((disabled) => {
|
||||
// disabled.should.equal('true');
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
|
||||
// it('should not be valid if an invalid server address has been set', () => {
|
||||
// return this.app.client.
|
||||
// setValue('#teamUrlInput', 'superInvalid url').
|
||||
// click('#saveNewServerModal').
|
||||
// pause(500).
|
||||
// isExisting('.has-error #teamUrlInput').then((existing) => {
|
||||
// existing.should.be.true;
|
||||
// });
|
||||
// });
|
||||
|
||||
// describe('Valid Team Settings', () => {
|
||||
// beforeEach(() => {
|
||||
// return this.app.client.
|
||||
// setValue('#teamUrlInput', 'http://example.org').
|
||||
// setValue('#teamNameInput', 'TestTeam');
|
||||
// });
|
||||
|
||||
// it('should be possible to click add', () => {
|
||||
// return this.app.client.
|
||||
// getAttribute('#saveNewServerModal', 'disabled').then((disabled) => {
|
||||
// (disabled === null).should.be.true;
|
||||
// });
|
||||
// });
|
||||
|
||||
// it('should add the team to the config file', async () => {
|
||||
// await this.app.client.
|
||||
// click('#saveNewServerModal').
|
||||
// waitForVisible('#newServerModal', 10000, true).
|
||||
// waitForVisible('#serversSaveIndicator', 10000).
|
||||
// waitForVisible('#serversSaveIndicator', 10000, true). // at least 2500 ms to disappear
|
||||
// waitUntilWindowLoaded();
|
||||
|
||||
// const savedConfig = JSON.parse(fs.readFileSync(env.configFilePath, 'utf8'));
|
||||
// savedConfig.teams.should.deep.contain({
|
||||
// name: 'TestTeam',
|
||||
// url: 'http://example.org',
|
||||
// order: 2,
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
const {SHOW_SETTINGS_WINDOW} = require('../../../src/common/communication');
|
||||
|
||||
const env = require('../../modules/environment');
|
||||
const {asyncSleep} = require('../../modules/utils');
|
||||
|
||||
describe('renderer/settings.html', function desc() {
|
||||
this.timeout(30000);
|
||||
|
||||
const config = {
|
||||
version: 3,
|
||||
teams: [{
|
||||
name: 'example',
|
||||
url: env.mattermostURL,
|
||||
order: 0,
|
||||
tabs: [
|
||||
{
|
||||
name: 'TAB_MESSAGING',
|
||||
order: 0,
|
||||
isOpen: true,
|
||||
},
|
||||
{
|
||||
name: 'TAB_FOCALBOARD',
|
||||
order: 1,
|
||||
isOpen: true,
|
||||
},
|
||||
{
|
||||
name: 'TAB_PLAYBOOKS',
|
||||
order: 2,
|
||||
isOpen: true,
|
||||
},
|
||||
],
|
||||
lastActiveTab: 0,
|
||||
}, {
|
||||
name: 'github',
|
||||
url: 'https://github.com/',
|
||||
order: 1,
|
||||
tabs: [
|
||||
{
|
||||
name: 'TAB_MESSAGING',
|
||||
order: 0,
|
||||
isOpen: true,
|
||||
},
|
||||
{
|
||||
name: 'TAB_FOCALBOARD',
|
||||
order: 1,
|
||||
isOpen: true,
|
||||
},
|
||||
{
|
||||
name: 'TAB_PLAYBOOKS',
|
||||
order: 2,
|
||||
isOpen: true,
|
||||
},
|
||||
],
|
||||
lastActiveTab: 0,
|
||||
}],
|
||||
showTrayIcon: false,
|
||||
trayIconTheme: 'light',
|
||||
minimizeToTray: false,
|
||||
notifications: {
|
||||
flashWindow: 0,
|
||||
bounceIcon: false,
|
||||
bounceIconType: 'informational',
|
||||
},
|
||||
showUnreadBadge: true,
|
||||
useSpellChecker: true,
|
||||
enableHardwareAcceleration: true,
|
||||
autostart: true,
|
||||
darkMode: false,
|
||||
lastActiveTeam: 0,
|
||||
spellCheckerLocales: [],
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
env.createTestUserDataDir();
|
||||
env.cleanTestConfig();
|
||||
fs.writeFileSync(env.configFilePath, JSON.stringify(config));
|
||||
await asyncSleep(1000);
|
||||
this.app = await env.getApp();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (this.app) {
|
||||
await this.app.close();
|
||||
}
|
||||
});
|
||||
|
||||
describe('Options', () => {
|
||||
describe('Start app on login', () => {
|
||||
it('should appear on win32 or linux', async () => {
|
||||
const expected = (process.platform === 'win32' || process.platform === 'linux');
|
||||
this.app.evaluate(({ipcMain}, showWindow) => {
|
||||
ipcMain.emit(showWindow);
|
||||
}, SHOW_SETTINGS_WINDOW);
|
||||
const settingsWindow = await this.app.waitForEvent('window', {
|
||||
predicate: (window) => window.url().includes('settings'),
|
||||
});
|
||||
await settingsWindow.waitForSelector('.settingsPage.container');
|
||||
const existing = await settingsWindow.isVisible('#inputAutoStart');
|
||||
existing.should.equal(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Show icon in menu bar / notification area', () => {
|
||||
it('should appear on darwin or linux', async () => {
|
||||
const expected = (process.platform === 'darwin' || process.platform === 'linux');
|
||||
this.app.evaluate(({ipcMain}, showWindow) => {
|
||||
ipcMain.emit(showWindow);
|
||||
}, SHOW_SETTINGS_WINDOW);
|
||||
const settingsWindow = await this.app.waitForEvent('window', {
|
||||
predicate: (window) => window.url().includes('settings'),
|
||||
});
|
||||
await settingsWindow.waitForSelector('.settingsPage.container');
|
||||
const existing = await settingsWindow.isVisible('#inputShowTrayIcon');
|
||||
existing.should.equal(expected);
|
||||
});
|
||||
|
||||
describe('Save tray icon setting on mac', () => {
|
||||
env.shouldTest(it, env.isOneOf(['darwin', 'linux']))('should be saved when it\'s selected', async () => {
|
||||
this.app.evaluate(({ipcMain}, showWindow) => {
|
||||
ipcMain.emit(showWindow);
|
||||
}, SHOW_SETTINGS_WINDOW);
|
||||
const settingsWindow = await this.app.waitForEvent('window', {
|
||||
predicate: (window) => window.url().includes('settings'),
|
||||
});
|
||||
await settingsWindow.waitForSelector('.settingsPage.container');
|
||||
await settingsWindow.click('#inputShowTrayIcon');
|
||||
await settingsWindow.waitForSelector('.IndicatorContainer :text("Saved")');
|
||||
|
||||
let config0 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8'));
|
||||
config0.showTrayIcon.should.true;
|
||||
|
||||
await settingsWindow.click('#inputShowTrayIcon');
|
||||
await settingsWindow.waitForSelector('.IndicatorContainer :text("Saved")');
|
||||
|
||||
config0 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8'));
|
||||
config0.showTrayIcon.should.false;
|
||||
});
|
||||
});
|
||||
|
||||
describe('Save tray icon theme on linux', () => {
|
||||
env.shouldTest(it, process.platform === 'linux')('should be saved when it\'s selected', async () => {
|
||||
this.app.evaluate(({ipcMain}, showWindow) => {
|
||||
ipcMain.emit(showWindow);
|
||||
}, SHOW_SETTINGS_WINDOW);
|
||||
const settingsWindow = await this.app.waitForEvent('window', {
|
||||
predicate: (window) => window.url().includes('settings'),
|
||||
});
|
||||
await settingsWindow.waitForSelector('.settingsPage.container');
|
||||
await settingsWindow.click('#inputShowTrayIcon');
|
||||
await settingsWindow.click('input[value="dark"]');
|
||||
await settingsWindow.waitForSelector('.IndicatorContainer :text("Saved")');
|
||||
|
||||
const config0 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8'));
|
||||
config0.trayIconTheme.should.equal('dark');
|
||||
|
||||
await settingsWindow.click('input[value="light"]');
|
||||
await settingsWindow.waitForSelector('.IndicatorContainer :text("Saved")');
|
||||
|
||||
const config1 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8'));
|
||||
config1.trayIconTheme.should.equal('light');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Leave app running in notification area when application window is closed', () => {
|
||||
it('should appear on linux', async () => {
|
||||
const expected = (process.platform === 'linux');
|
||||
this.app.evaluate(({ipcMain}, showWindow) => {
|
||||
ipcMain.emit(showWindow);
|
||||
}, SHOW_SETTINGS_WINDOW);
|
||||
const settingsWindow = await this.app.waitForEvent('window', {
|
||||
predicate: (window) => window.url().includes('settings'),
|
||||
});
|
||||
await settingsWindow.waitForSelector('.settingsPage.container');
|
||||
const existing = await settingsWindow.isVisible('#inputMinimizeToTray');
|
||||
existing.should.equal(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Flash app window and taskbar icon when a new message is received', () => {
|
||||
it('should appear on win32 and linux', async () => {
|
||||
const expected = (process.platform === 'win32' || process.platform === 'linux');
|
||||
this.app.evaluate(({ipcMain}, showWindow) => {
|
||||
ipcMain.emit(showWindow);
|
||||
}, SHOW_SETTINGS_WINDOW);
|
||||
const settingsWindow = await this.app.waitForEvent('window', {
|
||||
predicate: (window) => window.url().includes('settings'),
|
||||
});
|
||||
await settingsWindow.waitForSelector('.settingsPage.container');
|
||||
const existing = await settingsWindow.isVisible('#inputflashWindow');
|
||||
existing.should.equal(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Show red badge on taskbar icon to indicate unread messages', () => {
|
||||
it('should appear on darwin or win32', async () => {
|
||||
const expected = (process.platform === 'darwin' || process.platform === 'win32');
|
||||
this.app.evaluate(({ipcMain}, showWindow) => {
|
||||
ipcMain.emit(showWindow);
|
||||
}, SHOW_SETTINGS_WINDOW);
|
||||
const settingsWindow = await this.app.waitForEvent('window', {
|
||||
predicate: (window) => window.url().includes('settings'),
|
||||
});
|
||||
await settingsWindow.waitForSelector('.settingsPage.container');
|
||||
const existing = await settingsWindow.isVisible('#inputShowUnreadBadge');
|
||||
existing.should.equal(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Check spelling', () => {
|
||||
it('should appear and be selectable', async () => {
|
||||
this.app.evaluate(({ipcMain}, showWindow) => {
|
||||
ipcMain.emit(showWindow);
|
||||
}, SHOW_SETTINGS_WINDOW);
|
||||
const settingsWindow = await this.app.waitForEvent('window', {
|
||||
predicate: (window) => window.url().includes('settings'),
|
||||
});
|
||||
await settingsWindow.waitForSelector('.settingsPage.container');
|
||||
const existing = await settingsWindow.isVisible('#inputSpellChecker');
|
||||
existing.should.equal(true);
|
||||
|
||||
const selected = await settingsWindow.isChecked('#inputSpellChecker');
|
||||
selected.should.equal(true);
|
||||
|
||||
await settingsWindow.click('#inputSpellChecker');
|
||||
await settingsWindow.waitForSelector('.IndicatorContainer :text("Saved")');
|
||||
|
||||
const config1 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8'));
|
||||
config1.useSpellChecker.should.equal(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Enable GPU hardware acceleration', () => {
|
||||
it('should save selected option', async () => {
|
||||
const ID_INPUT_ENABLE_HARDWARE_ACCELERATION = '#inputEnableHardwareAcceleration';
|
||||
this.app.evaluate(({ipcMain}, showWindow) => {
|
||||
ipcMain.emit(showWindow);
|
||||
}, SHOW_SETTINGS_WINDOW);
|
||||
const settingsWindow = await this.app.waitForEvent('window', {
|
||||
predicate: (window) => window.url().includes('settings'),
|
||||
});
|
||||
await settingsWindow.waitForSelector('.settingsPage.container');
|
||||
const selected = await settingsWindow.isChecked(ID_INPUT_ENABLE_HARDWARE_ACCELERATION);
|
||||
selected.should.equal(true); // default is true
|
||||
|
||||
await settingsWindow.click(ID_INPUT_ENABLE_HARDWARE_ACCELERATION);
|
||||
await settingsWindow.waitForSelector('.IndicatorContainer :text("Saved")');
|
||||
const config0 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8'));
|
||||
config0.enableHardwareAcceleration.should.equal(false);
|
||||
|
||||
await settingsWindow.click(ID_INPUT_ENABLE_HARDWARE_ACCELERATION);
|
||||
await settingsWindow.waitForSelector('.IndicatorContainer :text("Saved")');
|
||||
const config1 = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8'));
|
||||
config1.enableHardwareAcceleration.should.equal(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
116
test/specs/config_test.js
Normal file
116
test/specs/config_test.js
Normal file
|
@ -0,0 +1,116 @@
|
|||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
const env = require('../modules/environment');
|
||||
|
||||
describe('config', function desc() {
|
||||
this.timeout(30000);
|
||||
|
||||
beforeEach(async () => {
|
||||
env.createTestUserDataDir();
|
||||
env.cleanTestConfig();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (this.app) {
|
||||
try {
|
||||
await this.app.close();
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch (err) {}
|
||||
}
|
||||
});
|
||||
|
||||
it('should show servers in dropdown when there is config file', async () => {
|
||||
const config = {
|
||||
version: 3,
|
||||
teams: [{
|
||||
name: 'example',
|
||||
url: env.mattermostURL,
|
||||
order: 0,
|
||||
tabs: [
|
||||
{
|
||||
name: 'TAB_MESSAGING',
|
||||
order: 0,
|
||||
isOpen: true,
|
||||
},
|
||||
{
|
||||
name: 'TAB_FOCALBOARD',
|
||||
order: 1,
|
||||
isOpen: true,
|
||||
},
|
||||
{
|
||||
name: 'TAB_PLAYBOOKS',
|
||||
order: 2,
|
||||
isOpen: true,
|
||||
},
|
||||
],
|
||||
lastActiveTab: 0,
|
||||
}, {
|
||||
name: 'github',
|
||||
url: 'https://github.com/',
|
||||
order: 1,
|
||||
tabs: [
|
||||
{
|
||||
name: 'TAB_MESSAGING',
|
||||
order: 0,
|
||||
isOpen: true,
|
||||
},
|
||||
{
|
||||
name: 'TAB_FOCALBOARD',
|
||||
order: 1,
|
||||
isOpen: true,
|
||||
},
|
||||
{
|
||||
name: 'TAB_PLAYBOOKS',
|
||||
order: 2,
|
||||
isOpen: true,
|
||||
},
|
||||
],
|
||||
lastActiveTab: 0,
|
||||
}],
|
||||
showTrayIcon: false,
|
||||
trayIconTheme: 'light',
|
||||
minimizeToTray: false,
|
||||
notifications: {
|
||||
flashWindow: 0,
|
||||
bounceIcon: false,
|
||||
bounceIconType: 'informational',
|
||||
},
|
||||
showUnreadBadge: true,
|
||||
useSpellChecker: true,
|
||||
enableHardwareAcceleration: true,
|
||||
autostart: true,
|
||||
darkMode: false,
|
||||
lastActiveTeam: 0,
|
||||
spellCheckerLocales: [],
|
||||
};
|
||||
fs.writeFileSync(env.configFilePath, JSON.stringify(config));
|
||||
this.app = await env.getApp();
|
||||
const mainWindow = this.app.windows().find((window) => window.url().includes('index'));
|
||||
const dropdownButtonText = await mainWindow.innerText('.TeamDropdownButton');
|
||||
dropdownButtonText.should.equal('example');
|
||||
await this.app.close();
|
||||
});
|
||||
|
||||
it('should upgrade v0 config file', async () => {
|
||||
const Config = require('../../src/common/config').default;
|
||||
const newConfig = new Config(env.configFilePath);
|
||||
const oldConfig = {
|
||||
url: env.mattermostURL,
|
||||
};
|
||||
fs.writeFileSync(env.configFilePath, JSON.stringify(oldConfig));
|
||||
this.app = await env.getApp();
|
||||
const mainWindow = this.app.windows().find((window) => window.url().includes('index'));
|
||||
const dropdownButtonText = await mainWindow.innerText('.TeamDropdownButton:has-text("Primary team")');
|
||||
dropdownButtonText.should.equal('Primary team');
|
||||
|
||||
const str = fs.readFileSync(env.configFilePath, 'utf8');
|
||||
const upgradedConfig = JSON.parse(str);
|
||||
upgradedConfig.version.should.equal(newConfig.defaultData.version);
|
||||
await this.app.close();
|
||||
});
|
||||
});
|
|
@ -2,9 +2,13 @@
|
|||
// See LICENSE.txt for license information.
|
||||
|
||||
import './app_test.js';
|
||||
import './security_test.js';
|
||||
import './spellchecker_test.js';
|
||||
import './config_test.js';
|
||||
import './mattermost_test.js';
|
||||
import './window_test.js';
|
||||
|
||||
import './browser/index_test.js';
|
||||
import './browser/modal_test.js';
|
||||
import './browser/settings_test.js';
|
||||
|
||||
import './main/user_activity_monitor_test.js';
|
||||
import './utils/util_test.js';
|
||||
|
|
106
test/specs/mattermost_test.js
Normal file
106
test/specs/mattermost_test.js
Normal file
|
@ -0,0 +1,106 @@
|
|||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
const env = require('../modules/environment');
|
||||
const {asyncSleep} = require('../modules/utils');
|
||||
|
||||
describe('mattermost', function desc() {
|
||||
this.timeout(30000);
|
||||
|
||||
const config = {
|
||||
version: 3,
|
||||
teams: [{
|
||||
name: 'example',
|
||||
url: env.mattermostURL,
|
||||
order: 0,
|
||||
tabs: [
|
||||
{
|
||||
name: 'TAB_MESSAGING',
|
||||
order: 0,
|
||||
isOpen: true,
|
||||
},
|
||||
{
|
||||
name: 'TAB_FOCALBOARD',
|
||||
order: 1,
|
||||
isOpen: false,
|
||||
},
|
||||
{
|
||||
name: 'TAB_PLAYBOOKS',
|
||||
order: 2,
|
||||
isOpen: false,
|
||||
},
|
||||
],
|
||||
lastActiveTab: 0,
|
||||
}, {
|
||||
name: 'github',
|
||||
url: 'https://github.com/',
|
||||
order: 1,
|
||||
tabs: [
|
||||
{
|
||||
name: 'TAB_MESSAGING',
|
||||
order: 0,
|
||||
isOpen: true,
|
||||
},
|
||||
{
|
||||
name: 'TAB_FOCALBOARD',
|
||||
order: 1,
|
||||
isOpen: false,
|
||||
},
|
||||
{
|
||||
name: 'TAB_PLAYBOOKS',
|
||||
order: 2,
|
||||
isOpen: false,
|
||||
},
|
||||
],
|
||||
lastActiveTab: 0,
|
||||
}],
|
||||
showTrayIcon: false,
|
||||
trayIconTheme: 'light',
|
||||
minimizeToTray: false,
|
||||
notifications: {
|
||||
flashWindow: 0,
|
||||
bounceIcon: false,
|
||||
bounceIconType: 'informational',
|
||||
},
|
||||
showUnreadBadge: true,
|
||||
useSpellChecker: true,
|
||||
enableHardwareAcceleration: true,
|
||||
autostart: true,
|
||||
darkMode: false,
|
||||
lastActiveTeam: 0,
|
||||
spellCheckerLocales: [],
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
env.cleanDataDir();
|
||||
env.createTestUserDataDir();
|
||||
env.cleanTestConfig();
|
||||
fs.writeFileSync(env.configFilePath, JSON.stringify(config));
|
||||
await asyncSleep(1000);
|
||||
this.app = await env.getApp();
|
||||
this.serverMap = await env.getServerMap(this.app);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (this.app) {
|
||||
await this.app.close();
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: enable when we have a server to test against
|
||||
it.skip('Control+F should focus the search bar in Mattermost', async () => {
|
||||
const loadingScreen = this.app.windows().find((window) => window.url().includes('loadingScreen'));
|
||||
await loadingScreen.waitForSelector('.LoadingScreen', {state: 'hidden'});
|
||||
const firstServer = this.serverMap[`${config.teams[0].name}___TAB_MESSAGING`].win;
|
||||
await env.loginToMattermost(firstServer);
|
||||
await firstServer.waitForSelector('#searchBox');
|
||||
await firstServer.press('body', process.platform === 'darwin' ? 'Meta+F' : 'Control+F');
|
||||
const isFocused = await firstServer.$eval('#searchBox', (el) => el === document.activeElement);
|
||||
isFocused.should.be.true;
|
||||
const text = await firstServer.inputValue('#searchBox');
|
||||
text.should.include('in:');
|
||||
});
|
||||
});
|
143
test/specs/menu_test.js
Normal file
143
test/specs/menu_test.js
Normal file
|
@ -0,0 +1,143 @@
|
|||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
// const http = require('http');
|
||||
// const path = require('path');
|
||||
|
||||
const robot = require('robotjs');
|
||||
|
||||
const env = require('../modules/environment');
|
||||
const {asyncSleep} = require('../modules/utils');
|
||||
|
||||
describe('mattermost', function desc() {
|
||||
this.timeout(30000);
|
||||
|
||||
const config = {
|
||||
version: 3,
|
||||
teams: [{
|
||||
name: 'example',
|
||||
url: env.mattermostURL,
|
||||
order: 0,
|
||||
tabs: [
|
||||
{
|
||||
name: 'TAB_MESSAGING',
|
||||
order: 0,
|
||||
isOpen: true,
|
||||
},
|
||||
{
|
||||
name: 'TAB_FOCALBOARD',
|
||||
order: 1,
|
||||
isOpen: false,
|
||||
},
|
||||
{
|
||||
name: 'TAB_PLAYBOOKS',
|
||||
order: 2,
|
||||
isOpen: false,
|
||||
},
|
||||
],
|
||||
lastActiveTab: 0,
|
||||
}, {
|
||||
name: 'github',
|
||||
url: 'https://github.com/',
|
||||
order: 1,
|
||||
tabs: [
|
||||
{
|
||||
name: 'TAB_MESSAGING',
|
||||
order: 0,
|
||||
isOpen: true,
|
||||
},
|
||||
{
|
||||
name: 'TAB_FOCALBOARD',
|
||||
order: 1,
|
||||
isOpen: false,
|
||||
},
|
||||
{
|
||||
name: 'TAB_PLAYBOOKS',
|
||||
order: 2,
|
||||
isOpen: false,
|
||||
},
|
||||
],
|
||||
lastActiveTab: 0,
|
||||
}],
|
||||
showTrayIcon: false,
|
||||
trayIconTheme: 'light',
|
||||
minimizeToTray: false,
|
||||
notifications: {
|
||||
flashWindow: 0,
|
||||
bounceIcon: false,
|
||||
bounceIconType: 'informational',
|
||||
},
|
||||
showUnreadBadge: true,
|
||||
useSpellChecker: true,
|
||||
enableHardwareAcceleration: true,
|
||||
autostart: true,
|
||||
darkMode: false,
|
||||
lastActiveTeam: 0,
|
||||
spellCheckerLocales: [],
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
env.cleanDataDir();
|
||||
env.createTestUserDataDir();
|
||||
env.cleanTestConfig();
|
||||
fs.writeFileSync(env.configFilePath, JSON.stringify(config));
|
||||
await asyncSleep(1000);
|
||||
this.app = await env.getApp();
|
||||
this.serverMap = await env.getServerMap(this.app);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (this.app) {
|
||||
await this.app.close();
|
||||
}
|
||||
});
|
||||
|
||||
it('should reload page when pressing Ctrl+R', async () => {
|
||||
const mainWindow = await this.app.firstWindow();
|
||||
const browserWindow = await this.app.browserWindow(mainWindow);
|
||||
const webContentsId = this.serverMap[`${config.teams[0].name}___TAB_MESSAGING`].webContentsId;
|
||||
|
||||
const loadingScreen = this.app.windows().find((window) => window.url().includes('loadingScreen'));
|
||||
await loadingScreen.waitForSelector('.LoadingScreen', {state: 'hidden'});
|
||||
const check = browserWindow.evaluate(async (window, id) => {
|
||||
const promise = new Promise((resolve) => {
|
||||
const browserView = window.getBrowserViews().find((view) => view.webContents.id === id);
|
||||
browserView.webContents.on('did-finish-load', () => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
await promise;
|
||||
return true;
|
||||
}, webContentsId);
|
||||
await asyncSleep(500);
|
||||
robot.keyTap('r', ['control']);
|
||||
const result = await check;
|
||||
result.should.be.true;
|
||||
});
|
||||
|
||||
it('should reload page when pressing Ctrl+Shift+R', async () => {
|
||||
const mainWindow = await this.app.firstWindow();
|
||||
const browserWindow = await this.app.browserWindow(mainWindow);
|
||||
const webContentsId = this.serverMap[`${config.teams[0].name}___TAB_MESSAGING`].webContentsId;
|
||||
|
||||
const loadingScreen = this.app.windows().find((window) => window.url().includes('loadingScreen'));
|
||||
await loadingScreen.waitForSelector('.LoadingScreen', {state: 'hidden'});
|
||||
const check = browserWindow.evaluate(async (window, id) => {
|
||||
const promise = new Promise((resolve) => {
|
||||
const browserView = window.getBrowserViews().find((view) => view.webContents.id === id);
|
||||
browserView.webContents.on('did-finish-load', () => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
await promise;
|
||||
return true;
|
||||
}, webContentsId);
|
||||
await asyncSleep(500);
|
||||
robot.keyTap('r', ['control', 'shift']);
|
||||
const result = await check;
|
||||
result.should.be.true;
|
||||
});
|
||||
});
|
|
@ -1,126 +0,0 @@
|
|||
// Copyright (c) 2015-2016 Yuya Ochiai
|
||||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
'use strict';
|
||||
|
||||
// const fs = require('fs');
|
||||
|
||||
// const path = require('path');
|
||||
// const http = require('http');
|
||||
|
||||
// const env = require('../modules/environment');
|
||||
|
||||
// describe.skip('security', function desc() {
|
||||
// this.timeout(30000);
|
||||
|
||||
// const serverPort = 8181;
|
||||
// const testURL = `http://localhost:${serverPort}`;
|
||||
|
||||
// const config = {
|
||||
// version: 2,
|
||||
// teams: [{
|
||||
// name: 'example_1',
|
||||
// url: testURL,
|
||||
// order: 0,
|
||||
// }, {
|
||||
// name: 'example_2',
|
||||
// url: testURL,
|
||||
// order: 1,
|
||||
// }],
|
||||
// };
|
||||
|
||||
// before(() => {
|
||||
// this.server = http.createServer((req, res) => {
|
||||
// res.writeHead(200, {
|
||||
// 'Content-Type': 'text/html',
|
||||
// });
|
||||
// res.end(fs.readFileSync(path.resolve(env.sourceRootDir, 'test/modules/test.html'), 'utf-8'));
|
||||
// }).listen(serverPort, '127.0.0.1');
|
||||
// });
|
||||
|
||||
// beforeEach(() => {
|
||||
// fs.writeFileSync(env.configFilePath, JSON.stringify(config));
|
||||
// this.app = env.getSpectronApp();
|
||||
// return this.app.start();
|
||||
// });
|
||||
|
||||
// afterEach(() => {
|
||||
// if (this.app && this.app.isRunning()) {
|
||||
// return this.app.stop();
|
||||
// }
|
||||
// return true;
|
||||
// });
|
||||
|
||||
// after((done) => {
|
||||
// this.server.close(done);
|
||||
// });
|
||||
|
||||
// it('should NOT be able to call Node.js API in webview', () => {
|
||||
// env.addClientCommands(this.app.client);
|
||||
|
||||
// // webview is handled as a window by chromedriver.
|
||||
// return this.app.client.
|
||||
// windowByIndex(1).isNodeEnabled().then((enabled) => {
|
||||
// enabled.should.be.false;
|
||||
// }).
|
||||
// windowByIndex(2).isNodeEnabled().then((enabled) => {
|
||||
// enabled.should.be.false;
|
||||
// }).
|
||||
// windowByIndex(0).
|
||||
// getAttribute('webview', 'nodeintegration').then((nodeintegration) => {
|
||||
// // nodeintegration is an array of string
|
||||
// nodeintegration.forEach((n) => {
|
||||
// n.should.equal('false');
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
|
||||
// it('should NOT be able to call Node.js API in a new window', () => {
|
||||
// env.addClientCommands(this.app.client);
|
||||
// const client = this.app.client;
|
||||
// return this.app.client.
|
||||
// windowByIndex(1). // in the first webview
|
||||
// execute(() => {
|
||||
// open_window();
|
||||
// }).
|
||||
// waitUntil(() => {
|
||||
// return client.windowHandles().then((handles) => {
|
||||
// return handles.value.length === 4;
|
||||
// });
|
||||
// }, 5000, 'expected a new window').
|
||||
// windowByIndex(3).isNodeEnabled().then((enabled) => {
|
||||
// enabled.should.be.false;
|
||||
// });
|
||||
// });
|
||||
|
||||
// it('should NOT be able to call eval() in any window', () => {
|
||||
// env.addClientCommands(this.app.client);
|
||||
// const tryEval = (index) => {
|
||||
// return this.app.client.
|
||||
// windowByIndex(index).
|
||||
// execute(() => {
|
||||
// return eval('1 + 1');
|
||||
// }).then((result) => {
|
||||
// throw new Error(`Promise was unexpectedly fulfilled (result: ${result})`);
|
||||
// }, (error) => {
|
||||
// (error !== null).should.be.true;
|
||||
// });
|
||||
// };
|
||||
// const tryEvalInSettingsPage = () => {
|
||||
// return this.app.client.
|
||||
// windowByIndex(0).
|
||||
// loadSettingsPage().
|
||||
// execute(() => {
|
||||
// return eval('1 + 1');
|
||||
// }).then((result) => {
|
||||
// throw new Error(`Promise was unexpectedly fulfilled (result: ${result})`);
|
||||
// }, (error) => {
|
||||
// (error !== null).should.be.true;
|
||||
// });
|
||||
// };
|
||||
// return Promise.all([
|
||||
// tryEval(0),
|
||||
// tryEvalInSettingsPage(),
|
||||
// ]);
|
||||
// });
|
||||
// });
|
|
@ -1,152 +0,0 @@
|
|||
// Copyright (c) 2015-2016 Yuya Ochiai
|
||||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
//import path from 'path';
|
||||
|
||||
// TODO: reenable with the new spellchecker
|
||||
|
||||
// describe('main/Spellchecker.js', function() {
|
||||
// describe('getSpellCheckerLocale()', () => {
|
||||
// it('should return recognized locale', () => {
|
||||
// // SpellChecker.getSpellCheckerLocale('en').should.equal('en-US');
|
||||
// // SpellChecker.getSpellCheckerLocale('en-US').should.equal('en-US');
|
||||
|
||||
// // SpellChecker.getSpellCheckerLocale('fr').should.equal('fr-FR');
|
||||
// // SpellChecker.getSpellCheckerLocale('fr-FR').should.equal('fr-FR');
|
||||
|
||||
// // SpellChecker.getSpellCheckerLocale('de').should.equal('de-DE');
|
||||
// // SpellChecker.getSpellCheckerLocale('de-DE').should.equal('de-DE');
|
||||
|
||||
// // SpellChecker.getSpellCheckerLocale('es').should.equal('es-ES');
|
||||
// // SpellChecker.getSpellCheckerLocale('es-ES').should.equal('es-ES');
|
||||
|
||||
// // SpellChecker.getSpellCheckerLocale('nl').should.equal('nl-NL');
|
||||
// // SpellChecker.getSpellCheckerLocale('nl-NL').should.equal('nl-NL');
|
||||
|
||||
// // SpellChecker.getSpellCheckerLocale('pl').should.equal('pl-PL');
|
||||
// // SpellChecker.getSpellCheckerLocale('pl-PL').should.equal('pl-PL');
|
||||
// // SpellChecker.getSpellCheckerLocale('pt').should.equal('pt-BR');
|
||||
// // SpellChecker.getSpellCheckerLocale('pt-BR').should.equal('pt-BR');
|
||||
|
||||
// // SpellChecker.getSpellCheckerLocale('ja').should.equal('en-US');
|
||||
// // SpellChecker.getSpellCheckerLocale('ja-JP').should.equal('en-US');
|
||||
|
||||
// // SpellChecker.getSpellCheckerLocale('it').should.equal('it-IT');
|
||||
// // SpellChecker.getSpellCheckerLocale('it-IT').should.equal('it-IT');
|
||||
// });
|
||||
// });
|
||||
|
||||
// describe('en-US', function() {
|
||||
// const spellchecker = null;
|
||||
|
||||
// // before(function(done) {
|
||||
// // // spellchecker = new SpellChecker(
|
||||
// // // 'en-US',
|
||||
// // // path.resolve(__dirname, '../../src/node_modules/simple-spellchecker/dict'),
|
||||
// // // done
|
||||
// // // );
|
||||
// // });
|
||||
|
||||
// it('should spellcheck', function() {
|
||||
// // https://github.com/jfmdev/simple-spellchecker/issues/3
|
||||
// spellchecker.spellCheck('spell').should.equal(true);
|
||||
// spellchecker.spellCheck('spel').should.equal(false);
|
||||
// spellchecker.spellCheck('December').should.equal(true);
|
||||
// spellchecker.spellCheck('december').should.equal(true);
|
||||
// spellchecker.spellCheck('English').should.equal(true);
|
||||
// spellchecker.spellCheck('Japan').should.equal(true);
|
||||
// });
|
||||
|
||||
// it('should allow contractions', function() {
|
||||
// spellchecker.spellCheck("shouldn't").should.equal(true);
|
||||
// spellchecker.spellCheck('shouldn').should.equal(true);
|
||||
// });
|
||||
|
||||
// it('should allow numerals', function() {
|
||||
// spellchecker.spellCheck('1').should.equal(true);
|
||||
// spellchecker.spellCheck('-100').should.equal(true);
|
||||
// spellchecker.spellCheck('3.14').should.equal(true);
|
||||
// });
|
||||
|
||||
// it('should allow "Mattermost"', function() {
|
||||
// spellchecker.spellCheck('Mattermost').should.equal(true);
|
||||
// spellchecker.spellCheck('mattermost').should.equal(true);
|
||||
// });
|
||||
|
||||
// it('should give at most the requested number of suggestions', function() {
|
||||
// // helllo known to give at least 4 suggestions
|
||||
// spellchecker.getSuggestions('helllo', 4).length.should.be.equal(4);
|
||||
// spellchecker.getSuggestions('helllo', 1).length.should.be.equal(1);
|
||||
// });
|
||||
|
||||
// it('should give suggestions which preserve case of first letter', function() {
|
||||
// let suggestions = spellchecker.getSuggestions('carr', 4);
|
||||
// suggestions.length.should.not.be.equal(0);
|
||||
// let i;
|
||||
// for (i = 0; i < suggestions.length; i++) {
|
||||
// suggestions[i].charAt(0).should.be.equal('c');
|
||||
// }
|
||||
|
||||
// suggestions = spellchecker.getSuggestions('Carr', 4);
|
||||
// suggestions.length.should.not.be.equal(0);
|
||||
// for (i = 0; i < suggestions.length; i++) {
|
||||
// suggestions[i].charAt(0).should.be.equal('C');
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
|
||||
// describe('en-GB', function() {
|
||||
// const spellchecker = null;
|
||||
|
||||
// // before(function(done) {
|
||||
// // spellchecker = new SpellChecker(
|
||||
// // 'en-GB',
|
||||
// // path.resolve(__dirname, '../../src/node_modules/simple-spellchecker/dict'),
|
||||
// // done
|
||||
// // );
|
||||
// // });
|
||||
|
||||
// it('should allow contractions', function() {
|
||||
// spellchecker.spellCheck("shouldn't").should.equal(true);
|
||||
// spellchecker.spellCheck('shouldn').should.equal(true);
|
||||
// });
|
||||
// });
|
||||
|
||||
// describe('de-DE', function() {
|
||||
// const spellchecker = null;
|
||||
|
||||
// // before(function(done) {
|
||||
// // spellchecker = new SpellChecker(
|
||||
// // 'de-DE',
|
||||
// // path.resolve(__dirname, '../../src/node_modules/simple-spellchecker/dict'),
|
||||
// // done
|
||||
// // );
|
||||
// // });
|
||||
|
||||
// it('should spellcheck', function() {
|
||||
// spellchecker.spellCheck('Guten').should.equal(true);
|
||||
// spellchecker.spellCheck('tag').should.equal(true);
|
||||
// });
|
||||
|
||||
// it('should allow numerals', function() {
|
||||
// spellchecker.spellCheck('1').should.equal(true);
|
||||
// spellchecker.spellCheck('-100').should.equal(true);
|
||||
// spellchecker.spellCheck('3.14').should.equal(true);
|
||||
// });
|
||||
|
||||
// it('should give suggestions which preserve case of first letter', function() {
|
||||
// let suggestions = spellchecker.getSuggestions('gutenn', 4);
|
||||
// suggestions.length.should.not.be.equal(0);
|
||||
// let i;
|
||||
// for (i = 0; i < suggestions.length; i++) {
|
||||
// suggestions[i].charAt(0).should.be.equal('g');
|
||||
// }
|
||||
|
||||
// suggestions = spellchecker.getSuggestions('Gutenn', 4);
|
||||
// suggestions.length.should.not.be.equal(0);
|
||||
// for (i = 0; i < suggestions.length; i++) {
|
||||
// suggestions[i].charAt(0).should.be.equal('G');
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
// });
|
67
test/specs/window_test.js
Normal file
67
test/specs/window_test.js
Normal file
|
@ -0,0 +1,67 @@
|
|||
// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
const env = require('../modules/environment');
|
||||
|
||||
describe('window', function desc() {
|
||||
this.timeout(30000);
|
||||
|
||||
beforeEach(async () => {
|
||||
env.createTestUserDataDir();
|
||||
env.cleanTestConfig();
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (this.app) {
|
||||
try {
|
||||
await this.app.close();
|
||||
// eslint-disable-next-line no-empty
|
||||
} catch (err) {}
|
||||
}
|
||||
});
|
||||
|
||||
it.skip('should restore window bounds', async () => {
|
||||
// TODO: Still fails in CircleCI
|
||||
// bounds seems to be incorrectly calculated in some environments
|
||||
// - Windows 10: OK
|
||||
// - CircleCI: NG
|
||||
const expectedBounds = {x: 100, y: 200, width: 800, height: 400};
|
||||
fs.writeFileSync(env.boundsInfoPath, JSON.stringify(expectedBounds));
|
||||
this.app = await env.getApp();
|
||||
const mainWindow = await this.app.firstWindow();
|
||||
const browserWindow = await this.app.browserWindow(mainWindow);
|
||||
const bounds = await browserWindow.evaluate((window) => window.getContentBounds());
|
||||
bounds.should.deep.equal(expectedBounds);
|
||||
await this.app.close();
|
||||
});
|
||||
|
||||
it('should NOT restore window bounds if x is located on outside of viewarea', async () => {
|
||||
// bounds seems to be incorrectly calculated in some environments (e.g. CircleCI)
|
||||
// - Windows 10: OK
|
||||
// - CircleCI: NG
|
||||
fs.writeFileSync(env.boundsInfoPath, JSON.stringify({x: -100000, y: 200, width: 800, height: 400}));
|
||||
this.app = await env.getApp();
|
||||
const mainWindow = await this.app.firstWindow();
|
||||
const browserWindow = await this.app.browserWindow(mainWindow);
|
||||
const bounds = await browserWindow.evaluate((window) => window.getContentBounds());
|
||||
bounds.x.should.satisfy((x) => (x > -100000));
|
||||
await this.app.close();
|
||||
});
|
||||
|
||||
it('should NOT restore window bounds if y is located on outside of viewarea', async () => {
|
||||
// bounds seems to be incorrectly calculated in some environments (e.g. CircleCI)
|
||||
// - Windows 10: OK
|
||||
// - CircleCI: NG
|
||||
fs.writeFileSync(env.boundsInfoPath, JSON.stringify({x: 100, y: 200000, width: 800, height: 400}));
|
||||
this.app = await env.getApp();
|
||||
const mainWindow = await this.app.firstWindow();
|
||||
const browserWindow = await this.app.browserWindow(mainWindow);
|
||||
const bounds = await browserWindow.evaluate((window) => window.getContentBounds());
|
||||
bounds.y.should.satisfy((y) => (y < 200000));
|
||||
await this.app.close();
|
||||
});
|
||||
});
|
|
@ -38,7 +38,8 @@ module.exports = merge(base, {
|
|||
net: 'require("net")',
|
||||
repl: 'require("repl")',
|
||||
tls: 'require("tls")',
|
||||
spectron: 'require("spectron")',
|
||||
playwright: 'require("playwright")',
|
||||
robotjs: 'require("robotjs")',
|
||||
},
|
||||
node: {
|
||||
__filename: false,
|
||||
|
|
Loading…
Reference in a new issue