From 48c1d46aa71b2d6278065a9f6c2c8fc8792cc834 Mon Sep 17 00:00:00 2001 From: Bruno Windels Date: Tue, 16 Apr 2019 15:35:31 +0200 Subject: [PATCH] remove explicit timeouts from tests for selectors - gets rid of the waitAndQuery vs query distinction, all queries now wait if needed (called query and queryAll) - remove explicit timeouts, as they depend on the speed of the machine the tests run on --- src/session.js | 24 +++++++++++------------- src/usecases/accept-invite.js | 4 ++-- src/usecases/create-room.js | 8 ++++---- src/usecases/dialog.js | 4 ++-- src/usecases/invite.js | 4 ++-- src/usecases/join.js | 8 ++++---- src/usecases/memberlist.js | 12 ++++++------ src/usecases/room-settings.js | 10 +++++----- src/usecases/send-message.js | 4 ++-- src/usecases/settings.js | 10 +++++----- src/usecases/signup.js | 20 ++++++++++---------- src/usecases/verify.js | 8 ++++---- 12 files changed, 57 insertions(+), 59 deletions(-) diff --git a/src/session.js b/src/session.js index 80e3225f1f..4fe882c97d 100644 --- a/src/session.js +++ b/src/session.js @@ -19,6 +19,8 @@ const Logger = require('./logger'); const LogBuffer = require('./logbuffer'); const {delay} = require('./util'); +const DEFAULT_TIMEOUT = 20000; + module.exports = class RiotSession { constructor(browser, page, username, riotserver, hsUrl) { this.browser = browser; @@ -113,23 +115,18 @@ module.exports = class RiotSession { } query(selector) { - return this.page.$(selector); - } - - waitAndQuery(selector, timeout = 5000) { + const timeout = DEFAULT_TIMEOUT; return this.page.waitForSelector(selector, {visible: true, timeout}); } - queryAll(selector) { - return this.page.$$(selector); + async queryAll(selector) { + const timeout = DEFAULT_TIMEOUT; + await this.query(selector, timeout); + return await this.page.$$(selector); } - async waitAndQueryAll(selector, timeout = 5000) { - await this.waitAndQuery(selector, timeout); - return await this.queryAll(selector); - } - - waitForReload(timeout = 10000) { + waitForReload() { + const timeout = DEFAULT_TIMEOUT; return new Promise((resolve, reject) => { const timeoutHandle = setTimeout(() => { this.browser.removeEventListener('domcontentloaded', callback); @@ -145,7 +142,8 @@ module.exports = class RiotSession { }); } - waitForNewPage(timeout = 5000) { + waitForNewPage() { + const timeout = DEFAULT_TIMEOUT; return new Promise((resolve, reject) => { const timeoutHandle = setTimeout(() => { this.browser.removeListener('targetcreated', callback); diff --git a/src/usecases/accept-invite.js b/src/usecases/accept-invite.js index 03fbac28fa..3676f6641b 100644 --- a/src/usecases/accept-invite.js +++ b/src/usecases/accept-invite.js @@ -20,7 +20,7 @@ const {acceptDialogMaybe} = require('./dialog'); module.exports = async function acceptInvite(session, name) { session.log.step(`accepts "${name}" invite`); //TODO: brittle selector - const invitesHandles = await session.waitAndQueryAll('.mx_RoomTile_name.mx_RoomTile_invite'); + const invitesHandles = await session.queryAll('.mx_RoomTile_name.mx_RoomTile_invite'); const invitesWithText = await Promise.all(invitesHandles.map(async (inviteHandle) => { const text = await session.innerText(inviteHandle); return {inviteHandle, text}; @@ -31,7 +31,7 @@ module.exports = async function acceptInvite(session, name) { await inviteHandle.click(); - const acceptInvitationLink = await session.waitAndQuery(".mx_RoomPreviewBar_join_text a:first-child"); + const acceptInvitationLink = await session.query(".mx_RoomPreviewBar_join_text a:first-child"); await acceptInvitationLink.click(); session.log.done(); diff --git a/src/usecases/create-room.js b/src/usecases/create-room.js index 16d0620879..4578dbaf0a 100644 --- a/src/usecases/create-room.js +++ b/src/usecases/create-room.js @@ -31,16 +31,16 @@ async function openRoomDirectory(session) { async function createRoom(session, roomName) { session.log.step(`creates room "${roomName}"`); await openRoomDirectory(session); - const createRoomButton = await session.waitAndQuery('.mx_RoomDirectory_createRoom'); + const createRoomButton = await session.query('.mx_RoomDirectory_createRoom'); await createRoomButton.click(); - const roomNameInput = await session.waitAndQuery('.mx_CreateRoomDialog_input'); + const roomNameInput = await session.query('.mx_CreateRoomDialog_input'); await session.replaceInputText(roomNameInput, roomName); - const createButton = await session.waitAndQuery('.mx_Dialog_primary'); + const createButton = await session.query('.mx_Dialog_primary'); await createButton.click(); - await session.waitAndQuery('.mx_MessageComposer'); + await session.query('.mx_MessageComposer'); session.log.done(); } diff --git a/src/usecases/dialog.js b/src/usecases/dialog.js index 10b343128a..58f135de04 100644 --- a/src/usecases/dialog.js +++ b/src/usecases/dialog.js @@ -17,7 +17,7 @@ limitations under the License. const assert = require('assert'); async function assertDialog(session, expectedTitle) { - const titleElement = await session.waitAndQuery(".mx_Dialog .mx_Dialog_title"); + const titleElement = await session.query(".mx_Dialog .mx_Dialog_title"); const dialogHeader = await session.innerText(titleElement); assert(dialogHeader, expectedTitle); } @@ -32,7 +32,7 @@ async function acceptDialog(session, expectedTitle) { async function acceptDialogMaybe(session, expectedTitle) { let primaryButton = null; try { - primaryButton = await session.waitAndQuery(".mx_Dialog .mx_Dialog_primary", 100); + primaryButton = await session.query(".mx_Dialog .mx_Dialog_primary"); } catch(err) { return false; } diff --git a/src/usecases/invite.js b/src/usecases/invite.js index 03dff7b30f..7b3f8a2b48 100644 --- a/src/usecases/invite.js +++ b/src/usecases/invite.js @@ -19,9 +19,9 @@ const assert = require('assert'); module.exports = async function invite(session, userId) { session.log.step(`invites "${userId}" to room`); await session.delay(1000); - const inviteButton = await session.waitAndQuery(".mx_MemberList_invite"); + const inviteButton = await session.query(".mx_MemberList_invite"); await inviteButton.click(); - const inviteTextArea = await session.waitAndQuery(".mx_AddressPickerDialog textarea"); + const inviteTextArea = await session.query(".mx_AddressPickerDialog textarea"); await inviteTextArea.type(userId); await inviteTextArea.press("Enter"); const confirmButton = await session.query(".mx_Dialog_primary"); diff --git a/src/usecases/join.js b/src/usecases/join.js index cba9e06660..cf23fbfb64 100644 --- a/src/usecases/join.js +++ b/src/usecases/join.js @@ -20,15 +20,15 @@ const {openRoomDirectory} = require('./create-room'); module.exports = async function join(session, roomName) { session.log.step(`joins room "${roomName}"`); await openRoomDirectory(session); - const roomInput = await session.waitAndQuery('.mx_DirectorySearchBox input'); + const roomInput = await session.query('.mx_DirectorySearchBox input'); await session.replaceInputText(roomInput, roomName); - const firstRoomLabel = await session.waitAndQuery('.mx_RoomDirectory_table .mx_RoomDirectory_name:first-child', 1000); + const firstRoomLabel = await session.query('.mx_RoomDirectory_table .mx_RoomDirectory_name:first-child'); await firstRoomLabel.click(); - const joinLink = await session.waitAndQuery('.mx_RoomPreviewBar_join_text a'); + const joinLink = await session.query('.mx_RoomPreviewBar_join_text a'); await joinLink.click(); - await session.waitAndQuery('.mx_MessageComposer'); + await session.query('.mx_MessageComposer'); session.log.done(); } diff --git a/src/usecases/memberlist.js b/src/usecases/memberlist.js index 0cd8744853..5858e82bb8 100644 --- a/src/usecases/memberlist.js +++ b/src/usecases/memberlist.js @@ -34,20 +34,20 @@ module.exports.verifyDeviceForUser = async function(session, name, expectedDevic }).map((m) => m.label)[0]; await matchingLabel.click(); // click verify in member info - const firstVerifyButton = await session.waitAndQuery(".mx_MemberDeviceInfo_verify"); + const firstVerifyButton = await session.query(".mx_MemberDeviceInfo_verify"); await firstVerifyButton.click(); // expect "Verify device" dialog and click "Begin Verification" - const dialogHeader = await session.innerText(await session.waitAndQuery(".mx_Dialog .mx_Dialog_title")); + const dialogHeader = await session.innerText(await session.query(".mx_Dialog .mx_Dialog_title")); assert(dialogHeader, "Verify device"); - const beginVerificationButton = await session.waitAndQuery(".mx_Dialog .mx_Dialog_primary") + const beginVerificationButton = await session.query(".mx_Dialog .mx_Dialog_primary") await beginVerificationButton.click(); // get emoji SAS labels - const sasLabelElements = await session.waitAndQueryAll(".mx_VerificationShowSas .mx_VerificationShowSas_emojiSas .mx_VerificationShowSas_emojiSas_label"); + const sasLabelElements = await session.queryAll(".mx_VerificationShowSas .mx_VerificationShowSas_emojiSas .mx_VerificationShowSas_emojiSas_label"); const sasLabels = await Promise.all(sasLabelElements.map(e => session.innerText(e))); console.log("my sas labels", sasLabels); - const dialogCodeFields = await session.waitAndQueryAll(".mx_QuestionDialog code"); + const dialogCodeFields = await session.queryAll(".mx_QuestionDialog code"); assert.equal(dialogCodeFields.length, 2); const deviceId = await session.innerText(dialogCodeFields[0]); const deviceKey = await session.innerText(dialogCodeFields[1]); @@ -61,7 +61,7 @@ module.exports.verifyDeviceForUser = async function(session, name, expectedDevic } async function getMembersInMemberlist(session) { - const memberNameElements = await session.waitAndQueryAll(".mx_MemberList .mx_EntityTile_name"); + const memberNameElements = await session.queryAll(".mx_MemberList .mx_EntityTile_name"); return Promise.all(memberNameElements.map(async (el) => { return {label: el, displayName: await session.innerText(el)}; })); diff --git a/src/usecases/room-settings.js b/src/usecases/room-settings.js index 95078d1c87..bf3e60d490 100644 --- a/src/usecases/room-settings.js +++ b/src/usecases/room-settings.js @@ -37,11 +37,11 @@ module.exports = async function changeRoomSettings(session, settings) { const settingsButton = await session.query(".mx_RoomHeader .mx_AccessibleButton[title=Settings]"); await settingsButton.click(); //find tabs - const tabButtons = await session.waitAndQueryAll(".mx_RoomSettingsDialog .mx_TabbedView_tabLabel"); + const tabButtons = await session.queryAll(".mx_RoomSettingsDialog .mx_TabbedView_tabLabel"); const tabLabels = await Promise.all(tabButtons.map(t => session.innerText(t))); const securityTabButton = tabButtons[tabLabels.findIndex(l => l.toLowerCase().includes("security"))]; - const generalSwitches = await session.waitAndQueryAll(".mx_RoomSettingsDialog .mx_ToggleSwitch"); + const generalSwitches = await session.queryAll(".mx_RoomSettingsDialog .mx_ToggleSwitch"); const isDirectory = generalSwitches[0]; if (typeof settings.directory === "boolean") { @@ -51,9 +51,9 @@ module.exports = async function changeRoomSettings(session, settings) { if (settings.alias) { session.log.step(`sets alias to ${settings.alias}`); - const aliasField = await session.waitAndQuery(".mx_RoomSettingsDialog .mx_AliasSettings input[type=text]"); + const aliasField = await session.query(".mx_RoomSettingsDialog .mx_AliasSettings input[type=text]"); await session.replaceInputText(aliasField, settings.alias); - const addButton = await session.waitAndQuery(".mx_RoomSettingsDialog .mx_AliasSettings .mx_AccessibleButton"); + const addButton = await session.query(".mx_RoomSettingsDialog .mx_AliasSettings .mx_AccessibleButton"); await addButton.click(); session.log.done(); } @@ -74,7 +74,7 @@ module.exports = async function changeRoomSettings(session, settings) { if (settings.visibility) { session.log.step(`sets visibility to ${settings.visibility}`); - const radios = await session.waitAndQueryAll(".mx_RoomSettingsDialog input[type=radio]"); + const radios = await session.queryAll(".mx_RoomSettingsDialog input[type=radio]"); assert.equal(radios.length, 7); const inviteOnly = radios[0]; const publicNoGuests = radios[1]; diff --git a/src/usecases/send-message.js b/src/usecases/send-message.js index 038171327c..d3bd02cae3 100644 --- a/src/usecases/send-message.js +++ b/src/usecases/send-message.js @@ -20,7 +20,7 @@ module.exports = async function sendMessage(session, message) { session.log.step(`writes "${message}" in room`); // this selector needs to be the element that has contenteditable=true, // not any if its parents, otherwise it behaves flaky at best. - const composer = await session.waitAndQuery('.mx_MessageComposer_editor'); + const composer = await session.query('.mx_MessageComposer_editor'); // sometimes the focus that type() does internally doesn't seem to work // and calling click before seems to fix it 🤷 await composer.click(); @@ -29,6 +29,6 @@ module.exports = async function sendMessage(session, message) { assert.equal(text.trim(), message.trim()); await composer.press("Enter"); // wait for the message to appear sent - await session.waitAndQuery(".mx_EventTile_last:not(.mx_EventTile_sending)"); + await session.query(".mx_EventTile_last:not(.mx_EventTile_sending)"); session.log.done(); } diff --git a/src/usecases/settings.js b/src/usecases/settings.js index 68a290c29d..903524e6b8 100644 --- a/src/usecases/settings.js +++ b/src/usecases/settings.js @@ -19,10 +19,10 @@ const assert = require('assert'); async function openSettings(session, section) { const menuButton = await session.query(".mx_TopLeftMenuButton_name"); await menuButton.click(); - const settingsItem = await session.waitAndQuery(".mx_TopLeftMenu_icon_settings"); + const settingsItem = await session.query(".mx_TopLeftMenu_icon_settings"); await settingsItem.click(); if (section) { - const sectionButton = await session.waitAndQuery(`.mx_UserSettingsDialog .mx_TabbedView_tabLabels .mx_UserSettingsDialog_${section}Icon`); + const sectionButton = await session.query(`.mx_UserSettingsDialog .mx_TabbedView_tabLabels .mx_UserSettingsDialog_${section}Icon`); await sectionButton.click(); } } @@ -31,10 +31,10 @@ module.exports.enableLazyLoading = async function(session) { session.log.step(`enables lazy loading of members in the lab settings`); const settingsButton = await session.query('.mx_BottomLeftMenu_settings'); await settingsButton.click(); - const llCheckbox = await session.waitAndQuery("#feature_lazyloading"); + const llCheckbox = await session.query("#feature_lazyloading"); await llCheckbox.click(); await session.waitForReload(); - const closeButton = await session.waitAndQuery(".mx_RoomHeader_cancelButton"); + const closeButton = await session.query(".mx_RoomHeader_cancelButton"); await closeButton.click(); session.log.done(); } @@ -42,7 +42,7 @@ module.exports.enableLazyLoading = async function(session) { module.exports.getE2EDeviceFromSettings = async function(session) { session.log.step(`gets e2e device/key from settings`); await openSettings(session, "security"); - const deviceAndKey = await session.waitAndQueryAll(".mx_SettingsTab_section .mx_SecurityUserSettingsTab_deviceInfo code"); + const deviceAndKey = await session.queryAll(".mx_SettingsTab_section .mx_SecurityUserSettingsTab_deviceInfo code"); assert.equal(deviceAndKey.length, 2); const id = await (await deviceAndKey[0].getProperty("innerText")).jsonValue(); const key = await (await deviceAndKey[1].getProperty("innerText")).jsonValue(); diff --git a/src/usecases/signup.js b/src/usecases/signup.js index 0bfdb27a58..66bf773ca1 100644 --- a/src/usecases/signup.js +++ b/src/usecases/signup.js @@ -21,17 +21,17 @@ module.exports = async function signup(session, username, password, homeserver) await session.goto(session.url('/#/register')); // change the homeserver by clicking the "Change" link. if (homeserver) { - const changeServerDetailsLink = await session.waitAndQuery('.mx_AuthBody_editServerDetails'); + const changeServerDetailsLink = await session.query('.mx_AuthBody_editServerDetails'); await changeServerDetailsLink.click(); - const hsInputField = await session.waitAndQuery('#mx_ServerConfig_hsUrl'); + const hsInputField = await session.query('#mx_ServerConfig_hsUrl'); await session.replaceInputText(hsInputField, homeserver); - const nextButton = await session.waitAndQuery('.mx_Login_submit'); + const nextButton = await session.query('.mx_Login_submit'); await nextButton.click(); } //fill out form - const usernameField = await session.waitAndQuery("#mx_RegistrationForm_username"); - const passwordField = await session.waitAndQuery("#mx_RegistrationForm_password"); - const passwordRepeatField = await session.waitAndQuery("#mx_RegistrationForm_passwordConfirm"); + const usernameField = await session.query("#mx_RegistrationForm_username"); + const passwordField = await session.query("#mx_RegistrationForm_password"); + const passwordRepeatField = await session.query("#mx_RegistrationForm_passwordConfirm"); await session.replaceInputText(usernameField, username); await session.replaceInputText(passwordField, password); await session.replaceInputText(passwordRepeatField, password); @@ -41,7 +41,7 @@ module.exports = async function signup(session, username, password, homeserver) await session.delay(300); /// focus on the button to make sure error validation /// has happened before checking the form is good to go - const registerButton = await session.waitAndQuery('.mx_Login_submit'); + const registerButton = await session.query('.mx_Login_submit'); await registerButton.focus(); //check no errors const error_text = await session.tryGetInnertext('.mx_Login_error'); @@ -51,15 +51,15 @@ module.exports = async function signup(session, username, password, homeserver) await registerButton.click(); //confirm dialog saying you cant log back in without e-mail - const continueButton = await session.waitAndQuery('.mx_QuestionDialog button.mx_Dialog_primary'); + const continueButton = await session.query('.mx_QuestionDialog button.mx_Dialog_primary'); await continueButton.click(); //find the privacy policy checkbox and check it - const policyCheckbox = await session.waitAndQuery('.mx_InteractiveAuthEntryComponents_termsPolicy input'); + const policyCheckbox = await session.query('.mx_InteractiveAuthEntryComponents_termsPolicy input'); await policyCheckbox.click(); //now click the 'Accept' button to agree to the privacy policy - const acceptButton = await session.waitAndQuery('.mx_InteractiveAuthEntryComponents_termsSubmit'); + const acceptButton = await session.query('.mx_InteractiveAuthEntryComponents_termsSubmit'); await acceptButton.click(); //wait for registration to finish so the hash gets set diff --git a/src/usecases/verify.js b/src/usecases/verify.js index 233bf4f954..323765bebf 100644 --- a/src/usecases/verify.js +++ b/src/usecases/verify.js @@ -19,19 +19,19 @@ const {openMemberInfo} = require("./memberlist"); const {assertDialog, acceptDialog} = require("./dialog"); async function assertVerified(session) { - const dialogSubTitle = await session.innerText(await session.waitAndQuery(".mx_Dialog h2")); + const dialogSubTitle = await session.innerText(await session.query(".mx_Dialog h2")); assert(dialogSubTitle, "Verified!"); } async function startVerification(session, name) { await openMemberInfo(session, name); // click verify in member info - const firstVerifyButton = await session.waitAndQuery(".mx_MemberDeviceInfo_verify"); + const firstVerifyButton = await session.query(".mx_MemberDeviceInfo_verify"); await firstVerifyButton.click(); } async function getSasCodes(session) { - const sasLabelElements = await session.waitAndQueryAll(".mx_VerificationShowSas .mx_VerificationShowSas_emojiSas .mx_VerificationShowSas_emojiSas_label"); + const sasLabelElements = await session.queryAll(".mx_VerificationShowSas .mx_VerificationShowSas_emojiSas .mx_VerificationShowSas_emojiSas_label"); const sasLabels = await Promise.all(sasLabelElements.map(e => session.innerText(e))); return sasLabels; } @@ -53,7 +53,7 @@ module.exports.startSasVerifcation = async function(session, name) { module.exports.acceptSasVerification = async function(session, name) { await assertDialog(session, "Incoming Verification Request"); - const opponentLabelElement = await session.waitAndQuery(".mx_IncomingSasDialog_opponentProfile h2"); + const opponentLabelElement = await session.query(".mx_IncomingSasDialog_opponentProfile h2"); const opponentLabel = await session.innerText(opponentLabelElement); assert(opponentLabel, name); // click "Continue" button