Allow local log downloads when a rageshake URL is not configured. (#31716)
* Add support for storing debug logs locally and allowing local downloads. * static * Comprehensive testing for bug report flow. * Driveby cleanup of typography * fix i18n * Improvements to UX * More testing * update snaps * linting * lint * Fix feedback * Fix boldnewss * fix bold * fix heading * Increase test coverage * remove focus * Don't show the FAQ depending on whether you can submit feedback. * move reset * fix err * Remove unused * update snap * Remove text * Bumping up that coverage * tidy * lint * update snap * Use a const * fix imports * Remove import in e2e test * whoops
This commit is contained in:
139
playwright/e2e/feedback/rageshakes.spec.ts
Normal file
139
playwright/e2e/feedback/rageshakes.spec.ts
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
Copyright 2026 Element Creations Ltd.
|
||||
|
||||
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";
|
||||
|
||||
function formDataParser(data: string, contentType: string | null): Record<string, string> {
|
||||
const [, boundary] =
|
||||
contentType
|
||||
?.split(";")
|
||||
.map((v) => v.trim())
|
||||
.find((v) => v.startsWith("boundary="))
|
||||
?.split("=") ?? [];
|
||||
if (!boundary) {
|
||||
throw Error("No boundary found in form data request");
|
||||
}
|
||||
const dataMap: Record<string, string> = {};
|
||||
for (const dataPart of data.split(boundary).map((p) => p.trim())) {
|
||||
const lines = dataPart.split("\r\n");
|
||||
const fieldName = lines[0].match(/name="([^"]+)"/)?.[1];
|
||||
if (!fieldName) {
|
||||
continue;
|
||||
}
|
||||
const data = lines.slice(1, -1).join("\n").trim();
|
||||
dataMap[fieldName] = data;
|
||||
}
|
||||
return dataMap;
|
||||
}
|
||||
|
||||
test.describe("Rageshakes", () => {
|
||||
test.describe("visible when enabled", () => {
|
||||
test.use({
|
||||
config: {
|
||||
// Enable this just so the options show up.
|
||||
bug_report_endpoint_url: "https://example.org/bug-report-place",
|
||||
},
|
||||
});
|
||||
test("should be able to open bug report dialog via slash command", async ({ page, app, user }) => {
|
||||
await app.client.createRoom({ name: "Test room" });
|
||||
await app.viewRoomByName("Test room");
|
||||
const composer = app.getComposer().locator("[contenteditable]");
|
||||
await composer.fill("/rageshake");
|
||||
await composer.press("Enter");
|
||||
await expect(page.getByRole("dialog", { name: "Submit debug logs" })).toBeVisible();
|
||||
});
|
||||
|
||||
test("should be able to open bug report dialog via feedback dialog", async ({ page, app, user }) => {
|
||||
const menu = await app.openUserMenu();
|
||||
await menu.getByRole("menuitem", { name: "Feedback" }).click();
|
||||
const feedbackDialog = page.getByRole("dialog", { name: "Feedback" });
|
||||
await feedbackDialog.getByRole("button", { name: "debug logs" }).click();
|
||||
await expect(page.getByRole("dialog", { name: "Submit debug logs" })).toBeVisible();
|
||||
});
|
||||
test("should be able to open bug report dialog via Settings", async ({ page, app, user }) => {
|
||||
const settings = await app.settings.openUserSettings("Help & About");
|
||||
await settings.getByRole("button", { name: "Submit debug logs" }).click();
|
||||
// Playwright can't see the dialog when both the settings and bug report dialogs are open, so key off heading.
|
||||
await expect(page.locator(".mx_BugReportDialog")).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe("hidden when disabled", () => {
|
||||
test("should NOT be able to open bug report dialog via slash command", async ({ page, app, user }) => {
|
||||
await app.client.createRoom({ name: "Test room" });
|
||||
await app.viewRoomByName("Test room");
|
||||
const composer = app.getComposer().locator("[contenteditable]");
|
||||
await composer.fill("/rageshake");
|
||||
await composer.press("Enter");
|
||||
await expect(page.getByRole("dialog", { name: "Unknown command" })).toBeVisible();
|
||||
});
|
||||
|
||||
test("should NOT be able to open bug report dialog via feedback dialog", async ({ page, app, user }) => {
|
||||
const menu = await app.openUserMenu();
|
||||
await expect(menu.getByRole("menuitem", { name: "Feedback" })).not.toBeVisible();
|
||||
});
|
||||
test("should NOT be able to open bug report dialog via Settings", async ({ page, app, user }) => {
|
||||
const settings = await app.settings.openUserSettings("Help & About");
|
||||
await expect(settings.getByRole("menuitem", { name: "Submit debug logs" })).not.toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe("via bug report endpoint", () => {
|
||||
test.use({
|
||||
config: {
|
||||
bug_report_endpoint_url: "http://example.org/bug-report-server",
|
||||
},
|
||||
});
|
||||
|
||||
test("should be able to rageshake to a URL", { tag: "@screenshot" }, async ({ page, app, user }) => {
|
||||
await page.route("http://example.org/bug-report-server", async (route, request) => {
|
||||
if (request.method() !== "POST") {
|
||||
throw Error("Expected POST");
|
||||
}
|
||||
const fields = formDataParser(request.postData(), await request.headerValue("Content-Type"));
|
||||
expect(fields.text).toEqual(
|
||||
"These are some notes\n\nIssue: https://github.com/element-hq/element-web/12345",
|
||||
);
|
||||
expect(fields.app).toEqual("element-web");
|
||||
expect(fields.user_id).toEqual(user.userId);
|
||||
expect(fields.device_id).toEqual(user.deviceId);
|
||||
// We don't check the logs contents, but we'd like for there to be a log.
|
||||
expect(fields["compressed-log"]).toBeDefined();
|
||||
return route.fulfill({ json: {}, status: 200 });
|
||||
});
|
||||
|
||||
const settings = await app.settings.openUserSettings("Help & About");
|
||||
await settings.getByRole("button", { name: "Submit debug logs" }).click();
|
||||
const dialog = page.locator(".mx_BugReportDialog");
|
||||
await dialog
|
||||
.getByRole("textbox", { name: "GitHub issue" })
|
||||
.fill("https://github.com/element-hq/element-web/12345");
|
||||
await dialog.getByRole("textbox", { name: "Notes" }).fill("These are some notes");
|
||||
await expect(dialog).toMatchScreenshot("rageshake_via_url.png");
|
||||
await dialog.getByRole("button", { name: "Send logs" }).click();
|
||||
await expect(page.getByRole("heading", { name: "Logs sent" })).toBeVisible();
|
||||
});
|
||||
});
|
||||
test.describe("via local download", () => {
|
||||
test.use({
|
||||
config: {
|
||||
bug_report_endpoint_url: "local",
|
||||
},
|
||||
});
|
||||
|
||||
test("should be able to rageshake to local download", { tag: "@screenshot" }, async ({ page, app, user }) => {
|
||||
const settings = await app.settings.openUserSettings("Help & About");
|
||||
await settings.getByRole("button", { name: "Download logs" }).click();
|
||||
const dialog = page.locator(".mx_BugReportDialog");
|
||||
await expect(dialog).toMatchScreenshot("rageshake_locally.png");
|
||||
const downloadPromise = page.waitForEvent("download");
|
||||
await dialog.getByRole("button", { name: "Download logs" }).click();
|
||||
const download = await downloadPromise;
|
||||
await download.cancel();
|
||||
});
|
||||
});
|
||||
});
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 40 KiB |
Reference in New Issue
Block a user