diff --git a/src/scenario.js b/src/scenario.js index 840cd3e0dc..70ceae1471 100644 --- a/src/scenario.js +++ b/src/scenario.js @@ -21,7 +21,11 @@ const join = require('./tests/join'); const sendMessage = require('./tests/send-message'); const acceptInvite = require('./tests/accept-invite'); const invite = require('./tests/invite'); -const receiveMessage = require('./tests/receive-message'); +const { + receiveMessage, + checkTimelineContains, + scrollToTimelineTop +} = require('./tests/timeline'); const createRoom = require('./tests/create-room'); const changeRoomSettings = require('./tests/room-settings'); const acceptServerNoticesInviteAndConsent = require('./tests/server-notices-consent'); diff --git a/src/tests/receive-message.js b/src/tests/receive-message.js deleted file mode 100644 index afe4247181..0000000000 --- a/src/tests/receive-message.js +++ /dev/null @@ -1,49 +0,0 @@ -/* -Copyright 2018 New Vector Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -const assert = require('assert'); - -module.exports = async function receiveMessage(session, message) { - session.log.step(`receives message "${message.body}" from ${message.sender}`); - // wait for a response to come in that contains the message - // crude, but effective - await session.page.waitForResponse(async (response) => { - if (response.request().url().indexOf("/sync") === -1) { - return false; - } - const body = await response.text(); - if (message.encrypted) { - return body.indexOf(message.sender) !== -1 && - body.indexOf("m.room.encrypted") !== -1; - } else { - return body.indexOf(message.body) !== -1; - } - }); - // wait a bit for the incoming event to be rendered - await session.delay(1000); - let lastTile = await session.query(".mx_EventTile_last"); - const senderElement = await lastTile.$(".mx_SenderProfile_name"); - const bodyElement = await lastTile.$(".mx_EventTile_body"); - const sender = await(await senderElement.getProperty("innerText")).jsonValue(); - const body = await(await bodyElement.getProperty("innerText")).jsonValue(); - if (message.encrypted) { - const e2eIcon = await lastTile.$(".mx_EventTile_e2eIcon"); - assert.ok(e2eIcon); - } - assert.equal(body, message.body); - assert.equal(sender, message.sender); - session.log.done(); -} diff --git a/src/tests/timeline.js b/src/tests/timeline.js new file mode 100644 index 0000000000..1e724a2d39 --- /dev/null +++ b/src/tests/timeline.js @@ -0,0 +1,125 @@ +/* +Copyright 2018 New Vector Ltd + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +const assert = require('assert'); + +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 () => { + const timelineScrollView = document.querySelector(".mx_RoomView .gm-scroll-view"); + let timedOut = false; + let timeoutHandle = null; + // set scrollTop to 0 in a loop and check every 50ms + // if content became available (scrollTop not being 0 anymore), + // assume everything is loaded after 1000ms + do { + if (timelineScrollView.scrollTop !== 0) { + if (timeoutHandle) { + clearTimeout(timeoutHandle); + } + timeoutHandle = setTimeout(() => timedOut = true, 1000); + timelineScrollView.scrollTop = 0; + } else { + await new Promise((resolve) => setTimeout(resolve, 50)); + } + } while (!timedOut) + }); + }) + session.log.done(); +} + +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 + await session.page.waitForResponse(async (response) => { + if (response.request().url().indexOf("/sync") === -1) { + return false; + } + const body = await response.text(); + if (expectedMessage.encrypted) { + return body.indexOf(expectedMessage.sender) !== -1 && + body.indexOf("m.room.encrypted") !== -1; + } else { + return body.indexOf(expectedMessage.body) !== -1; + } + }); + // wait a bit for the incoming event to be rendered + await session.delay(1000); + const lastTile = await getLastEventTile(session); + const foundMessage = await getMessageFromEventTile(lastTile); + assertMessage(foundMessage, expectedMessage); + session.log.done(); +} + + +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); + let timelineMessages = await Promise.all(eventTiles.map((eventTile) => { + return getMessageFromEventTile(eventTile); + })); + //filter out tiles that were not messages + timelineMessages = timelineMessages .filter((m) => !!m); + expectedMessages.forEach((expectedMessage) => { + const foundMessage = timelineMessages.find((message) => { + return message.sender === expectedMessage.sender && + message.body === expectedMessage.body; + }); + assertMessage(foundMessage, expectedMessage); + }); + + session.log.done(); +} + +function assertMessage(foundMessage, expectedMessage) { + assert(foundMessage, `message ${JSON.stringify(expectedMessage)} not found in timeline`); + assert.equal(foundMessage.body, expectedMessage.body); + assert.equal(foundMessage.sender, expectedMessage.sender); + if (expectedMessage.hasOwnProperty("encrypted")) { + assert.equal(foundMessage.encrypted, expectedMessage.encrypted); + } +} + +function getLastEventTile(session) { + return session.query(".mx_EventTile_last"); +} + +function getAllEventTiles(session) { + return session.queryAll(".mx_RoomView_MessageList > *"); +} + +async function getMessageFromEventTile(eventTile) { + const senderElement = await eventTile.$(".mx_SenderProfile_name"); + const bodyElement = await eventTile.$(".mx_EventTile_body"); + let sender = null; + if (senderElement) { + sender = await(await senderElement.getProperty("innerText")).jsonValue(); + } + if (!bodyElement) { + return null; + } + const body = await(await bodyElement.getProperty("innerText")).jsonValue(); + const e2eIcon = await eventTile.$(".mx_EventTile_e2eIcon"); + + return { + sender, + body, + encrypted: !!e2eIcon + }; +}