Playwright test for pasting files (#33350)
* Add tests for pasting * Add tests for pasting files. * Remove redundant fn * rm comment
This commit is contained in:
@@ -8,6 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
|||||||
|
|
||||||
import { test, expect } from "../../element-web-test";
|
import { test, expect } from "../../element-web-test";
|
||||||
import { SettingLevel } from "../../../src/settings/SettingLevel";
|
import { SettingLevel } from "../../../src/settings/SettingLevel";
|
||||||
|
import { getSampleFilePath } from "../../sample-files";
|
||||||
|
|
||||||
const CtrlOrMeta = process.platform === "darwin" ? "Meta" : "Control";
|
const CtrlOrMeta = process.platform === "darwin" ? "Meta" : "Control";
|
||||||
|
|
||||||
@@ -198,5 +199,16 @@ test.describe("Composer", () => {
|
|||||||
// Take a screenshot of the autocomplete
|
// Take a screenshot of the autocomplete
|
||||||
await expect(autocomplete).toMatchScreenshot("emoji-autocomplete.png");
|
await expect(autocomplete).toMatchScreenshot("emoji-autocomplete.png");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("can paste a file", async ({ page, bot, app }) => {
|
||||||
|
// Set up a private room so we have another user to mention
|
||||||
|
await app.client.createRoom({
|
||||||
|
is_direct: true,
|
||||||
|
invite: [bot.credentials.userId],
|
||||||
|
});
|
||||||
|
await app.viewRoomByName("Bob");
|
||||||
|
await app.composerDragAndPasteFile("room", getSampleFilePath("riot.png"), "image/png");
|
||||||
|
await expect(page.locator(".mx_MImageBody")).toBeVisible();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ Please see LICENSE files in the repository root for full details.
|
|||||||
|
|
||||||
import { test, expect } from "../../element-web-test";
|
import { test, expect } from "../../element-web-test";
|
||||||
import { SettingLevel } from "../../../src/settings/SettingLevel";
|
import { SettingLevel } from "../../../src/settings/SettingLevel";
|
||||||
|
import { getSampleFilePath } from "../../sample-files";
|
||||||
|
|
||||||
const CtrlOrMeta = process.platform === "darwin" ? "Meta" : "Control";
|
const CtrlOrMeta = process.platform === "darwin" ? "Meta" : "Control";
|
||||||
|
|
||||||
@@ -195,6 +196,26 @@ test.describe("Composer", () => {
|
|||||||
await expect(page.locator(".mx_EventTile_body strong").getByText("bold")).toBeVisible();
|
await expect(page.locator(".mx_EventTile_body strong").getByText("bold")).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("can paste a file", async ({ page, bot, app }) => {
|
||||||
|
await app.composerDragAndPasteFile("room", getSampleFilePath("riot.png"), "image/png");
|
||||||
|
await expect(page.locator(".mx_MImageBody")).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("can paste a file in a thread", async ({ page, app }) => {
|
||||||
|
// Send a message
|
||||||
|
const composer = page.locator("div[contenteditable=true]");
|
||||||
|
await composer.pressSequentially("my first message");
|
||||||
|
await page.getByRole("button", { name: "Send message" }).click();
|
||||||
|
|
||||||
|
// Click reply
|
||||||
|
const tile = page.locator(".mx_EventTile_last");
|
||||||
|
await tile.hover();
|
||||||
|
await tile.getByRole("button", { name: "Reply in thread" }).click();
|
||||||
|
|
||||||
|
await app.composerDragAndPasteFile("thread", getSampleFilePath("riot.png"), "image/png");
|
||||||
|
await expect(page.locator(".mx_MImageBody")).toBeVisible();
|
||||||
|
});
|
||||||
|
|
||||||
test.describe("when Control+Enter is required to send", () => {
|
test.describe("when Control+Enter is required to send", () => {
|
||||||
test.beforeEach(async ({ app }) => {
|
test.beforeEach(async ({ app }) => {
|
||||||
await app.settings.setValue("MessageComposerInput.ctrlEnterToSend", null, SettingLevel.ACCOUNT, true);
|
await app.settings.setValue("MessageComposerInput.ctrlEnterToSend", null, SettingLevel.ACCOUNT, true);
|
||||||
|
|||||||
@@ -405,6 +405,28 @@ test.describe("Threads", () => {
|
|||||||
await app.composerDragAndUploadFiles("thread", getSampleFilePath("riot.png"), "image/png");
|
await app.composerDragAndUploadFiles("thread", getSampleFilePath("riot.png"), "image/png");
|
||||||
await expect(page.locator(".mx_ThreadView .mx_EventTile_image")).toHaveCount(1);
|
await expect(page.locator(".mx_ThreadView .mx_EventTile_image")).toHaveCount(1);
|
||||||
});
|
});
|
||||||
|
test("can send files via paste", async ({ page, app, user }) => {
|
||||||
|
// Increase right-panel size, so that files fit
|
||||||
|
await page.evaluate(() => {
|
||||||
|
window.localStorage.setItem("mx_rhs_size", "600");
|
||||||
|
});
|
||||||
|
|
||||||
|
const roomId = await app.client.createRoom({});
|
||||||
|
await page.goto("/#/room/" + roomId);
|
||||||
|
|
||||||
|
// Send message
|
||||||
|
const locator = page.locator(".mx_RoomView_body");
|
||||||
|
await locator.getByRole("textbox", { name: "Send an unencrypted message…" }).fill("Hello Mr. Bot");
|
||||||
|
await locator.getByRole("textbox", { name: "Send an unencrypted message…" }).press("Enter");
|
||||||
|
// Create thread
|
||||||
|
const locator2 = locator.locator(".mx_EventTile[data-scroll-tokens]").filter({ hasText: "Hello Mr. Bot" });
|
||||||
|
await locator2.hover();
|
||||||
|
await locator2.getByRole("button", { name: "Reply in thread" }).click();
|
||||||
|
|
||||||
|
await expect(page.locator(".mx_ThreadView_timelinePanelWrapper")).toHaveCount(1);
|
||||||
|
await app.composerDragAndPasteFile("thread", getSampleFilePath("riot.png"), "image/png");
|
||||||
|
await expect(page.locator(".mx_ThreadView .mx_EventTile_image")).toHaveCount(1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test(
|
test(
|
||||||
|
|||||||
@@ -218,6 +218,40 @@ export class ElementAppPage {
|
|||||||
await this.page.locator(".mx_Dialog").getByRole("button", { name: "Upload" }).click();
|
await this.page.locator(".mx_Dialog").getByRole("button", { name: "Upload" }).click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Paste a "file" into the specified locator and automatically uploads it.
|
||||||
|
* @param location Should the drop target the main room or the thread.
|
||||||
|
* @param path The path to the sample file so it can be read.
|
||||||
|
* @param type The mimetype of the file.
|
||||||
|
*/
|
||||||
|
public async composerDragAndPasteFile(location: "room" | "thread", path: string, type: string): Promise<void> {
|
||||||
|
// Based on https://github.com/microsoft/playwright/issues/10667#issuecomment-2742123424
|
||||||
|
// This read a file, encodes it into base64 and then sends it along to the page to be treated
|
||||||
|
// as a DataTransfer (the mechanism for drag and dropped files).
|
||||||
|
const buffer = await readFile(path);
|
||||||
|
const name = basename(path);
|
||||||
|
const composer = this.getComposerField(location === "thread");
|
||||||
|
|
||||||
|
await composer.evaluate(
|
||||||
|
async (element, [buffer, name, type]) => {
|
||||||
|
const clipboardData = new DataTransfer();
|
||||||
|
const file = new File([Uint8Array.fromBase64(buffer)], name, {
|
||||||
|
type,
|
||||||
|
});
|
||||||
|
clipboardData.items.add(file);
|
||||||
|
element.dispatchEvent(
|
||||||
|
new ClipboardEvent("paste", {
|
||||||
|
clipboardData,
|
||||||
|
bubbles: true,
|
||||||
|
cancelable: true,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
[buffer.toString("base64"), name, type],
|
||||||
|
);
|
||||||
|
await this.page.locator(".mx_Dialog").getByRole("button", { name: "Upload" }).click();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the space panel space button based on a name. The space
|
* Returns the space panel space button based on a name. The space
|
||||||
* must be visible in the space panel
|
* must be visible in the space panel
|
||||||
|
|||||||
Reference in New Issue
Block a user