110 lines
3.1 KiB
TypeScript
110 lines
3.1 KiB
TypeScript
import { expect, test } from "@playwright/test";
|
|
|
|
const attachmentId = "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb";
|
|
const file = {
|
|
name: "fixture_chair.nitro",
|
|
mimeType: "application/octet-stream",
|
|
buffer: Buffer.from("isolated upload fixture"),
|
|
};
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
await page.goto("/admin/attachment-harness");
|
|
await page
|
|
.getByText("Attach original file and resume", { exact: true })
|
|
.click();
|
|
});
|
|
|
|
test("attachment upload and double-click resume send one retry and refresh history", async ({
|
|
page,
|
|
}) => {
|
|
let retries = 0;
|
|
await page.route("**/api/admin/studio/import-attachment", async (route) => {
|
|
expect(route.request().method()).toBe("POST");
|
|
expect(route.request().postData()).toContain('name="classname"');
|
|
expect(route.request().postData()).toContain("fixture_chair");
|
|
expect(route.request().postData()).toContain(
|
|
'filename="fixture_chair.nitro"',
|
|
);
|
|
await route.fulfill({ json: { ok: true, attachmentId } });
|
|
});
|
|
await page.route("**/api/admin/studio/import-jobs", async (route) => {
|
|
retries++;
|
|
expect(route.request().method()).toBe("PATCH");
|
|
expect(route.request().postDataJSON()).toEqual({
|
|
id: "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
|
|
action: "retry",
|
|
attachments: { fixture_chair: attachmentId },
|
|
});
|
|
await new Promise((resolve) => setTimeout(resolve, 150));
|
|
await route.fulfill({ json: { ok: true } });
|
|
});
|
|
await page.getByLabel("Choose the original .nitro file").setInputFiles(file);
|
|
await expect(
|
|
page.getByText("Matching original file attached", { exact: true }),
|
|
).toBeVisible();
|
|
await page
|
|
.getByRole("button", {
|
|
name: "Resume failed imports with this file",
|
|
exact: true,
|
|
})
|
|
.dblclick();
|
|
await expect(page.getByLabel("Resumed count")).toHaveText("1");
|
|
expect(retries).toBe(1);
|
|
await expect(
|
|
page.getByRole("button", {
|
|
name: "Resume failed imports with this file",
|
|
exact: true,
|
|
}),
|
|
).toHaveCount(0);
|
|
});
|
|
|
|
for (const scenario of [
|
|
{
|
|
name: "owner rejection",
|
|
status: 403,
|
|
code: "forbidden",
|
|
message: "Could not attach the file.",
|
|
},
|
|
{
|
|
name: "mismatched furniture",
|
|
status: 400,
|
|
code: "mismatchedFile",
|
|
message: "This file belongs to different furniture.",
|
|
},
|
|
{
|
|
name: "network failure",
|
|
status: 0,
|
|
code: "",
|
|
message: "Network connection failed",
|
|
},
|
|
])
|
|
test(`attachment ${scenario.name} shows readable error without enabling resume`, async ({
|
|
page,
|
|
}) => {
|
|
let retries = 0;
|
|
await page.route("**/api/admin/studio/import-jobs", async (route) => {
|
|
retries++;
|
|
await route.fulfill({ json: { ok: true } });
|
|
});
|
|
await page.route("**/api/admin/studio/import-attachment", (route) =>
|
|
scenario.status
|
|
? route.fulfill({
|
|
status: scenario.status,
|
|
json: { ok: false, code: scenario.code },
|
|
})
|
|
: route.abort("failed"),
|
|
);
|
|
await page
|
|
.getByLabel("Choose the original .nitro file")
|
|
.setInputFiles(file);
|
|
await expect(page.getByRole("alert")).toContainText(scenario.message);
|
|
await expect(
|
|
page.getByRole("button", {
|
|
name: "Resume failed imports with this file",
|
|
exact: true,
|
|
}),
|
|
).toHaveCount(0);
|
|
await expect(page.getByLabel("Resumed count")).toHaveText("0");
|
|
expect(retries).toBe(0);
|
|
});
|