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
This commit is contained in:
Bruno Windels 2019-04-16 15:35:31 +02:00
parent c40f7f6a3c
commit 48c1d46aa7
12 changed files with 57 additions and 59 deletions

View file

@ -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);

View file

@ -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();

View file

@ -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();
}

View file

@ -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;
}

View file

@ -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");

View file

@ -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();
}

View file

@ -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)};
}));

View file

@ -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];

View file

@ -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();
}

View file

@ -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();

View file

@ -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

View file

@ -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