From e66f2a6c3ff76c434c5e9490a2f8aec4271cff47 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Fri, 10 Jan 2020 10:13:41 -0700 Subject: [PATCH] Revert ES6ification of end-to-end tests and add instructions for Windows Because the tests are run directly by node, we have to use the CommonJS module syntax. We could run the thing through babel, but then we just have another babel. Windows instructions are from experience and may not be optimized. --- test/end-to-end-tests/Windows.md | 39 +++++++++++++++++++ test/end-to-end-tests/src/logbuffer.js | 2 +- test/end-to-end-tests/src/logger.js | 2 +- test/end-to-end-tests/src/rest/consent.js | 4 +- test/end-to-end-tests/src/rest/creator.js | 14 +++---- test/end-to-end-tests/src/rest/multi.js | 2 +- test/end-to-end-tests/src/rest/room.js | 2 +- test/end-to-end-tests/src/rest/session.js | 2 +- .../src/scenarios/directory.js | 2 +- .../src/scenarios/e2e-encryption.js | 2 +- .../src/scenarios/lazy-loading.js | 2 +- test/end-to-end-tests/src/session.js | 2 +- .../src/usecases/accept-invite.js | 4 +- .../src/usecases/create-room.js | 6 ++- test/end-to-end-tests/src/usecases/dialog.js | 12 ++++-- test/end-to-end-tests/src/usecases/invite.js | 2 +- test/end-to-end-tests/src/usecases/join.js | 2 +- .../src/usecases/memberlist.js | 12 ++++-- .../src/usecases/room-settings.js | 2 +- .../end-to-end-tests/src/usecases/settings.js | 8 ++-- test/end-to-end-tests/src/usecases/signup.js | 2 +- .../end-to-end-tests/src/usecases/timeline.js | 14 +++---- test/end-to-end-tests/src/usecases/verify.js | 8 ++-- test/end-to-end-tests/src/util.js | 8 ++-- 24 files changed, 103 insertions(+), 52 deletions(-) create mode 100644 test/end-to-end-tests/Windows.md diff --git a/test/end-to-end-tests/Windows.md b/test/end-to-end-tests/Windows.md new file mode 100644 index 0000000000..dee4fabb3f --- /dev/null +++ b/test/end-to-end-tests/Windows.md @@ -0,0 +1,39 @@ +# Running the end-to-end tests on Windows + +Windows is not the best platform to run the tests on, but if you have to, enable Windows Subsystem for Linux (WSL) +and start following these steps to get going: + +1. Navigate to your working directory (`cd /mnt/c/users/travisr/whatever/matrix-react-sdk` for example). +2. Run `sudo apt-get install unzip python3 virtualenv dos2unix` +3. Run `dos2unix ./test/end-to-end-tests/*.sh ./test/end-to-end-tests/synapse/*.sh ./test/end-to-end-tests/riot/*.sh` +4. Install NodeJS for ubuntu: + ```bash + curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash - + sudo apt-get update + sudo apt-get install nodejs + ``` +5. Start Riot on Windows through `yarn start` +6. While that builds... Run: + ```bash + sudo apt-get install x11-apps + wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb + sudo dpkg -i google-chrome-stable_current_amd64.deb + sudo apt -f install + ``` +7. Run: + ```bash + cd ./test/end-to-end-tests + ./synapse/install.sh + ./run.sh --riot-url http://localhost:8080 --no-sandbox + ``` + +Note that using `yarn test:e2e` probably won't work for you. You might also have to use the config.json from the +`riot/config-template` directory in order to actually succeed at the tests. + +Also note that you'll have to use `--no-sandbox` otherwise Chrome will complain that there's no sandbox available. You +could probably fix this with enough effort, or you could run a headless Chrome in the WSL container without a sandbox. + + +Reference material that isn't fully represented in the steps above (but snippets have been borrowed): +* https://virtualizationreview.com/articles/2017/02/08/graphical-programs-on-windows-subsystem-on-linux.aspx +* https://gist.github.com/drexler/d70ab957f964dbef1153d46bd853c775 diff --git a/test/end-to-end-tests/src/logbuffer.js b/test/end-to-end-tests/src/logbuffer.js index db4be33e8d..873363c2ec 100644 --- a/test/end-to-end-tests/src/logbuffer.js +++ b/test/end-to-end-tests/src/logbuffer.js @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -export default class LogBuffer { +module.exports = class LogBuffer { constructor(page, eventName, eventMapper, reduceAsync=false, initialValue = "") { this.buffer = initialValue; page.on(eventName, (arg) => { diff --git a/test/end-to-end-tests/src/logger.js b/test/end-to-end-tests/src/logger.js index 42a9544e4d..f5a338e2c7 100644 --- a/test/end-to-end-tests/src/logger.js +++ b/test/end-to-end-tests/src/logger.js @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -export default class Logger { +module.exports = class Logger { constructor(username) { this.indent = 0; this.username = username; diff --git a/test/end-to-end-tests/src/rest/consent.js b/test/end-to-end-tests/src/rest/consent.js index 5c424cd6e8..956441571b 100644 --- a/test/end-to-end-tests/src/rest/consent.js +++ b/test/end-to-end-tests/src/rest/consent.js @@ -19,7 +19,7 @@ const request = require('request-promise-native'); const cheerio = require('cheerio'); const url = require("url"); -export async function approveConsent(consentUrl) { +module.exports.approveConsent = async function(consentUrl) { const body = await request.get(consentUrl); const doc = cheerio.load(body); const v = doc("input[name=v]").val(); @@ -28,4 +28,4 @@ export async function approveConsent(consentUrl) { const formAction = doc("form").attr("action"); const absAction = url.resolve(consentUrl, formAction); await request.post(absAction).form({v, u, h}); -} +}; diff --git a/test/end-to-end-tests/src/rest/creator.js b/test/end-to-end-tests/src/rest/creator.js index c4ddee0581..03b2e099bc 100644 --- a/test/end-to-end-tests/src/rest/creator.js +++ b/test/end-to-end-tests/src/rest/creator.js @@ -32,7 +32,7 @@ function execAsync(command, options) { }); } -export default class RestSessionCreator { +module.exports = class RestSessionCreator { constructor(synapseSubdir, hsUrl, cwd) { this.synapseSubdir = synapseSubdir; this.hsUrl = hsUrl; @@ -72,12 +72,12 @@ export default class RestSessionCreator { async _authenticate(username, password) { const requestBody = { - "type": "m.login.password", - "identifier": { - "type": "m.id.user", - "user": username, - }, - "password": password, + "type": "m.login.password", + "identifier": { + "type": "m.id.user", + "user": username, + }, + "password": password, }; const url = `${this.hsUrl}/_matrix/client/r0/login`; const responseBody = await request.post({url, json: true, body: requestBody}); diff --git a/test/end-to-end-tests/src/rest/multi.js b/test/end-to-end-tests/src/rest/multi.js index d4cd5c765c..570879bff7 100644 --- a/test/end-to-end-tests/src/rest/multi.js +++ b/test/end-to-end-tests/src/rest/multi.js @@ -17,7 +17,7 @@ limitations under the License. const Logger = require('../logger'); -export default class RestMultiSession { +module.exports = class RestMultiSession { constructor(sessions, groupName) { this.log = new Logger(groupName); this.sessions = sessions; diff --git a/test/end-to-end-tests/src/rest/room.js b/test/end-to-end-tests/src/rest/room.js index b3ba725336..94afce1dac 100644 --- a/test/end-to-end-tests/src/rest/room.js +++ b/test/end-to-end-tests/src/rest/room.js @@ -18,7 +18,7 @@ limitations under the License. const uuidv4 = require('uuid/v4'); /* no pun intented */ -export default class RestRoom { +module.exports = class RestRoom { constructor(session, roomId, log) { this.session = session; this._roomId = roomId; diff --git a/test/end-to-end-tests/src/rest/session.js b/test/end-to-end-tests/src/rest/session.js index 344493968c..5b97824f5c 100644 --- a/test/end-to-end-tests/src/rest/session.js +++ b/test/end-to-end-tests/src/rest/session.js @@ -19,7 +19,7 @@ const Logger = require('../logger'); const RestRoom = require('./room'); const {approveConsent} = require('./consent'); -export default class RestSession { +module.exports = class RestSession { constructor(credentials) { this.log = new Logger(credentials.userId); this._credentials = credentials; diff --git a/test/end-to-end-tests/src/scenarios/directory.js b/test/end-to-end-tests/src/scenarios/directory.js index cf995ae1a8..ca2f99f192 100644 --- a/test/end-to-end-tests/src/scenarios/directory.js +++ b/test/end-to-end-tests/src/scenarios/directory.js @@ -22,7 +22,7 @@ const {receiveMessage} = require('../usecases/timeline'); const {createRoom} = require('../usecases/create-room'); const changeRoomSettings = require('../usecases/room-settings'); -export default async function roomDirectoryScenarios(alice, bob) { +module.exports = async function roomDirectoryScenarios(alice, bob) { console.log(" creating a public room and join through directory:"); const room = 'test'; await createRoom(alice, room); diff --git a/test/end-to-end-tests/src/scenarios/e2e-encryption.js b/test/end-to-end-tests/src/scenarios/e2e-encryption.js index 2a002da66b..2f08acf417 100644 --- a/test/end-to-end-tests/src/scenarios/e2e-encryption.js +++ b/test/end-to-end-tests/src/scenarios/e2e-encryption.js @@ -24,7 +24,7 @@ const changeRoomSettings = require('../usecases/room-settings'); const {startSasVerifcation, acceptSasVerification} = require('../usecases/verify'); const assert = require('assert'); -export default async function e2eEncryptionScenarios(alice, bob) { +module.exports = async function e2eEncryptionScenarios(alice, bob) { console.log(" creating an e2e encrypted room and join through invite:"); const room = "secrets"; await createRoom(bob, room); diff --git a/test/end-to-end-tests/src/scenarios/lazy-loading.js b/test/end-to-end-tests/src/scenarios/lazy-loading.js index 651397e426..0c45b0d083 100644 --- a/test/end-to-end-tests/src/scenarios/lazy-loading.js +++ b/test/end-to-end-tests/src/scenarios/lazy-loading.js @@ -28,7 +28,7 @@ const {getMembersInMemberlist} = require('../usecases/memberlist'); const changeRoomSettings = require('../usecases/room-settings'); const assert = require('assert'); -export default async function lazyLoadingScenarios(alice, bob, charlies) { +module.exports = async function lazyLoadingScenarios(alice, bob, charlies) { console.log(" creating a room for lazy loading member scenarios:"); const charly1to5 = charlies.slice("charly-1..5", 0, 5); const charly6to10 = charlies.slice("charly-6..10", 5); diff --git a/test/end-to-end-tests/src/session.js b/test/end-to-end-tests/src/session.js index b17e55efa4..f25c5056ad 100644 --- a/test/end-to-end-tests/src/session.js +++ b/test/end-to-end-tests/src/session.js @@ -22,7 +22,7 @@ const {delay} = require('./util'); const DEFAULT_TIMEOUT = 20000; -export default class RiotSession { +module.exports = class RiotSession { constructor(browser, page, username, riotserver, hsUrl) { this.browser = browser; this.page = page; diff --git a/test/end-to-end-tests/src/usecases/accept-invite.js b/test/end-to-end-tests/src/usecases/accept-invite.js index d17f583a77..3f208cc1fc 100644 --- a/test/end-to-end-tests/src/usecases/accept-invite.js +++ b/test/end-to-end-tests/src/usecases/accept-invite.js @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -export default async function acceptInvite(session, name) { +module.exports = async function acceptInvite(session, name) { session.log.step(`accepts "${name}" invite`); //TODO: brittle selector const invitesHandles = await session.queryAll('.mx_RoomTile_name.mx_RoomTile_invite'); @@ -24,7 +24,7 @@ export default async function acceptInvite(session, name) { return {inviteHandle, text}; })); const inviteHandle = invitesWithText.find(({inviteHandle, text}) => { - return text.trim() === name; + return text.trim() === name; }).inviteHandle; await inviteHandle.click(); diff --git a/test/end-to-end-tests/src/usecases/create-room.js b/test/end-to-end-tests/src/usecases/create-room.js index 7ca3826c71..140748bca7 100644 --- a/test/end-to-end-tests/src/usecases/create-room.js +++ b/test/end-to-end-tests/src/usecases/create-room.js @@ -15,12 +15,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -export async function openRoomDirectory(session) { +async function openRoomDirectory(session) { const roomDirectoryButton = await session.query('.mx_LeftPanel_explore .mx_AccessibleButton'); await roomDirectoryButton.click(); } -export async function createRoom(session, roomName) { +async function createRoom(session, roomName) { session.log.step(`creates room "${roomName}"`); const roomListHeaders = await session.queryAll('.mx_RoomSubList_labelContainer'); @@ -43,3 +43,5 @@ export async function createRoom(session, roomName) { await session.query('.mx_MessageComposer'); session.log.done(); } + +module.exports = {openRoomDirectory, createRoom}; diff --git a/test/end-to-end-tests/src/usecases/dialog.js b/test/end-to-end-tests/src/usecases/dialog.js index 72d024fc79..d4ae97dff9 100644 --- a/test/end-to-end-tests/src/usecases/dialog.js +++ b/test/end-to-end-tests/src/usecases/dialog.js @@ -17,20 +17,20 @@ limitations under the License. const assert = require('assert'); -export async function assertDialog(session, expectedTitle) { +async function assertDialog(session, expectedTitle) { const titleElement = await session.query(".mx_Dialog .mx_Dialog_title"); const dialogHeader = await session.innerText(titleElement); assert(dialogHeader, expectedTitle); } -export async function acceptDialog(session, expectedTitle) { +async function acceptDialog(session, expectedTitle) { const foundDialog = await acceptDialogMaybe(session, expectedTitle); if (!foundDialog) { throw new Error("could not find a dialog"); } } -export async function acceptDialogMaybe(session, expectedTitle) { +async function acceptDialogMaybe(session, expectedTitle) { let primaryButton = null; try { primaryButton = await session.query(".mx_Dialog .mx_Dialog_primary"); @@ -43,3 +43,9 @@ export async function acceptDialogMaybe(session, expectedTitle) { await primaryButton.click(); return true; } + +module.exports = { + assertDialog, + acceptDialog, + acceptDialogMaybe, +}; diff --git a/test/end-to-end-tests/src/usecases/invite.js b/test/end-to-end-tests/src/usecases/invite.js index fc91e4ce16..6bee5dfd6f 100644 --- a/test/end-to-end-tests/src/usecases/invite.js +++ b/test/end-to-end-tests/src/usecases/invite.js @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -export default async function invite(session, userId) { +module.exports = async function invite(session, userId) { session.log.step(`invites "${userId}" to room`); await session.delay(1000); const memberPanelButton = await session.query(".mx_RightPanel_membersButton"); diff --git a/test/end-to-end-tests/src/usecases/join.js b/test/end-to-end-tests/src/usecases/join.js index 4fbc134598..655c0be686 100644 --- a/test/end-to-end-tests/src/usecases/join.js +++ b/test/end-to-end-tests/src/usecases/join.js @@ -17,7 +17,7 @@ limitations under the License. const {openRoomDirectory} = require('./create-room'); -export default async function join(session, roomName) { +module.exports = async function join(session, roomName) { session.log.step(`joins room "${roomName}"`); await openRoomDirectory(session); const roomInput = await session.query('.mx_DirectorySearchBox input'); diff --git a/test/end-to-end-tests/src/usecases/memberlist.js b/test/end-to-end-tests/src/usecases/memberlist.js index 8d2aacf35c..e974eea95b 100644 --- a/test/end-to-end-tests/src/usecases/memberlist.js +++ b/test/end-to-end-tests/src/usecases/memberlist.js @@ -17,7 +17,7 @@ limitations under the License. const assert = require('assert'); -export async function openMemberInfo(session, name) { +async function openMemberInfo(session, name) { const membersAndNames = await getMembersInMemberlist(session); const matchingLabel = membersAndNames.filter((m) => { return m.displayName === name; @@ -25,7 +25,9 @@ export async function openMemberInfo(session, name) { await matchingLabel.click(); } -export async function verifyDeviceForUser(session, name, expectedDevice) { +module.exports.openMemberInfo = openMemberInfo; + +module.exports.verifyDeviceForUser = async function(session, name, expectedDevice) { session.log.step(`verifies e2e device for ${name}`); const membersAndNames = await getMembersInMemberlist(session); const matchingLabel = membersAndNames.filter((m) => { @@ -58,9 +60,9 @@ export async function verifyDeviceForUser(session, name, expectedDevice) { const closeMemberInfo = await session.query(".mx_MemberInfo_cancel"); await closeMemberInfo.click(); session.log.done(); -} +}; -export async function getMembersInMemberlist(session) { +async function getMembersInMemberlist(session) { const memberPanelButton = await session.query(".mx_RightPanel_membersButton"); try { await session.query(".mx_RightPanel_headerButton_highlight", 500); @@ -77,3 +79,5 @@ export async function getMembersInMemberlist(session) { return {label: el, displayName: await session.innerText(el)}; })); } + +module.exports.getMembersInMemberlist = getMembersInMemberlist; diff --git a/test/end-to-end-tests/src/usecases/room-settings.js b/test/end-to-end-tests/src/usecases/room-settings.js index c6a84706cf..f526312f8a 100644 --- a/test/end-to-end-tests/src/usecases/room-settings.js +++ b/test/end-to-end-tests/src/usecases/room-settings.js @@ -30,7 +30,7 @@ async function setSettingsToggle(session, toggle, enabled) { } } -export default async function changeRoomSettings(session, settings) { +module.exports = async function changeRoomSettings(session, settings) { session.log.startGroup(`changes the room settings`); /// XXX delay is needed here, possibly because the header is being rerendered /// click doesn't do anything otherwise diff --git a/test/end-to-end-tests/src/usecases/settings.js b/test/end-to-end-tests/src/usecases/settings.js index 411ec3b497..a405fde9fb 100644 --- a/test/end-to-end-tests/src/usecases/settings.js +++ b/test/end-to-end-tests/src/usecases/settings.js @@ -29,7 +29,7 @@ async function openSettings(session, section) { } } -export async function enableLazyLoading(session) { +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(); @@ -39,9 +39,9 @@ export async function enableLazyLoading(session) { const closeButton = await session.query(".mx_RoomHeader_cancelButton"); await closeButton.click(); session.log.done(); -} +}; -export async function getE2EDeviceFromSettings(session) { +module.exports.getE2EDeviceFromSettings = async function(session) { session.log.step(`gets e2e device/key from settings`); await openSettings(session, "security"); const deviceAndKey = await session.queryAll(".mx_SettingsTab_section .mx_SecurityUserSettingsTab_deviceInfo code"); @@ -52,4 +52,4 @@ export async function getE2EDeviceFromSettings(session) { await closeButton.click(); session.log.done(); return {id, key}; -} +}; diff --git a/test/end-to-end-tests/src/usecases/signup.js b/test/end-to-end-tests/src/usecases/signup.js index 381b87ec9e..ef8a259091 100644 --- a/test/end-to-end-tests/src/usecases/signup.js +++ b/test/end-to-end-tests/src/usecases/signup.js @@ -17,7 +17,7 @@ limitations under the License. const assert = require('assert'); -export default async function signup(session, username, password, homeserver) { +module.exports = async function signup(session, username, password, homeserver) { session.log.step("signs up"); await session.goto(session.url('/#/register')); // change the homeserver by clicking the advanced section diff --git a/test/end-to-end-tests/src/usecases/timeline.js b/test/end-to-end-tests/src/usecases/timeline.js index 8a18e2653f..3889dce108 100644 --- a/test/end-to-end-tests/src/usecases/timeline.js +++ b/test/end-to-end-tests/src/usecases/timeline.js @@ -17,7 +17,7 @@ limitations under the License. const assert = require('assert'); -export async function scrollToTimelineTop(session) { +module.exports.scrollToTimelineTop = async function(session) { session.log.step(`scrolls to the top of the timeline`); await session.page.evaluate(() => { return Promise.resolve().then(async () => { @@ -41,9 +41,9 @@ export async function scrollToTimelineTop(session) { }); }); session.log.done(); -} +}; -export async function receiveMessage(session, expectedMessage) { +module.exports.receiveMessage = async function(session, expectedMessage) { session.log.step(`receives message "${expectedMessage.body}" from ${expectedMessage.sender}`); // wait for a response to come in that contains the message // crude, but effective @@ -67,10 +67,10 @@ export async function receiveMessage(session, expectedMessage) { }); assertMessage(lastMessage, expectedMessage); session.log.done(); -} +}; -export async function checkTimelineContains(session, expectedMessages, sendersDescription) { +module.exports.checkTimelineContains = async function(session, expectedMessages, sendersDescription) { session.log.step(`checks timeline contains ${expectedMessages.length} ` + `given messages${sendersDescription ? ` from ${sendersDescription}`:""}`); const eventTiles = await getAllEventTiles(session); @@ -91,7 +91,7 @@ export async function checkTimelineContains(session, expectedMessages, sendersDe expectedMessages.forEach((expectedMessage) => { const foundMessage = timelineMessages.find((message) => { return message.sender === expectedMessage.sender && - message.body === expectedMessage.body; + message.body === expectedMessage.body; }); try { assertMessage(foundMessage, expectedMessage); @@ -102,7 +102,7 @@ export async function checkTimelineContains(session, expectedMessages, sendersDe }); session.log.done(); -} +}; function assertMessage(foundMessage, expectedMessage) { assert(foundMessage, `message ${JSON.stringify(expectedMessage)} not found in timeline`); diff --git a/test/end-to-end-tests/src/usecases/verify.js b/test/end-to-end-tests/src/usecases/verify.js index a8b71cfe5c..5f507f96e6 100644 --- a/test/end-to-end-tests/src/usecases/verify.js +++ b/test/end-to-end-tests/src/usecases/verify.js @@ -38,7 +38,7 @@ async function getSasCodes(session) { return sasLabels; } -export async function startSasVerifcation(session, name) { +module.exports.startSasVerifcation = async function(session, name) { await startVerification(session, name); // expect "Verify device" dialog and click "Begin Verification" await assertDialog(session, "Verify device"); @@ -51,9 +51,9 @@ export async function startSasVerifcation(session, name) { // click "Got it" when verification is done await acceptDialog(session); return sasCodes; -} +}; -export async function acceptSasVerification(session, name) { +module.exports.acceptSasVerification = async function(session, name) { await assertDialog(session, "Incoming Verification Request"); const opponentLabelElement = await session.query(".mx_IncomingSasDialog_opponentProfile h2"); const opponentLabel = await session.innerText(opponentLabelElement); @@ -67,4 +67,4 @@ export async function acceptSasVerification(session, name) { // click "Got it" when verification is done await acceptDialog(session); return sasCodes; -} +}; diff --git a/test/end-to-end-tests/src/util.js b/test/end-to-end-tests/src/util.js index cafe929eca..cc7391fa9f 100644 --- a/test/end-to-end-tests/src/util.js +++ b/test/end-to-end-tests/src/util.js @@ -15,14 +15,14 @@ See the License for the specific language governing permissions and limitations under the License. */ -export function range(start, amount, step = 1) { +module.exports.range = function(start, amount, step = 1) { const r = []; for (let i = 0; i < amount; ++i) { r.push(start + (i * step)); } return r; -} +}; -export function delay(ms) { +module.exports.delay = function(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); -} +};