131 lines
4.1 KiB
TypeScript
131 lines
4.1 KiB
TypeScript
/**
|
|
* Autosave E2E Tests
|
|
*
|
|
* Tests that autosave updates the existing draft revision in place
|
|
* rather than creating a new revision on each keystroke.
|
|
*
|
|
* Covers issue #5: skipRevision was stripped by Zod validation,
|
|
* causing every autosave to create a new revision.
|
|
*/
|
|
|
|
import { test, expect } from "../fixtures";
|
|
|
|
test.describe("Autosave", () => {
|
|
let collectionSlug: string;
|
|
let postId: string;
|
|
let headers: Record<string, string>;
|
|
let baseUrl: string;
|
|
|
|
test.beforeEach(async ({ admin, serverInfo }) => {
|
|
await admin.devBypassAuth();
|
|
|
|
baseUrl = serverInfo.baseUrl;
|
|
headers = {
|
|
"Content-Type": "application/json",
|
|
Authorization: `Bearer ${serverInfo.token}`,
|
|
"X-EmDash-Request": "1",
|
|
Origin: baseUrl,
|
|
};
|
|
|
|
// Create a collection with revision support
|
|
collectionSlug = `autosave_${Date.now()}`;
|
|
await fetch(`${baseUrl}/_emdash/api/schema/collections`, {
|
|
method: "POST",
|
|
headers,
|
|
body: JSON.stringify({
|
|
slug: collectionSlug,
|
|
label: "Autosave Test",
|
|
labelSingular: "Autosave Test",
|
|
supports: ["revisions", "drafts"],
|
|
}),
|
|
});
|
|
|
|
await fetch(`${baseUrl}/_emdash/api/schema/collections/${collectionSlug}/fields`, {
|
|
method: "POST",
|
|
headers,
|
|
body: JSON.stringify({ slug: "title", type: "string", label: "Title", required: true }),
|
|
});
|
|
|
|
// Create and publish a post
|
|
const createRes = await fetch(`${baseUrl}/_emdash/api/content/${collectionSlug}`, {
|
|
method: "POST",
|
|
headers,
|
|
body: JSON.stringify({ data: { title: "Original" }, slug: "autosave-test" }),
|
|
});
|
|
const createData: any = await createRes.json();
|
|
postId = createData.data?.item?.id ?? createData.data?.id;
|
|
|
|
await fetch(`${baseUrl}/_emdash/api/content/${collectionSlug}/${postId}/publish`, {
|
|
method: "POST",
|
|
headers,
|
|
body: JSON.stringify({}),
|
|
});
|
|
});
|
|
|
|
test.afterEach(async () => {
|
|
await fetch(`${baseUrl}/_emdash/api/content/${collectionSlug}/${postId}`, {
|
|
method: "DELETE",
|
|
headers,
|
|
}).catch(() => {});
|
|
await fetch(`${baseUrl}/_emdash/api/schema/collections/${collectionSlug}`, {
|
|
method: "DELETE",
|
|
headers,
|
|
}).catch(() => {});
|
|
});
|
|
|
|
test("multiple autosaves update draft in place instead of creating new revisions", async ({
|
|
admin,
|
|
}) => {
|
|
const contentUrl = `/_emdash/api/content/${collectionSlug}/${postId}`;
|
|
const isPut = (res: any) => res.url().includes(contentUrl) && res.request().method() === "PUT";
|
|
const isGet = (res: any) =>
|
|
res.url().includes(contentUrl) &&
|
|
!res.url().includes("/revisions") &&
|
|
res.request().method() === "GET";
|
|
|
|
await admin.goToEditContent(collectionSlug, postId);
|
|
await admin.waitForLoading();
|
|
|
|
const titleInput = admin.page.locator("#field-title");
|
|
await expect(titleInput).toHaveValue("Original");
|
|
|
|
// First edit — listen for both the PUT and the subsequent cache re-fetch GET
|
|
const firstPut = admin.page.waitForResponse(isPut, { timeout: 10000 });
|
|
await titleInput.fill("Edit One");
|
|
await firstPut;
|
|
|
|
// Wait for the cache invalidation GET to settle so form doesn't get overwritten
|
|
const refetchGet = admin.page.waitForResponse(isGet, { timeout: 5000 }).catch(() => {});
|
|
await refetchGet;
|
|
// Extra settle time for React state updates
|
|
await admin.page.waitForTimeout(500);
|
|
|
|
// Check revision count after first autosave
|
|
const res1 = await fetch(
|
|
`${baseUrl}/_emdash/api/content/${collectionSlug}/${postId}/revisions`,
|
|
{ headers },
|
|
);
|
|
const data1: any = await res1.json();
|
|
const countAfterFirst = data1.data.total;
|
|
|
|
// Second edit — set up listener BEFORE typing
|
|
const secondPut = admin.page.waitForResponse(isPut, { timeout: 10000 });
|
|
await titleInput.fill("Edit Two");
|
|
await secondPut;
|
|
|
|
// Check revision count — should be same (updated in place, not new revision)
|
|
const res2 = await fetch(
|
|
`${baseUrl}/_emdash/api/content/${collectionSlug}/${postId}/revisions`,
|
|
{ headers },
|
|
);
|
|
const data2: any = await res2.json();
|
|
const countAfterSecond = data2.data.total;
|
|
|
|
expect(countAfterSecond).toBe(countAfterFirst);
|
|
|
|
// Verify the latest revision contains the last autosaved data
|
|
const latestRevision = data2.data.items?.[0];
|
|
expect(latestRevision?.data?.title).toBe("Edit Two");
|
|
});
|
|
});
|