From 6199287fe71beaaa6706e1082ecc4694be2794fe Mon Sep 17 00:00:00 2001
From: Michael Telatynski <7t3chguy@gmail.com>
Date: Mon, 11 Dec 2023 14:36:30 +0000
Subject: [PATCH] Migrate audio-player.spec.ts from Cypress to Playwright
(#12008)
* Migrate audio-player.spec.ts from Cypress to Playwright
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
* Stabilise screenshots
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
* Stabilise bot MXID length
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
* Stabilise test user MXID
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
* Stabilise timestamps
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
* Update screenshots
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
* Update element-web-test.ts
* Use deterministic monospace font
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---------
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
---
cypress/e2e/audio-player/audio-player.spec.ts | 387 ------------------
.../e2e/audio-player/audio-player.spec.ts | 351 ++++++++++++++++
playwright/element-web-test.ts | 15 +-
...layer--dark-theme--bubble-layout-linux.png | Bin 0 -> 5666 bytes
...player--dark-theme--group-layout-linux.png | Bin 0 -> 10650 bytes
...o-player--dark-theme--irc-layout-linux.png | Bin 0 -> 7613 bytes
...er--high-contrast--bubble-layout-linux.png | Bin 0 -> 5650 bytes
...yer--high-contrast--group-layout-linux.png | Bin 0 -> 10701 bytes
...layer--high-contrast--irc-layout-linux.png | Bin 0 -> 7758 bytes
...ayer--light-theme--bubble-layout-linux.png | Bin 0 -> 5541 bytes
...layer--light-theme--group-layout-linux.png | Bin 0 -> 10518 bytes
...-player--light-theme--irc-layout-linux.png | Bin 0 -> 7699 bytes
...e--monospace-font--bubble-layout-linux.png | Bin 0 -> 5483 bytes
...me--monospace-font--group-layout-linux.png | Bin 0 -> 10763 bytes
...heme--monospace-font--irc-layout-linux.png | Bin 0 -> 7683 bytes
...layer-with-a-reply-bubble-layout-linux.png | Bin 0 -> 10197 bytes
...with-a-reply-chain-bubble-layout-linux.png | Bin 0 -> 17004 bytes
...-with-a-reply-chain-group-layout-linux.png | Bin 0 -> 18261 bytes
...er-with-a-reply-chain-irc-layout-linux.png | Bin 0 -> 19289 bytes
...player-with-a-reply-group-layout-linux.png | Bin 0 -> 11452 bytes
...o-player-with-a-reply-irc-layout-linux.png | Bin 0 -> 12434 bytes
21 files changed, 364 insertions(+), 389 deletions(-)
delete mode 100644 cypress/e2e/audio-player/audio-player.spec.ts
create mode 100644 playwright/e2e/audio-player/audio-player.spec.ts
create mode 100644 playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--dark-theme--bubble-layout-linux.png
create mode 100644 playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--dark-theme--group-layout-linux.png
create mode 100644 playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--dark-theme--irc-layout-linux.png
create mode 100644 playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--high-contrast--bubble-layout-linux.png
create mode 100644 playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--high-contrast--group-layout-linux.png
create mode 100644 playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--high-contrast--irc-layout-linux.png
create mode 100644 playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--light-theme--bubble-layout-linux.png
create mode 100644 playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--light-theme--group-layout-linux.png
create mode 100644 playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--light-theme--irc-layout-linux.png
create mode 100644 playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--light-theme--monospace-font--bubble-layout-linux.png
create mode 100644 playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--light-theme--monospace-font--group-layout-linux.png
create mode 100644 playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--light-theme--monospace-font--irc-layout-linux.png
create mode 100644 playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player-with-a-reply-bubble-layout-linux.png
create mode 100644 playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player-with-a-reply-chain-bubble-layout-linux.png
create mode 100644 playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player-with-a-reply-chain-group-layout-linux.png
create mode 100644 playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player-with-a-reply-chain-irc-layout-linux.png
create mode 100644 playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player-with-a-reply-group-layout-linux.png
create mode 100644 playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player-with-a-reply-irc-layout-linux.png
diff --git a/cypress/e2e/audio-player/audio-player.spec.ts b/cypress/e2e/audio-player/audio-player.spec.ts
deleted file mode 100644
index 30470716c9..0000000000
--- a/cypress/e2e/audio-player/audio-player.spec.ts
+++ /dev/null
@@ -1,387 +0,0 @@
-/*
-Copyright 2023 Suguru Hirahara
-
-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.
-*/
-
-///
-
-import { HomeserverInstance } from "../../plugins/utils/homeserver";
-import { SettingLevel } from "../../../src/settings/SettingLevel";
-import { Layout } from "../../../src/settings/enums/Layout";
-
-describe("Audio player", () => {
- let homeserver: HomeserverInstance;
- const TEST_USER = "Hanako";
-
- const percyCSS =
- // FIXME: hide mx_SeekBar because flaky - see https://github.com/vector-im/element-web/issues/24898
- ".mx_SeekBar, " +
- // Exclude various components from the snapshot, for consistency
- ".mx_JumpToBottomButton, " +
- ".mx_MessageTimestamp, .mx_MessagePanel_myReadMarker { visibility: hidden !important; }";
-
- const uploadFile = (file: string) => {
- // Upload a file from the message composer
- cy.get(".mx_MessageComposer_actions input[type='file']").selectFile(file, { force: true });
-
- cy.get(".mx_Dialog").within(() => {
- // Find and click primary "Upload" button
- cy.findByRole("button", { name: "Upload" }).click();
- });
-
- // Wait until the file is sent
- cy.get(".mx_RoomView_statusArea_expanded").should("not.exist");
- cy.get(".mx_EventTile.mx_EventTile_last .mx_EventTile_receiptSent").should("exist");
- // wait for the tile to finish loading
- cy.get(".mx_AudioPlayer_mediaName").should("exist");
- };
-
- /**
- * Take snapshots of mx_EventTile_last on each layout, outputting log for reference/debugging.
- * @param detail The Percy snapshot name. Used for outputting logs too.
- * @param monospace This changes the font used to render the UI from a default one to a monospace one.
- * Set to false by default. Note that the font applied to Percy snapshots can be different from the test result
- * on your local environment.
- */
- const takeSnapshots = (detail: string, monospace = false) => {
- // Check that the audio player is rendered and its button becomes visible
- const checkPlayerVisibility = () => {
- // Assert that the audio player and media information are visible
- cy.get(".mx_EventTile_mediaLine .mx_MAudioBody .mx_AudioPlayer_container .mx_AudioPlayer_mediaInfo").within(
- () => {
- cy.contains(".mx_AudioPlayer_mediaName", ".ogg").should("be.visible"); // extension
- cy.contains(".mx_AudioPlayer_byline", "00:01").should("be.visible");
- cy.contains(".mx_AudioPlayer_byline", "(3.56 KB)").should("be.visible"); // actual size
- },
- );
-
- // Assert that the play button can be found and is visible
- cy.findByRole("button", { name: "Play" }).should("be.visible");
-
- if (monospace) {
- // Assert that the monospace timer is visible
- cy.get("[role='timer']").should("have.css", "font-family", '"monospace"').should("be.visible");
- }
- };
-
- /**
- * Define snapshot widths of selected EventTile, on which the audio player is rendered
- *
- * 50px (magic number): narrow enough EventTile to be compressed to check a11y
- * 267px: EventTile on IRC and modern/group layout, on which the player is rendered in its full width
- * 285px: EventTile on bubble layout, on which the player is rendered in its full width
- */
- const snapshotWidthsIRC = [50, 267];
- const snapshotWidthsGroup = snapshotWidthsIRC;
- const snapshotWidthsBubble = [50, 285];
-
- if (monospace) {
- // Enable system font and monospace setting
- cy.setSettingValue("useSystemFont", null, SettingLevel.DEVICE, true);
- cy.setSettingValue("systemFont", null, SettingLevel.DEVICE, "monospace");
- }
-
- // Check the status of the seek bar
- // TODO: check if visible - currently checking its visibility on a compressed EventTile returns an error
- cy.get(".mx_AudioPlayer_seek input[type='range']").should("exist");
-
- // Enable IRC layout
- cy.setSettingValue("layout", null, SettingLevel.DEVICE, Layout.IRC);
-
- cy.get(".mx_EventTile_last[data-layout='irc']").within(() => {
- // Click the event timestamp to highlight EventTile in case it is not visible
- cy.get(".mx_MessageTimestamp").click();
-
- // Assert that rendering of the player settled and the play button is visible before taking a snapshot
- checkPlayerVisibility();
- });
-
- // Take a snapshot of mx_EventTile_last on IRC layout
- cy.get(".mx_EventTile_last").percySnapshotElement(detail + " on IRC layout", {
- percyCSS,
- widths: snapshotWidthsIRC,
- });
-
- // Output a log
- cy.log("Took a snapshot of " + detail + " on IRC layout");
-
- // Take a snapshot on modern/group layout
- cy.setSettingValue("layout", null, SettingLevel.DEVICE, Layout.Group);
- cy.get(".mx_EventTile_last[data-layout='group']").within(() => {
- cy.get(".mx_MessageTimestamp").click();
- checkPlayerVisibility();
- });
- cy.get(".mx_EventTile_last").percySnapshotElement(detail + " on modern/group layout", {
- percyCSS,
- widths: snapshotWidthsGroup,
- });
- cy.log("Took a snapshot of " + detail + " on modern/group layout");
-
- // Take a snapshot on bubble layout
- cy.setSettingValue("layout", null, SettingLevel.DEVICE, Layout.Bubble);
- cy.get(".mx_EventTile_last[data-layout='bubble']").within(() => {
- cy.get(".mx_MessageTimestamp").click();
- checkPlayerVisibility();
- });
- cy.get(".mx_EventTile_last").percySnapshotElement(detail + " on bubble layout", {
- percyCSS,
- widths: snapshotWidthsBubble,
- });
- cy.log("Took a snapshot of " + detail + " on bubble layout");
- };
-
- beforeEach(() => {
- cy.startHomeserver("default").then((data) => {
- homeserver = data;
- cy.initTestUser(homeserver, TEST_USER);
- });
-
- cy.createRoom({ name: "Test Room" }).viewRoomByName("Test Room");
-
- // Wait until configuration is finished
- cy.get(".mx_GenericEventListSummary[data-layout='group'] .mx_GenericEventListSummary_summary").within(() => {
- cy.findByText(TEST_USER + " created and configured the room.").should("exist");
- });
- });
-
- afterEach(() => {
- cy.stopHomeserver(homeserver);
- });
-
- it("should be correctly rendered - light theme", () => {
- uploadFile("cypress/fixtures/1sec-long-name-audio-file.ogg");
-
- takeSnapshots("Selected EventTile of audio player (light theme)");
- });
-
- it("should be correctly rendered - light theme with monospace font", () => {
- uploadFile("cypress/fixtures/1sec-long-name-audio-file.ogg");
-
- // Disabled because flaky - see https://github.com/vector-im/element-web/issues/24881
- //takeSnapshots("Selected EventTile of audio player (light theme, monospace font)", true); // Enable monospace
- });
-
- it("should be correctly rendered - high contrast theme", () => {
- // Disable system theme in case ThemeWatcher enables the theme automatically,
- // so that the high contrast theme can be enabled
- cy.setSettingValue("use_system_theme", null, SettingLevel.DEVICE, false);
-
- // Enable high contrast manually
- cy.openUserSettings("Appearance")
- .findByTestId("mx_ThemeChoicePanel")
- .findByLabelText("Use high contrast")
- .click({ force: true }); // force click because the size of the checkbox is zero
-
- cy.closeDialog();
-
- uploadFile("cypress/fixtures/1sec-long-name-audio-file.ogg");
-
- // Disabled because flaky - see https://github.com/vector-im/element-web/issues/24881
- //takeSnapshots("Selected EventTile of audio player (high contrast)");
- });
-
- it("should be correctly rendered - dark theme", () => {
- // Enable dark theme
- cy.setSettingValue("theme", null, SettingLevel.ACCOUNT, "dark");
-
- uploadFile("cypress/fixtures/1sec-long-name-audio-file.ogg");
-
- takeSnapshots("Selected EventTile of audio player (dark theme)");
- });
-
- it("should play an audio file", () => {
- uploadFile("cypress/fixtures/1sec.ogg");
-
- // Assert that the audio player is rendered
- cy.get(".mx_EventTile_last .mx_EventTile_mediaLine .mx_MAudioBody .mx_AudioPlayer_container").within(() => {
- // Assert that the counter is zero before clicking the play button
- cy.contains(".mx_AudioPlayer_seek [role='timer']", "00:00").should("exist");
-
- // Find and click "Play" button, the wait is to make the test less flaky
- cy.findByRole("button", { name: "Play" }).should("exist");
- cy.wait(500).findByRole("button", { name: "Play" }).click();
-
- // Assert that "Pause" button can be found
- cy.findByRole("button", { name: "Pause" }).should("exist");
-
- // Assert that the timer is reset when the audio file finished playing
- cy.contains(".mx_AudioPlayer_seek [role='timer']", "00:00").should("exist");
-
- // Assert that "Play" button can be found
- cy.findByRole("button", { name: "Play" }).should("exist");
- });
- });
-
- it("should support downloading an audio file", () => {
- uploadFile("cypress/fixtures/1sec.ogg");
-
- // Find and click "Download" button on MessageActionBar
- cy.get(".mx_EventTile_last").realHover().findByRole("button", { name: "Download" }).click();
-
- // Assert that the file was downloaded
- cy.readFile("cypress/downloads/1sec.ogg").should("exist");
- });
-
- it("should support replying to audio file with another audio file", () => {
- uploadFile("cypress/fixtures/1sec.ogg");
-
- // Assert the audio player is rendered
- cy.get(".mx_EventTile_last .mx_AudioPlayer_container").should("exist");
-
- // Find and click "Reply" button on MessageActionBar
- cy.get(".mx_EventTile_last").realHover().findByRole("button", { name: "Reply" }).click();
-
- // Reply to the player with another audio file
- uploadFile("cypress/fixtures/1sec.ogg");
-
- cy.get(".mx_EventTile_last").within(() => {
- // Assert that the audio player is rendered
- cy.get(".mx_AudioPlayer_container").should("exist");
-
- // Assert that replied audio file is rendered as file button inside ReplyChain
- cy.get(".mx_ReplyChain_wrapper .mx_MFileBody_info[role='button']").within(() => {
- // Assert that the file button has file name
- cy.get(".mx_MFileBody_info_filename").should("exist");
- });
- });
-
- // Disabled because flaky - see https://github.com/vector-im/element-web/issues/24881
- //takeSnapshots("Selected EventTile of audio player with a reply");
- });
-
- it("should support creating a reply chain with multiple audio files", () => {
- // Note: "mx_ReplyChain" element is used not only for replies which
- // create a reply chain, but also for a single reply without a replied
- // message. This test checks whether a reply chain which consists of
- // multiple audio file replies is rendered properly.
-
- // Find and click "Reply" button
- const clickButtonReply = () => {
- cy.get(".mx_EventTile_last").realHover().findByRole("button", { name: "Reply" }).click();
- };
-
- uploadFile("cypress/fixtures/upload-first.ogg");
-
- // Assert that the audio player is rendered
- cy.get(".mx_EventTile_last .mx_AudioPlayer_container").should("exist");
-
- clickButtonReply();
-
- // Reply to the player with another audio file
- uploadFile("cypress/fixtures/upload-second.ogg");
-
- // Assert that the audio player is rendered
- cy.get(".mx_EventTile_last .mx_AudioPlayer_container").should("exist");
-
- clickButtonReply();
-
- // Reply to the player with yet another audio file to create a reply chain
- uploadFile("cypress/fixtures/upload-third.ogg");
-
- cy.get(".mx_EventTile_last").within(() => {
- // Assert that the audio player is rendered
- cy.get(".mx_AudioPlayer_container").should("exist");
-
- // Assert that there are two "mx_ReplyChain" elements
- cy.get(".mx_ReplyChain").should("have.length", 2);
-
- // Assert that one line contains the user name
- cy.get(".mx_ReplyChain .mx_ReplyTile_sender").within(() => {
- cy.findByText(TEST_USER);
- });
-
- // Assert that the other line contains the file button
- cy.get(".mx_ReplyChain .mx_MFileBody").should("exist");
-
- // Click "In reply to"
- cy.contains(".mx_ReplyChain .mx_ReplyChain_show", "In reply to").click();
-
- cy.get("blockquote.mx_ReplyChain:first-of-type").within(() => {
- // Assert that "In reply to" has disappeared
- cy.findByText("In reply to").should("not.exist");
-
- // Assert that audio file on the first row is rendered as file button
- cy.get(".mx_MFileBody_info[role='button']").within(() => {
- // Assert that the file button contains the name of the file sent at first
- cy.contains(".mx_MFileBody_info_filename", "upload-first.ogg");
- });
- });
- });
-
- // Take snapshots
- takeSnapshots("Selected EventTile of audio player with a reply chain");
- });
-
- it("should be rendered, play, and support replying on a thread", () => {
- uploadFile("cypress/fixtures/1sec-long-name-audio-file.ogg");
-
- // On the main timeline
- cy.get(".mx_RoomView_MessageList").within(() => {
- // Assert the audio player is rendered
- cy.get(".mx_EventTile_last .mx_AudioPlayer_container").should("exist");
-
- // Find and click "Reply in thread" button
- cy.get(".mx_EventTile_last").realHover().findByRole("button", { name: "Reply in thread" }).click();
- });
-
- // On a thread
- cy.get(".mx_ThreadView").within(() => {
- cy.get(".mx_EventTile_last").within(() => {
- // Assert that the player is correctly rendered on a thread
- cy.get(".mx_EventTile_mediaLine .mx_MAudioBody .mx_AudioPlayer_container").within(() => {
- // Assert that the counter is zero before clicking the play button
- cy.contains(".mx_AudioPlayer_seek [role='timer']", "00:00").should("exist");
-
- // Find and click "Play" button, the wait is to make the test less flaky
- cy.findByRole("button", { name: "Play" }).should("exist");
- cy.wait(500).findByRole("button", { name: "Play" }).click();
-
- // Assert that "Pause" button can be found
- cy.findByRole("button", { name: "Pause" }).should("exist");
-
- // Assert that the timer is reset when the audio file finished playing
- cy.contains(".mx_AudioPlayer_seek [role='timer']", "00:00").should("exist");
-
- // Assert that "Play" button can be found
- cy.findByRole("button", { name: "Play" }).should("exist").should("not.have.attr", "disabled");
- });
- });
-
- // Find and click "Reply" button
- //
- // Calling cy.get(".mx_EventTile_last") again here is a workaround for
- // https://github.com/matrix-org/matrix-js-sdk/issues/3394: the event tile may have been re-mounted while
- // the audio was playing.
- cy.get(".mx_EventTile_last").realHover().findByRole("button", { name: "Reply" }).click();
-
- cy.get(".mx_MessageComposer--compact").within(() => {
- // Assert that the reply preview is rendered on the message composer
- cy.get(".mx_ReplyPreview").within(() => {
- // Assert that the reply preview contains audio ReplyTile the file info button
- cy.get(".mx_ReplyTile_audio .mx_MFileBody_info[role='button']").should("exist");
- });
-
- // Select :smile: emoji and send it
- cy.findByTestId("basicmessagecomposer").type(":smile:");
- cy.get(".mx_Autocomplete_Completion[aria-selected='true']").click();
- cy.findByTestId("basicmessagecomposer").type("{enter}");
- });
-
- cy.get(".mx_EventTile_last").within(() => {
- // Assert that the file name is rendered on the file button
- cy.get(".mx_ReplyTile_audio .mx_MFileBody_info[role='button']").should("exist");
- });
- });
- });
-});
diff --git a/playwright/e2e/audio-player/audio-player.spec.ts b/playwright/e2e/audio-player/audio-player.spec.ts
new file mode 100644
index 0000000000..f7aaf1fb46
--- /dev/null
+++ b/playwright/e2e/audio-player/audio-player.spec.ts
@@ -0,0 +1,351 @@
+/*
+Copyright 2023 Suguru Hirahara
+Copyright 2023 The Matrix.org Foundation C.I.C.
+
+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.
+*/
+
+import type { Locator, Page } from "@playwright/test";
+import { test, expect } from "../../element-web-test";
+import { SettingLevel } from "../../../src/settings/SettingLevel";
+import { Layout } from "../../../src/settings/enums/Layout";
+import { ElementAppPage } from "../../pages/ElementAppPage";
+
+test.describe("Audio player", () => {
+ test.use({
+ displayName: "Hanako",
+ });
+
+ const uploadFile = async (page: Page, file: string) => {
+ // Upload a file from the message composer
+ await page.locator(".mx_MessageComposer_actions input[type='file']").setInputFiles(file);
+
+ // Find and click primary "Upload" button
+ await page.locator(".mx_Dialog").getByRole("button", { name: "Upload" }).click();
+
+ // Wait until the file is sent
+ await expect(page.locator(".mx_RoomView_statusArea_expanded")).not.toBeVisible();
+ await expect(page.locator(".mx_EventTile.mx_EventTile_last .mx_EventTile_receiptSent")).toBeVisible();
+ // wait for the tile to finish loading
+ await expect(
+ page
+ .locator(".mx_AudioPlayer_mediaName")
+ .last()
+ .filter({ hasText: file.split("/").at(-1) }),
+ ).toBeVisible();
+ };
+
+ /**
+ * Take snapshots of mx_EventTile_last on each layout, outputting log for reference/debugging.
+ * @param detail The snapshot name. Used for outputting logs too.
+ * @param monospace This changes the font used to render the UI from a default one to Inconsolata. Set to false by default.
+ */
+ const takeSnapshots = async (page: Page, app: ElementAppPage, detail: string, monospace = false) => {
+ // Check that the audio player is rendered and its button becomes visible
+ const checkPlayerVisibility = async (locator: Locator) => {
+ // Assert that the audio player and media information are visible
+ const mediaInfo = locator.locator(
+ ".mx_EventTile_mediaLine .mx_MAudioBody .mx_AudioPlayer_container .mx_AudioPlayer_mediaInfo",
+ );
+ await expect(mediaInfo.locator(".mx_AudioPlayer_mediaName", { hasText: ".ogg" })).toBeVisible(); // extension
+ await expect(mediaInfo.locator(".mx_AudioPlayer_byline", { hasText: "00:01" })).toBeVisible();
+ await expect(mediaInfo.locator(".mx_AudioPlayer_byline", { hasText: "(3.56 KB)" })).toBeVisible(); // actual size
+
+ // Assert that the play button can be found and is visible
+ await expect(locator.getByRole("button", { name: "Play" })).toBeVisible();
+
+ if (monospace) {
+ // Assert that the monospace timer is visible
+ await expect(locator.locator("[role='timer']")).toHaveCSS("font-family", "Inconsolata");
+ }
+ };
+
+ if (monospace) {
+ // Enable system font and monospace setting
+ await app.settings.setValue("useBundledEmojiFont", null, SettingLevel.DEVICE, false);
+ await app.settings.setValue("useSystemFont", null, SettingLevel.DEVICE, true);
+ await app.settings.setValue("systemFont", null, SettingLevel.DEVICE, "Inconsolata");
+ }
+
+ // Check the status of the seek bar
+ expect(await page.locator(".mx_AudioPlayer_seek input[type='range']").count()).toBeGreaterThan(0);
+
+ // Enable IRC layout
+ await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.IRC);
+
+ const ircTile = page.locator(".mx_EventTile_last[data-layout='irc']");
+ // Click the event timestamp to highlight EventTile in case it is not visible
+ await ircTile.locator(".mx_MessageTimestamp").click();
+ // Assert that rendering of the player settled and the play button is visible before taking a snapshot
+ await checkPlayerVisibility(ircTile);
+
+ const screenshotOptions = {
+ css: `
+ /* The timestamp is of inconsistent width depending on the time the test runs at */
+ .mx_MessageTimestamp {
+ display: none !important;
+ }
+ `,
+ mask: [page.locator(".mx_AudioPlayer_seek")],
+ };
+
+ // Take a snapshot of mx_EventTile_last on IRC layout
+ await expect(page.locator(".mx_EventTile_last")).toMatchScreenshot(
+ `${detail.replaceAll(" ", "-")}-irc-layout.png`,
+ screenshotOptions,
+ );
+
+ // Take a snapshot on modern/group layout
+ await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.Group);
+ const groupTile = page.locator(".mx_EventTile_last[data-layout='group']");
+ await groupTile.locator(".mx_MessageTimestamp").click();
+ await checkPlayerVisibility(groupTile);
+ await expect(page.locator(".mx_EventTile_last")).toMatchScreenshot(
+ `${detail.replaceAll(" ", "-")}-group-layout.png`,
+ screenshotOptions,
+ );
+
+ // Take a snapshot on bubble layout
+ await app.settings.setValue("layout", null, SettingLevel.DEVICE, Layout.Bubble);
+ const bubbleTile = page.locator(".mx_EventTile_last[data-layout='bubble']");
+ await bubbleTile.locator(".mx_MessageTimestamp").click();
+ await checkPlayerVisibility(bubbleTile);
+ await expect(page.locator(".mx_EventTile_last")).toMatchScreenshot(
+ `${detail.replaceAll(" ", "-")}-bubble-layout.png`,
+ screenshotOptions,
+ );
+ };
+
+ test.beforeEach(async ({ page, app, user }) => {
+ await app.client.createRoom({ name: "Test Room" });
+ await app.viewRoomByName("Test Room");
+
+ // Wait until configuration is finished
+ await expect(
+ page
+ .locator(".mx_GenericEventListSummary[data-layout='group'] .mx_GenericEventListSummary_summary")
+ .getByText(`${user.displayName} created and configured the room.`),
+ ).toBeVisible();
+ });
+
+ test("should be correctly rendered - light theme", async ({ page, app }) => {
+ await uploadFile(page, "cypress/fixtures/1sec-long-name-audio-file.ogg");
+ await takeSnapshots(page, app, "Selected EventTile of audio player (light theme)");
+ });
+
+ test("should be correctly rendered - light theme with monospace font", async ({ page, app }) => {
+ await uploadFile(page, "cypress/fixtures/1sec-long-name-audio-file.ogg");
+
+ await takeSnapshots(page, app, "Selected EventTile of audio player (light theme, monospace font)", true); // Enable monospace
+ });
+
+ test("should be correctly rendered - high contrast theme", async ({ page, app }) => {
+ // Disable system theme in case ThemeWatcher enables the theme automatically,
+ // so that the high contrast theme can be enabled
+ await app.settings.setValue("use_system_theme", null, SettingLevel.DEVICE, false);
+
+ // Enable high contrast manually
+ const settings = await app.settings.openUserSettings("Appearance");
+ await settings.getByTestId("mx_ThemeChoicePanel").getByText("Use high contrast").click();
+
+ await app.closeDialog();
+
+ await uploadFile(page, "cypress/fixtures/1sec-long-name-audio-file.ogg");
+
+ await takeSnapshots(page, app, "Selected EventTile of audio player (high contrast)");
+ });
+
+ test("should be correctly rendered - dark theme", async ({ page, app }) => {
+ // Enable dark theme
+ await app.settings.setValue("theme", null, SettingLevel.ACCOUNT, "dark");
+
+ await uploadFile(page, "cypress/fixtures/1sec-long-name-audio-file.ogg");
+
+ await takeSnapshots(page, app, "Selected EventTile of audio player (dark theme)");
+ });
+
+ test("should play an audio file", async ({ page, app }) => {
+ await uploadFile(page, "cypress/fixtures/1sec.ogg");
+
+ // Assert that the audio player is rendered
+ const container = page.locator(".mx_EventTile_last .mx_AudioPlayer_container");
+ // Assert that the counter is zero before clicking the play button
+ await expect(container.locator(".mx_AudioPlayer_seek [role='timer']", { hasText: "00:00" })).toBeVisible();
+
+ // Find and click "Play" button, the wait is to make the test less flaky
+ await expect(container.getByRole("button", { name: "Play" })).toBeVisible();
+ await container.getByRole("button", { name: "Play" }).click();
+
+ // Assert that "Pause" button can be found
+ await expect(container.getByRole("button", { name: "Pause" })).toBeVisible();
+
+ // Assert that the timer is reset when the audio file finished playing
+ await expect(container.locator(".mx_AudioPlayer_seek [role='timer']", { hasText: "00:00" })).toBeVisible();
+
+ // Assert that "Play" button can be found
+ await expect(container.getByRole("button", { name: "Play" })).toBeVisible();
+ });
+
+ test("should support downloading an audio file", async ({ page, app }) => {
+ await uploadFile(page, "cypress/fixtures/1sec.ogg");
+
+ const downloadPromise = page.waitForEvent("download");
+
+ // Find and click "Download" button on MessageActionBar
+ const tile = page.locator(".mx_EventTile_last");
+ await tile.hover();
+ await tile.getByRole("button", { name: "Download" }).click();
+
+ // Assert that the file was downloaded
+ const download = await downloadPromise;
+ expect(download.suggestedFilename()).toBe("1sec.ogg");
+ });
+
+ test("should support replying to audio file with another audio file", async ({ page, app }) => {
+ await uploadFile(page, "cypress/fixtures/1sec.ogg");
+
+ // Assert the audio player is rendered
+ await expect(page.locator(".mx_EventTile_last .mx_AudioPlayer_container")).toBeVisible();
+
+ // Find and click "Reply" button on MessageActionBar
+ const tile = page.locator(".mx_EventTile_last");
+ await tile.hover();
+ await tile.getByRole("button", { name: "Reply", exact: true }).click();
+
+ // Reply to the player with another audio file
+ await uploadFile(page, "cypress/fixtures/1sec.ogg");
+
+ // Assert that the audio player is rendered
+ await expect(tile.locator(".mx_AudioPlayer_container")).toBeVisible();
+
+ // Assert that replied audio file is rendered as file button inside ReplyChain
+ const button = tile.locator(".mx_ReplyChain_wrapper .mx_MFileBody_info[role='button']");
+ // Assert that the file button has file name
+ await expect(button.locator(".mx_MFileBody_info_filename")).toBeVisible();
+
+ await takeSnapshots(page, app, "Selected EventTile of audio player with a reply");
+ });
+
+ test("should support creating a reply chain with multiple audio files", async ({ page, app, user }) => {
+ // Note: "mx_ReplyChain" element is used not only for replies which
+ // create a reply chain, but also for a single reply without a replied
+ // message. This test checks whether a reply chain which consists of
+ // multiple audio file replies is rendered properly.
+
+ const tile = page.locator(".mx_EventTile_last");
+
+ // Find and click "Reply" button
+ const clickButtonReply = async () => {
+ await tile.hover();
+ await tile.getByRole("button", { name: "Reply", exact: true }).click();
+ };
+
+ await uploadFile(page, "cypress/fixtures/upload-first.ogg");
+
+ // Assert that the audio player is rendered
+ await expect(page.locator(".mx_EventTile_last .mx_AudioPlayer_container")).toBeVisible();
+
+ await clickButtonReply();
+
+ // Reply to the player with another audio file
+ await uploadFile(page, "cypress/fixtures/upload-second.ogg");
+
+ // Assert that the audio player is rendered
+ await expect(page.locator(".mx_EventTile_last .mx_AudioPlayer_container")).toBeVisible();
+
+ await clickButtonReply();
+
+ // Reply to the player with yet another audio file to create a reply chain
+ await uploadFile(page, "cypress/fixtures/upload-third.ogg");
+
+ // Assert that the audio player is rendered
+ await expect(tile.locator(".mx_AudioPlayer_container")).toBeVisible();
+
+ // Assert that there are two "mx_ReplyChain" elements
+ await expect(tile.locator(".mx_ReplyChain")).toHaveCount(2);
+
+ // Assert that one line contains the user name
+ await expect(tile.locator(".mx_ReplyChain .mx_ReplyTile_sender").getByText(user.displayName)).toBeVisible();
+
+ // Assert that the other line contains the file button
+ await expect(tile.locator(".mx_ReplyChain .mx_MFileBody")).toBeVisible();
+
+ // Click "In reply to"
+ await tile.locator(".mx_ReplyChain .mx_ReplyChain_show", { hasText: "In reply to" }).click();
+
+ const replyChain = tile.locator(".mx_ReplyChain:first-of-type");
+ // Assert that "In reply to" has disappeared
+ await expect(replyChain.getByText("In reply to")).not.toBeVisible();
+
+ // Assert that the file button contains the name of the file sent at first
+ await expect(
+ replyChain
+ .locator(".mx_MFileBody_info[role='button']")
+ .locator(".mx_MFileBody_info_filename", { hasText: "upload-first.ogg" }),
+ ).toBeVisible();
+
+ // Take snapshots
+ await takeSnapshots(page, app, "Selected EventTile of audio player with a reply chain");
+ });
+
+ test("should be rendered, play, and support replying on a thread", async ({ page, app }) => {
+ await uploadFile(page, "cypress/fixtures/1sec-long-name-audio-file.ogg");
+
+ // On the main timeline
+ const messageList = page.locator(".mx_RoomView_MessageList");
+ // Assert the audio player is rendered
+ await expect(messageList.locator(".mx_EventTile_last .mx_AudioPlayer_container")).toBeVisible();
+ // Find and click "Reply in thread" button
+ await messageList.locator(".mx_EventTile_last").hover();
+ await messageList.locator(".mx_EventTile_last").getByRole("button", { name: "Reply in thread" }).click();
+
+ // On a thread
+ const thread = page.locator(".mx_ThreadView");
+ const threadTile = thread.locator(".mx_EventTile_last");
+ const audioPlayer = threadTile.locator(".mx_AudioPlayer_container");
+
+ // Assert that the counter is zero before clicking the play button
+ await expect(audioPlayer.locator(".mx_AudioPlayer_seek [role='timer']", { hasText: "00:00" })).toBeVisible();
+
+ // Find and click "Play" button, the wait is to make the test less flaky
+ await expect(audioPlayer.getByRole("button", { name: "Play" })).toBeVisible();
+ await audioPlayer.getByRole("button", { name: "Play" }).click();
+
+ // Assert that "Pause" button can be found
+ await expect(audioPlayer.getByRole("button", { name: "Pause" })).toBeVisible();
+
+ // Assert that the timer is reset when the audio file finished playing
+ await expect(audioPlayer.locator(".mx_AudioPlayer_seek [role='timer']", { hasText: "00:00" })).toBeVisible();
+
+ // Assert that "Play" button can be found
+ await expect(audioPlayer.getByRole("button", { name: "Play" })).not.toBeDisabled();
+
+ // Find and click "Reply" button
+ await threadTile.hover();
+ await threadTile.getByRole("button", { name: "Reply", exact: true }).click();
+
+ const composer = thread.locator(".mx_MessageComposer--compact");
+ // Assert that the reply preview contains audio ReplyTile the file info button
+ await expect(
+ composer.locator(".mx_ReplyPreview .mx_ReplyTile_audio .mx_MFileBody_info[role='button']"),
+ ).toBeVisible();
+
+ // Select :smile: emoji and send it
+ await composer.getByTestId("basicmessagecomposer").fill(":smile:");
+ await composer.locator(".mx_Autocomplete_Completion[aria-selected='true']").click();
+ await composer.getByTestId("basicmessagecomposer").press("Enter");
+
+ // Assert that the file name is rendered on the file button
+ await expect(threadTile.locator(".mx_ReplyTile_audio .mx_MFileBody_info[role='button']")).toBeVisible();
+ });
+});
diff --git a/playwright/element-web-test.ts b/playwright/element-web-test.ts
index 52bd31c0ce..ee78be2d06 100644
--- a/playwright/element-web-test.ts
+++ b/playwright/element-web-test.ts
@@ -211,7 +211,17 @@ export const test = base.extend<
});
export const expect = baseExpect.extend({
- async toMatchScreenshot(this: ExpectMatcherState, receiver: Page | Locator, ...args) {
+ async toMatchScreenshot(
+ this: ExpectMatcherState,
+ receiver: Page | Locator,
+ name?: `${string}.png`,
+ options?: {
+ mask?: Array;
+ omitBackground?: boolean;
+ timeout?: number;
+ css?: string;
+ },
+ ) {
const page = "page" in receiver ? receiver.page() : receiver;
// We add a custom style tag before taking screenshots
@@ -233,10 +243,11 @@ export const expect = baseExpect.extend({
.mx_ReplyChain {
border-left-color: var(--cpd-color-blue-1200) !important;
}
+ ${options?.css ?? ""}
`,
})) as ElementHandle;
- await baseExpect(receiver).toHaveScreenshot(...args);
+ await baseExpect(receiver).toHaveScreenshot(name, options);
await style.evaluate((tag) => tag.remove());
return { pass: true, message: () => "", name: "toMatchScreenshot" };
diff --git a/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--dark-theme--bubble-layout-linux.png b/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--dark-theme--bubble-layout-linux.png
new file mode 100644
index 0000000000000000000000000000000000000000..1a6148c9c14226ca744c4be6baa08f52a073a3b8
GIT binary patch
literal 5666
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
literal 0
HcmV?d00001
diff --git a/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--dark-theme--irc-layout-linux.png b/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--dark-theme--irc-layout-linux.png
new file mode 100644
index 0000000000000000000000000000000000000000..98ce66178e0c302d5887c0b2d7c0296f0b9415d7
GIT binary patch
literal 7613
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
literal 0
HcmV?d00001
diff --git a/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--high-contrast--group-layout-linux.png b/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--high-contrast--group-layout-linux.png
new file mode 100644
index 0000000000000000000000000000000000000000..655baf15a23faca02b611220fb43ff8f543c0217
GIT binary patch
literal 10701
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
E3vx(9u>b%7
literal 0
HcmV?d00001
diff --git a/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--high-contrast--irc-layout-linux.png b/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--high-contrast--irc-layout-linux.png
new file mode 100644
index 0000000000000000000000000000000000000000..f230fe06da4a38fee9c5c9d5e995c34c7c3083f9
GIT binary patch
literal 7758
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