v5.2.0: undo/redo, version history, embedded AI assistant, mobile builder & more (#3205)

This commit is contained in:
Amruth Pillai
2026-07-04 14:57:25 +02:00
committed by GitHub
parent 09bc6ec521
commit 57e9c8c487
181 changed files with 46794 additions and 11348 deletions
+6 -5
View File
@@ -15,17 +15,18 @@ export async function createSampleResumeFromDashboard(page: Page, testInfo: Test
await createGroup.getByRole("button").last().click();
await page.getByRole("menuitem", { name: "Create a Sample Resume" }).click();
const resumeLink = page.getByRole("link", { name: new RegExp(resumeName) });
await expect(resumeLink).toBeVisible();
await resumeLink.click();
// Creating a resume now navigates straight into the builder.
await page.waitForURL(/\/builder\/.+/);
return resumeName;
}
export async function openSidebarSection(page: Page, title: string) {
await page.getByTitle(title, { exact: true }).click();
await expect(page.getByRole("heading", { name: title, exact: true })).toBeVisible();
// Rail nav buttons are labelled with the section title (aria-label); clicking scrolls to the section.
await page.getByRole("button", { name: title, exact: true }).first().click();
// The visible section heading is exactly the title. Filter to visible because the screen-reader-only
// resume mirror in the preview also renders <h2> section headings with the same name.
await expect(page.getByRole("heading", { name: title, exact: true }).filter({ visible: true }).first()).toBeVisible();
}
export async function openResumeCardMenu(page: Page, resumeName: string) {
+1 -1
View File
@@ -7,7 +7,7 @@ test("renames, duplicates and deletes a resume from the dashboard", async ({ aut
// Rename via the card context menu (resume names are capped at 64 chars, keep it short)
const renamedTo = `E2E Renamed ${Date.now().toString(36)}`;
await openResumeCardMenu(page, resumeName);
await page.getByRole("menuitem", { name: "Update" }).click();
await page.getByRole("menuitem", { name: "Edit details" }).click();
const updateDialog = page.getByRole("dialog", { name: "Update Resume" });
await updateDialog.getByLabel("Name").fill(renamedTo);
await updateDialog.getByRole("button", { name: "Save Changes" }).click();
+2 -3
View File
@@ -17,10 +17,9 @@ test("exports and imports a resume JSON backup", async ({ authPage: page }, test
const exportedData = JSON.parse(await readFile(downloadPath, "utf-8")) as { basics: { name: string } };
await page.goto("/dashboard/resumes");
await page.getByText("Import an existing resume").click();
await page.getByRole("button", { name: "Import", exact: true }).click();
const dialog = page.getByRole("dialog", { name: "Import an existing resume" });
await dialog.getByRole("combobox").click();
await page.getByRole("option", { name: "Reactive Resume (JSON)" }).click();
// Import is now file-first: selecting the file auto-detects the Reactive Resume JSON format.
await dialog.locator('input[type="file"]').setInputFiles(downloadPath);
await dialog.getByRole("button", { name: "Import", exact: true }).click();
+1 -1
View File
@@ -17,7 +17,7 @@ test("locks a resume, blocking updates and deletion until unlocked", async ({ au
// Locked: the menu now offers Unlock, and destructive/edit actions are disabled
await openResumeCardMenu(page, resumeName);
await expect(page.getByRole("menuitem", { name: "Unlock" })).toBeVisible();
await expect(page.getByRole("menuitem", { name: "Update" })).toBeDisabled();
await expect(page.getByRole("menuitem", { name: "Edit details" })).toBeDisabled();
await expect(page.getByRole("menuitem", { name: "Delete" })).toBeDisabled();
// Unlock restores the actions — wait for the mutation to land before re-reading the menu
+1 -1
View File
@@ -14,7 +14,7 @@ test("publishes a resume and renders it for an anonymous visitor", async ({ brow
const anonymous = await browser.newPage();
try {
await anonymous.goto(publicUrl);
await expect(anonymous.getByRole("button", { name: "Download PDF" })).toBeVisible();
await expect(anonymous.getByRole("button", { name: "Download PDF" }).first()).toBeVisible();
} finally {
await anonymous.close();
}
+3 -3
View File
@@ -24,11 +24,11 @@ test("adds an experience item and persists it across reloads", async ({ authPage
await savePromise;
// The new item shows up in the section list with the company as its title
await expect(page.getByText(company)).toBeVisible();
await expect(page.getByText(company).filter({ visible: true }).first()).toBeVisible();
// And it survives a full reload
await page.reload();
await openSidebarSection(page, "Experience");
await expect(page.getByText(company)).toBeVisible();
await expect(page.getByText(position)).toBeVisible();
await expect(page.getByText(company).filter({ visible: true }).first()).toBeVisible();
await expect(page.getByText(position).filter({ visible: true }).first()).toBeVisible();
});
+1 -1
View File
@@ -27,7 +27,7 @@ test("password-protects a public resume and unlocks it as a visitor", async ({ b
await anonymous.getByRole("button", { name: "Unlock" }).click();
// The correct password reveals the actual resume
await expect(anonymous.getByRole("button", { name: "Download PDF" })).toBeVisible();
await expect(anonymous.getByRole("button", { name: "Download PDF" }).first()).toBeVisible();
} finally {
await anonymous.close();
}