From 865fd2522fe6829f87d8d42bb7b560a59c6f0286 Mon Sep 17 00:00:00 2001 From: Devin Binnie <52460000+devinbinnie@users.noreply.github.com> Date: Tue, 6 Dec 2022 08:40:56 -0400 Subject: [PATCH] Fixed some E2E tests that broke on v5.2 (#2453) * Fixing some E2E tests * Fixed a couple flaky ones * Fixed some issues on Windows --- e2e/modules/environment.js | 7 ++-- e2e/specs/deep_linking/deeplink.test.js | 5 +++ e2e/specs/downloads/downloads_manager.test.js | 14 ++++---- e2e/specs/mattermost/back_button.test.js | 24 ++++++------- e2e/specs/menu_bar/file_menu.test.js | 3 +- e2e/specs/menu_bar/view_menu.test.js | 10 ++++-- e2e/specs/menu_bar/window_menu.test.js | 10 ++++-- e2e/specs/popup.test.js | 4 +-- .../add_server_modal.test.js | 2 +- .../server_management/drag_and_drop.test.js | 3 +- .../edit_server_modal.test.js | 16 --------- e2e/specs/startup/app.test.js | 36 +++++-------------- src/common/config/index.ts | 2 +- src/renderer/components/MainPage.tsx | 5 +++ 14 files changed, 64 insertions(+), 77 deletions(-) diff --git a/e2e/modules/environment.js b/e2e/modules/environment.js index 546395d7..77fa7b56 100644 --- a/e2e/modules/environment.js +++ b/e2e/modules/environment.js @@ -105,7 +105,7 @@ const demoConfig = { darkMode: false, lastActiveTeam: 0, startInFullscreen: false, - autoCheckForUpdates: false, + autoCheckForUpdates: true, appLanguage: 'en', logLevel: 'silly', }; @@ -271,14 +271,15 @@ module.exports = { await dlButtonLocator.click(); await asyncSleep(500); - const downloadsWindow = app.windows().find((window) => window.url().includes('downloadsDropdown')); + const downloadsWindow = app.windows().find((window) => window.url().includes('downloadsDropdown.html')); await downloadsWindow.waitForLoadState(); await downloadsWindow.bringToFront(); + await downloadsWindow.isVisible('.DownloadsDropdown'); return downloadsWindow; }, async downloadsDropdownIsOpen(app) { - const downloadsWindow = app.windows().find((window) => window.url().includes('downloadsDropdown')); + const downloadsWindow = app.windows().find((window) => window.url().includes('downloadsDropdown.html')); const result = await downloadsWindow.isVisible('.DownloadsDropdown'); return result; }, diff --git a/e2e/specs/deep_linking/deeplink.test.js b/e2e/specs/deep_linking/deeplink.test.js index 41f6b51d..7620756d 100644 --- a/e2e/specs/deep_linking/deeplink.test.js +++ b/e2e/specs/deep_linking/deeplink.test.js @@ -34,6 +34,11 @@ describe('application', function desc() { it('MM-T1304/MM-T1306 should open the app on the requested deep link', async () => { this.app = await env.getApp(['mattermost://github.com/test/url']); this.serverMap = await env.getServerMap(this.app); + if (!this.app.windows().some((window) => window.url().includes('github.com'))) { + await this.app.waitForEvent('window', { + predicate: (window) => window.url().includes('github.com'), + }); + } const mainWindow = this.app.windows().find((window) => window.url().includes('index')); const browserWindow = await this.app.browserWindow(mainWindow); const webContentsId = this.serverMap[`${config.teams[1].name}___TAB_MESSAGING`].webContentsId; diff --git a/e2e/specs/downloads/downloads_manager.test.js b/e2e/specs/downloads/downloads_manager.test.js index 26cf4892..15f7f521 100644 --- a/e2e/specs/downloads/downloads_manager.test.js +++ b/e2e/specs/downloads/downloads_manager.test.js @@ -2,10 +2,11 @@ // See LICENSE.txt for license information. 'use strict'; +const fs = require('fs'); const robot = require('robotjs'); const env = require('../../modules/environment'); -const {asyncSleep, rmDirAsync, writeFileAsync} = require('../../modules/utils'); +const {asyncSleep, rmDirAsync} = require('../../modules/utils'); const config = { ...env.demoMattermostConfig, @@ -41,12 +42,11 @@ describe('downloads/downloads_manager', function desc() { const filename = `${Date.now().toString()}.txt`; beforeEach(async () => { - await env.cleanDataDirAsync(); - await env.cleanTestConfigAsync(); - await env.createTestUserDataDirAsync(); - await writeFileAsync(env.configFilePath, JSON.stringify(config)); + 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); const loadingScreen = this.app.windows().find((window) => window.url().includes('loadingScreen')); @@ -76,9 +76,9 @@ describe('downloads/downloads_manager', function desc() { await firstServer.locator('#file-attachment-link', {hasText: filename}).click(); await asyncSleep(1000); await Promise.all([ - firstServer.waitForEvent('download'), // It is important to call waitForEvent before click to set up waiting. firstServer.locator(`div[role="dialog"] a[download="${filename}"]`).click(), // Triggers the download. ]); + await asyncSleep(1000); (await env.downloadsDropdownIsOpen(this.app)).should.equal(true); }); }); diff --git a/e2e/specs/mattermost/back_button.test.js b/e2e/specs/mattermost/back_button.test.js index 05e7ee87..2e59a9d1 100644 --- a/e2e/specs/mattermost/back_button.test.js +++ b/e2e/specs/mattermost/back_button.test.js @@ -56,7 +56,7 @@ describe('MM-T2633 Back button should behave as expected', function desc() { const loadingScreen = this.app.windows().find((window) => window.url().includes('loadingScreen')); await loadingScreen.waitForSelector('.LoadingScreen', {state: 'hidden'}); firstServer = this.serverMap[`${config.teams[0].name}___TAB_MESSAGING`].win; - await firstServer.click('a:has-text("OneLogin")'); + await firstServer.click('a:has-text("Okta")'); backButton = await mainWindow.waitForSelector('button:has-text("Back")'); }); @@ -67,10 +67,10 @@ describe('MM-T2633 Back button should behave as expected', function desc() { await env.clearElectronInstances(); }); - it('MM-T2633_1 after clicking OneLogin, back button should appear', async () => { + it('MM-T2633_1 after clicking Okta, back button should appear', async () => { backButton.should.not.be.null; - const poweredByOneLogin = await firstServer.waitForSelector('a:has-text("Powered by OneLogin")'); - poweredByOneLogin.should.not.be.null; + const poweredByOkta = await firstServer.waitForSelector('p:has-text("Powered by Okta")'); + poweredByOkta.should.not.be.null; }); it('MM-T2633_2 after clicking Back, should be back on the login screen', async () => { @@ -80,26 +80,26 @@ describe('MM-T2633 Back button should behave as expected', function desc() { await mainWindow.waitForSelector('button:has-text("Back")', {state: 'hidden'}); }); - it('MM-T2633_3 on the OneLogin screen, should still allow links to be clicked and still show the Back button', async () => { + it('MM-T2633_3 on the Okta screen, should still allow links to be clicked and still show the Back button', async () => { let isNewWindow = false; this.app.on('window', () => { isNewWindow = true; }); - const oneLoginUrl = firstServer.url(); - await firstServer.click('a:has-text("OneLogin")'); - const poweredByOneLogin = await firstServer.waitForSelector('a:has-text("Powered by OneLogin")'); - poweredByOneLogin.click(); + const OktaUrl = firstServer.url(); + await firstServer.click('a:has-text("Okta")'); + const poweredByOkta = await firstServer.waitForSelector('p:has-text("Powered by Okta") a:has-text("Okta")'); + poweredByOkta.click(); backButton = await mainWindow.waitForSelector('button:has-text("Back")'); backButton.should.not.be.null; const frameUrl = firstServer.url(); - frameUrl.should.not.equal(oneLoginUrl); + frameUrl.should.not.equal(OktaUrl); isNewWindow.should.be.false; - await firstServer.waitForSelector('a:has-text("Powered by OneLogin")', {state: 'hidden'}); + await firstServer.waitForSelector('p:has-text("Powered by Okta")', {state: 'hidden'}); }); it('MM-T2633_4 after click Back twice, user should be on the main login screen again', async () => { await backButton.click(); - await firstServer.waitForURL('https://mattermost.onelogin.com/**'); + await firstServer.waitForURL('https://mattermost.okta.com/**'); await backButton.click(); const loginPrompt = await firstServer.waitForSelector('#input_loginId'); loginPrompt.should.not.be.null; diff --git a/e2e/specs/menu_bar/file_menu.test.js b/e2e/specs/menu_bar/file_menu.test.js index b2b9b7b8..d7c2af39 100644 --- a/e2e/specs/menu_bar/file_menu.test.js +++ b/e2e/specs/menu_bar/file_menu.test.js @@ -87,7 +87,7 @@ describe('file_menu/dropdown', function desc() { // TODO: Causes issues on Windows so skipping for Windows if (process.platform !== 'win32') { - it('MM-T806 Exit in the Menu Bar', () => { + it('MM-T806 Exit in the Menu Bar', async () => { const mainWindow = this.app.windows().find((window) => window.url().includes('index')); mainWindow.should.not.be.null; @@ -99,6 +99,7 @@ describe('file_menu/dropdown', function desc() { robot.keyTap('q', ['control']); } + await asyncSleep(500); this.app.windows().find((window) => window.url().should.not.include('index')); skipAfterEach = true; // Need to skip closing in aftereach as apps execution context is destroyed above diff --git a/e2e/specs/menu_bar/view_menu.test.js b/e2e/specs/menu_bar/view_menu.test.js index bc1c5085..9bc05955 100644 --- a/e2e/specs/menu_bar/view_menu.test.js +++ b/e2e/specs/menu_bar/view_menu.test.js @@ -234,7 +234,7 @@ describe('menu/view', function desc() { }); it('MM-T820 should open Developer Tools For Application Wrapper for main window', async () => { - const mainWindow = this.app.windows().find((window) => window.url().includes('loadingScreen')); + const mainWindow = this.app.windows().find((window) => window.url().includes('index.html')); const browserWindow = await this.app.browserWindow(mainWindow); const loadingScreen = this.app.windows().find((window) => window.url().includes('loadingScreen')); await loadingScreen.waitForSelector('.LoadingScreen', {state: 'hidden'}); @@ -244,7 +244,11 @@ describe('menu/view', function desc() { }); isDevToolsOpen.should.be.false; - robot.keyTap('i', process.platform === 'darwin' ? ['command', 'alt'] : ['control', 'shift']); + robot.keyTap('alt'); + robot.keyTap('enter'); + robot.keyTap('v'); + robot.keyTap('d'); + robot.keyTap('enter'); await asyncSleep(1000); isDevToolsOpen = await browserWindow.evaluate((window) => { @@ -256,7 +260,7 @@ describe('menu/view', function desc() { // TODO: Missing shortcut for macOS if (process.platform !== 'darwin') { it('MM-T821 should open Developer Tools For Current Server for the active tab', async () => { - const mainWindow = this.app.windows().find((window) => window.url().includes('loadingScreen')); + const mainWindow = this.app.windows().find((window) => window.url().includes('index')); 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')); diff --git a/e2e/specs/menu_bar/window_menu.test.js b/e2e/specs/menu_bar/window_menu.test.js index 9e6128b4..787802d5 100644 --- a/e2e/specs/menu_bar/window_menu.test.js +++ b/e2e/specs/menu_bar/window_menu.test.js @@ -38,6 +38,7 @@ describe('Menu/window_menu', function desc() { lastActiveTab: 0, }, ], + lastActiveTeam: 2, minimizeToTray: true, alwaysMinimize: true, }; @@ -72,7 +73,7 @@ describe('Menu/window_menu', function desc() { it('MM-T826_1 should show the second server', async () => { let dropdownButtonText = await mainWindow.innerText('.TeamDropdownButton'); - dropdownButtonText.should.equal('example'); + dropdownButtonText.should.equal('google'); robot.keyTap('2', ['control', process.platform === 'darwin' ? 'command' : 'shift']); dropdownButtonText = await mainWindow.innerText('.TeamDropdownButton:has-text("github")'); @@ -92,7 +93,7 @@ describe('Menu/window_menu', function desc() { }); }); - it('MM-T4385 select tab from menu', async () => { + describe('MM-T4385 select tab from menu', async () => { let mainView; before(async () => { @@ -106,18 +107,21 @@ describe('Menu/window_menu', function desc() { tabViewButton.should.equal('Channels'); robot.keyTap('2', [env.cmdOrCtrl]); + await asyncSleep(500); tabViewButton = await mainView.innerText('.active'); tabViewButton.should.equal('Boards'); }); it('MM-T4385_2 should show the third tab', async () => { robot.keyTap('3', [env.cmdOrCtrl]); + await asyncSleep(500); const tabViewButton = await mainView.innerText('.active'); tabViewButton.should.equal('Playbooks'); }); it('MM-T4385_3 should show the first tab', async () => { robot.keyTap('1', [env.cmdOrCtrl]); + await asyncSleep(500); const tabViewButton = await mainView.innerText('.active'); tabViewButton.should.equal('Channels'); }); @@ -132,10 +136,12 @@ describe('Menu/window_menu', function desc() { tabViewButton.should.equal('Channels'); robot.keyTap('tab', ['control']); + await asyncSleep(500); tabViewButton = await mainView.innerText('.active'); tabViewButton.should.equal('Boards'); robot.keyTap('tab', ['shift', 'control']); + await asyncSleep(500); tabViewButton = await mainView.innerText('.active'); tabViewButton.should.equal('Channels'); diff --git a/e2e/specs/popup.test.js b/e2e/specs/popup.test.js index 6852f223..1d4a1420 100644 --- a/e2e/specs/popup.test.js +++ b/e2e/specs/popup.test.js @@ -43,7 +43,7 @@ describe('popup', function desc() { await firstServer.waitForSelector('#sidebarItem_suscipit-4'); await firstServer.click('#sidebarItem_suscipit-4'); await firstServer.click('#post_textbox'); - await firstServer.type('#post_textbox', '/github connect'); + await firstServer.type('#post_textbox', '/github connect '); await firstServer.press('#post_textbox', 'Enter'); const githubLink = await firstServer.waitForSelector('a.theme.markdown__link:has-text("GitHub account")'); @@ -99,7 +99,7 @@ describe('popup', function desc() { await firstServer.waitForSelector('#sidebarItem_suscipit-4'); await firstServer.click('#sidebarItem_suscipit-4'); await firstServer.click('#post_textbox'); - await firstServer.type('#post_textbox', '/github connect'); + await firstServer.type('#post_textbox', '/github connect '); await firstServer.press('#post_textbox', 'Enter'); const githubLink = await firstServer.waitForSelector('a.theme.markdown__link:has-text("GitHub account")'); diff --git a/e2e/specs/server_management/add_server_modal.test.js b/e2e/specs/server_management/add_server_modal.test.js index 29799283..9070eaeb 100644 --- a/e2e/specs/server_management/add_server_modal.test.js +++ b/e2e/specs/server_management/add_server_modal.test.js @@ -41,7 +41,7 @@ describe('Add Server Modal', function desc() { let newServerView; it('MM-T1312 should focus the first text input', async () => { - const isFocused = await newServerView.$eval('#teamNameInput', (el) => el.isSameNode(document.activeElement)); + const isFocused = await newServerView.$eval('#teamUrlInput', (el) => el.isSameNode(document.activeElement)); isFocused.should.be.true; }); diff --git a/e2e/specs/server_management/drag_and_drop.test.js b/e2e/specs/server_management/drag_and_drop.test.js index 4324b9a2..f5b695cc 100644 --- a/e2e/specs/server_management/drag_and_drop.test.js +++ b/e2e/specs/server_management/drag_and_drop.test.js @@ -36,6 +36,7 @@ describe('server_management/drag_and_drop', function desc() { lastActiveTab: 0, }, ], + lastActiveTeam: 2, }; const beforeFunc = async () => { @@ -159,7 +160,7 @@ describe('server_management/drag_and_drop', function desc() { it('MM-T2635_3 should update the config file', () => { // Verify config is updated const newConfig = JSON.parse(fs.readFileSync(env.configFilePath, 'utf-8')); - const firstTeam = newConfig.teams.find((team) => team.name === 'example'); + const firstTeam = newConfig.teams.find((team) => team.name === 'google'); const order0 = firstTeam.tabs.find((tab) => tab.name === 'TAB_FOCALBOARD'); order0.order.should.equal(0); const order1 = firstTeam.tabs.find((tab) => tab.name === 'TAB_MESSAGING'); diff --git a/e2e/specs/server_management/edit_server_modal.test.js b/e2e/specs/server_management/edit_server_modal.test.js index a3e731ce..756674b9 100644 --- a/e2e/specs/server_management/edit_server_modal.test.js +++ b/e2e/specs/server_management/edit_server_modal.test.js @@ -59,12 +59,10 @@ describe('EditServerModal', function desc() { { name: 'TAB_FOCALBOARD', order: 1, - isOpen: true, }, { name: 'TAB_PLAYBOOKS', order: 2, - isOpen: true, }, ], lastActiveTab: 0, @@ -91,12 +89,10 @@ describe('EditServerModal', function desc() { { name: 'TAB_FOCALBOARD', order: 1, - isOpen: true, }, { name: 'TAB_PLAYBOOKS', order: 2, - isOpen: true, }, ], lastActiveTab: 0, @@ -143,12 +139,10 @@ describe('EditServerModal', function desc() { { name: 'TAB_FOCALBOARD', order: 1, - isOpen: true, }, { name: 'TAB_PLAYBOOKS', order: 2, - isOpen: true, }, ], lastActiveTab: 0, @@ -166,12 +160,10 @@ describe('EditServerModal', function desc() { { name: 'TAB_FOCALBOARD', order: 1, - isOpen: true, }, { name: 'TAB_PLAYBOOKS', order: 2, - isOpen: true, }, ], lastActiveTab: 0, @@ -199,12 +191,10 @@ describe('EditServerModal', function desc() { { name: 'TAB_FOCALBOARD', order: 1, - isOpen: true, }, { name: 'TAB_PLAYBOOKS', order: 2, - isOpen: true, }, ], lastActiveTab: 0, @@ -222,12 +212,10 @@ describe('EditServerModal', function desc() { { name: 'TAB_FOCALBOARD', order: 1, - isOpen: true, }, { name: 'TAB_PLAYBOOKS', order: 2, - isOpen: true, }, ], lastActiveTab: 0, @@ -256,12 +244,10 @@ describe('EditServerModal', function desc() { { name: 'TAB_FOCALBOARD', order: 1, - isOpen: true, }, { name: 'TAB_PLAYBOOKS', order: 2, - isOpen: true, }, ], lastActiveTab: 0, @@ -279,12 +265,10 @@ describe('EditServerModal', function desc() { { name: 'TAB_FOCALBOARD', order: 1, - isOpen: true, }, { name: 'TAB_PLAYBOOKS', order: 2, - isOpen: true, }, ], lastActiveTab: 0, diff --git a/e2e/specs/startup/app.test.js b/e2e/specs/startup/app.test.js index 21ea049e..796033f3 100644 --- a/e2e/specs/startup/app.test.js +++ b/e2e/specs/startup/app.test.js @@ -16,11 +16,6 @@ describe('startup/app', function desc() { env.createTestUserDataDir(); env.cleanTestConfig(); this.app = await env.getApp(); - - // Skip welcome screen modal - const welcomeScreenModal = this.app.windows().find((window) => window.url().includes('welcomeScreen')); - welcomeScreenModal.click('.WelcomeScreen .WelcomeScreen__button'); - await asyncSleep(500); }); afterEach(async () => { @@ -30,29 +25,6 @@ describe('startup/app', function desc() { await env.clearElectronInstances(); }); - it('MM-T4399_1 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'); - }); - - it('MM-T4419 should not allow the user to close the new server modal when no servers exist', async () => { - const newServerModal = this.app.windows().find((window) => window.url().includes('newServer')); - - const existing = await newServerModal.isVisible('#cancelNewServerModal'); - existing.should.be.false; - - robot.keyTap('escape'); - const existingModal = this.app.windows().find((window) => window.url().includes('newServer')); - existingModal.should.not.be.null; - }); - - it('MM-T4985 should show app name in title bar when no servers exist', async () => { - const mainWindow = this.app.windows().find((window) => window.url().includes('index')); - const titleBarText = await mainWindow.innerText('.app-title'); - titleBarText.should.equal('Mattermost'); - }); - it('MM-T4400 should be stopped when the app instance already exists', (done) => { const secondApp = env.getApp(); @@ -84,4 +56,12 @@ describe('startup/app', function desc() { const modalButton = await welcomeScreenModal.innerText('.WelcomeScreen .WelcomeScreen__button'); modalButton.should.equal('Get Started'); }); + + if (process.platform !== 'linux') { + it('MM-T4985 should show app name in title bar when no servers exist', async () => { + const mainWindow = this.app.windows().find((window) => window.url().includes('index')); + const titleBarText = await mainWindow.innerText('.app-title'); + titleBarText.should.equal('Mattermost'); + }); + } }); diff --git a/src/common/config/index.ts b/src/common/config/index.ts index d4be610f..694213ef 100644 --- a/src/common/config/index.ts +++ b/src/common/config/index.ts @@ -321,7 +321,7 @@ export class Config extends EventEmitter { } get canUpgrade() { - return this.canUpgradeValue && this.buildConfigData?.enableAutoUpdater && !(process.platform === 'linux' && !process.env.APPIMAGE) && !(process.platform === 'win32' && this.registryConfigData?.enableAutoUpdater === false); + return process.env.NODE_ENV === 'test' || (this.canUpgradeValue && this.buildConfigData?.enableAutoUpdater && !(process.platform === 'linux' && !process.env.APPIMAGE) && !(process.platform === 'win32' && this.registryConfigData?.enableAutoUpdater === false)); } get autoCheckForUpdates() { diff --git a/src/renderer/components/MainPage.tsx b/src/renderer/components/MainPage.tsx index bbef16a1..475c2b99 100644 --- a/src/renderer/components/MainPage.tsx +++ b/src/renderer/components/MainPage.tsx @@ -77,12 +77,14 @@ type TabViewStatus = { } class MainPage extends React.PureComponent { + threeDotMenu: React.RefObject; topBar: React.RefObject; constructor(props: Props) { super(props); this.topBar = React.createRef(); + this.threeDotMenu = React.createRef(); const firstServer = this.props.teams.find((team) => team.order === this.props.lastActiveTeam) || this.props.teams.find((team) => team.order === 0); let firstTab = firstServer?.tabs.find((tab) => tab.order === firstServer.lastActiveTab) || firstServer?.tabs.find((tab) => tab.order === 0); @@ -355,12 +357,14 @@ class MainPage extends React.PureComponent { } focusThreeDotsButton = () => { + this.threeDotMenu.current?.focus(); this.setState({ threeDotsIsFocused: true, }); } unFocusThreeDotsButton = () => { + this.threeDotMenu.current?.blur(); this.setState({ threeDotsIsFocused: false, }); @@ -487,6 +491,7 @@ class MainPage extends React.PureComponent { )}