-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Expand file tree
/
Copy pathfile-panel.spec.ts
More file actions
213 lines (170 loc) · 10.3 KB
/
Copy pathfile-panel.spec.ts
File metadata and controls
213 lines (170 loc) · 10.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/*
Copyright 2024 New Vector Ltd.
Copyright 2023 Suguru Hirahara
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { test, expect } from "../../element-web-test";
import { viewRoomSummaryByName } from "./utils";
import { isDendrite } from "../../plugins/homeserver/dendrite";
import { getSampleFilePath } from "../../sample-files";
import type { ElementAppPage } from "../../pages/ElementAppPage";
const ROOM_NAME = "Test room";
const NAME = "Alice";
async function uploadFile(app: ElementAppPage, sampleFile: string) {
// Upload a file from the message composer
await app.composerUploadFiles("room", getSampleFilePath(sampleFile));
// Wait until the file is sent
await expect(app.page.locator(".mx_RoomView_statusArea_expanded")).not.toBeVisible();
await expect(app.page.locator(".mx_RoomView_body .mx_EventTile").last().getByRole("status")).toHaveAccessibleName(
"Your message was sent",
);
}
test.describe("FilePanel", () => {
test.use({
displayName: NAME,
});
test.beforeEach(async ({ page, user, app }) => {
await app.client.createRoom({ name: ROOM_NAME });
// Open the file panel
await viewRoomSummaryByName(page, app, ROOM_NAME);
await page.getByRole("menuitem", { name: "Files" }).click();
await expect(page.locator(".mx_FilePanel")).toBeVisible();
});
test.describe("render", { tag: ["@no-firefox", "@no-webkit"] }, () => {
test("should render empty state", { tag: "@screenshot" }, async ({ page }) => {
// Wait until the information about the empty state is rendered
await expect(page.locator(".mx_EmptyState")).toBeVisible();
// Take a snapshot of RightPanel - fix https://github.com/vector-im/element-web/issues/25332
await expect(page.locator(".mx_RightPanel")).toMatchScreenshot("empty.png");
});
test("should list tiles on the panel", { tag: "@screenshot" }, async ({ page, app }) => {
// Upload multiple files
await uploadFile(app, "riot.png"); // Image
await uploadFile(app, "1sec.ogg"); // Audio
await uploadFile(app, "matrix-org-client-versions.json"); // JSON
const roomViewBody = page.locator(".mx_RoomView_body");
// Assert that all of the file were uploaded and rendered
await expect(roomViewBody.locator(".mx_EventTile")).toHaveCount(3);
// Assert that the image exists and has the alt string
await expect(
roomViewBody.locator(".mx_EventTile").filter({ has: page.locator("img[alt='riot.png']") }),
).toBeVisible();
// Assert that the audio player is rendered
await expect(roomViewBody.getByRole("region", { name: "Audio player" })).toBeVisible();
// Assert that the file is rendered as a preview tile with its name and a download button
const fileTile = roomViewBody.locator(".mx_EventTile").last();
await expect(fileTile.getByText(/matrix.*?\.json/)).toBeVisible();
await expect(fileTile.getByRole("button", { name: "Download" })).toBeVisible();
const filePanel = page.locator(".mx_FilePanel");
// Assert that the file panel is opened inside mx_RightPanel and visible
await expect(filePanel).toBeVisible();
const filePanelMessageList = filePanel.locator(".mx_RoomView_MessageList");
// The panel renders EventTileView file tiles without legacy layout attributes.
await expect(filePanelMessageList.locator(".mx_EventTile").first()).not.toHaveAttribute("data-layout");
// Assert that all of the file tiles are rendered
await expect(filePanelMessageList.locator(".mx_EventTile")).toHaveCount(3);
// Assert that the download links are rendered for the image and the audio file, which embed
// the classic file body as their download-only fallback
await expect(filePanelMessageList.locator(".mx_MFileBody")).toHaveCount(2);
// Assert that the sender of the files is rendered on all of the tiles
await expect(filePanelMessageList.getByText(NAME)).toHaveCount(3);
// Detect the image file
const image = filePanelMessageList
.locator(".mx_EventTile")
.filter({ has: page.locator("img[alt='riot.png']") })
.getByTestId("event-tile-slot-body");
// Assert that the image is specified as thumbnail and has the alt string
await expect(image.locator("img.mx_ImageBody_image")).toBeVisible();
await expect(image.locator("img[alt='riot.png']")).toBeVisible();
// Detect the audio file
const audio = filePanelMessageList.getByRole("region", { name: "Audio player" });
// Assert that the play button is rendered
await expect(audio.getByRole("button", { name: "Play" })).toBeVisible();
// Detect the JSON file
// Assert that the file is rendered as a preview tile with its name and a download button
const file = filePanelMessageList.locator(".mx_EventTile").last();
await expect(file.getByText(/matrix.*?\.json/)).toBeVisible();
await expect(file.getByRole("button", { name: "Download" })).toBeVisible();
// Make the viewport tall enough to display all of the file tiles on FilePanel
await page.setViewportSize({ width: 800, height: 1000 });
// In case the panel is scrollable on the resized viewport
// Assert that the value for flexbox is applied
await expect(filePanel.locator(".mx_ScrollPanel .mx_RoomView_MessageList")).toHaveCSS(
"justify-content",
"flex-end",
);
// Assert that all of the file tiles are visible before taking a snapshot
await expect(filePanelMessageList.locator(".mx_ImageBody")).toBeVisible(); // top
await expect(filePanelMessageList.locator(".mx_MAudioBody")).toBeVisible(); // middle
const timestampedTile = filePanelMessageList
.locator(".mx_EventTile")
.filter({ has: page.getByTestId("event-tile-slot-timestamp") })
.last();
const senderDetails = timestampedTile.getByTestId("event-tile-slot-sender");
await expect(senderDetails.locator(".mx_DisambiguatedProfile")).toBeVisible();
await expect(
timestampedTile.getByTestId("event-tile-slot-timestamp").locator(".mx_MessageTimestamp"),
).toBeVisible();
// Take a snapshot of file tiles list on FilePanel
await expect(filePanelMessageList).toMatchScreenshot("file-tiles-list.png", {
// Exclude timestamps & flaky seek bar from snapshot
mask: [page.getByTestId("audio-player-seek")],
css: `
.mx_MessageTimestamp {
visibility: hidden;
}
`,
});
});
test("should render the audio player and play the audio file on the panel", async ({ page, app }) => {
// Upload an image file
await uploadFile(app, "1sec.ogg");
const audioBody = page.getByTestId("right-panel").getByRole("region", { name: "Audio player" });
// Assert that the audio player is rendered
// Assert that the audio file information is rendered;
await expect(audioBody.getByText("1sec.ogg")).toBeVisible(); // extension
await expect(audioBody.getByRole("time")).toHaveText("00:01"); // duration
await expect(audioBody.getByText("(3.56 KB)")).toBeVisible(); // actual size;
// Assert that the duration counter is 00:01 before clicking the play button
await expect(audioBody.getByRole("time")).toHaveText("00:01");
// Assert that the counter is zero before clicking the play button
await expect(audioBody.getByRole("timer")).toHaveText("00:00");
// Click the play button
await audioBody.getByRole("button", { name: "Play" }).click();
// Assert that the pause button is rendered
await expect(audioBody.getByRole("button", { name: "Pause" })).toBeVisible();
// Assert that the timer is reset when the audio file finished playing
await expect(audioBody.getByRole("timer")).toHaveText("00:00");
// Assert that the play button is rendered
await expect(audioBody.getByRole("button", { name: "Play" })).toBeVisible();
});
test("should render file size in kibibytes on a file tile", async ({ page, app }) => {
const size = "1.12 KB"; // actual file size in kibibytes (1024 bytes)
// Upload a file
await uploadFile(app, "matrix-org-client-versions.json");
const tile = page.locator(".mx_FilePanel .mx_EventTile");
// Assert that the file size is displayed in kibibytes, not kilobytes (1000 bytes)
// See: https://github.com/vector-im/element-web/issues/24866
// The panel renders files as a preview tile, which shows the size as the tile body.
await expect(tile.getByText(size)).toBeVisible();
});
});
test.describe("download", () => {
test.skip(isDendrite, "due to a Dendrite sending Content-Disposition inline");
test("should download an image via the link on the panel", async ({ page, app, context }) => {
// Upload an image file
await uploadFile(app, "riot.png");
// Detect the image file on the panel
const imageTile = page
.locator(".mx_FilePanel .mx_RoomView_MessageList .mx_EventTile")
.filter({ has: page.locator("img[alt='riot.png']") });
const link = imageTile.getByTestId("event-tile-slot-body").getByRole("link", { name: /^Download/ });
const downloadPromise = page.waitForEvent("download");
// Click the anchor link (not the image itself)
await link.click();
const download = await downloadPromise;
expect(download.suggestedFilename()).toBe("riot.png");
});
});
});