fix(cv): verify fresh builder workflow
This commit is contained in:
@@ -533,7 +533,8 @@ public static class StartupInitializationExtensions
|
||||
EnsureColumn(conn, "AspNetUsers", "StripeSubscriptionId", "ALTER TABLE AspNetUsers ADD COLUMN StripeSubscriptionId TEXT NULL;");
|
||||
EnsureColumn(conn, "AspNetUsers", "StripeSubscriptionStatus", "ALTER TABLE AspNetUsers ADD COLUMN StripeSubscriptionStatus TEXT NULL;");
|
||||
EnsureColumn(conn, "AspNetUsers", "StripeLastEventCreatedUtc", "ALTER TABLE AspNetUsers ADD COLUMN StripeLastEventCreatedUtc TEXT NULL;");
|
||||
EnsureColumn(conn, "AspNetUsers", "UiLanguage", "ALTER TABLE AspNetUsers ADD COLUMN UiLanguage TEXT NULL;");
|
||||
// UiLanguage is migration-owned (AddUiLanguagePreference). Adding it here before
|
||||
// the per-migration loop makes a fresh database fail when that migration runs.
|
||||
|
||||
static void EnsureUserRuleSettingsTable(DbConnection c)
|
||||
{
|
||||
@@ -1436,7 +1437,8 @@ public static class StartupInitializationExtensions
|
||||
EnsureMySqlColumn(conn, "AspNetUsers", "StripeSubscriptionId", "ALTER TABLE `AspNetUsers` ADD COLUMN `StripeSubscriptionId` varchar(255) NULL;");
|
||||
EnsureMySqlColumn(conn, "AspNetUsers", "StripeSubscriptionStatus", "ALTER TABLE `AspNetUsers` ADD COLUMN `StripeSubscriptionStatus` varchar(64) NULL;");
|
||||
EnsureMySqlColumn(conn, "AspNetUsers", "StripeLastEventCreatedUtc", "ALTER TABLE `AspNetUsers` ADD COLUMN `StripeLastEventCreatedUtc` datetime(6) NULL;");
|
||||
EnsureMySqlColumn(conn, "AspNetUsers", "UiLanguage", "ALTER TABLE `AspNetUsers` ADD COLUMN `UiLanguage` varchar(16) NULL;");
|
||||
// UiLanguage is migration-owned; the final reconciliation pass observes it
|
||||
// after AddUiLanguagePreference instead of racing the migration.
|
||||
|
||||
// RuleSettings is MIGRATION-owned — the initial migration creates it. The reconciler
|
||||
// used to create it too, which made a clean install fail with "Table 'RuleSettings'
|
||||
|
||||
+2
-1
@@ -7,7 +7,6 @@
|
||||
|
||||
## Next
|
||||
|
||||
- [ ] Visually verify the revised builder at 375 px, 768 px, and 1440 px in light/dark mode, including keyboard navigation, multiple expanded sections, add-content focus return, whole-document AI review, responsive editor/preview switching, PDF parity, and long multi-page CVs.
|
||||
- [ ] Resume from authenticated production smoke findings if they identify a regression.
|
||||
|
||||
## Completed
|
||||
@@ -18,6 +17,8 @@
|
||||
- [x] Added per-section Rows, Grid, Compact and Bubble presentation plus one/two-column controls; normalized them in the persisted settings model and rendered them through the shared preview/PDF engine.
|
||||
- [x] Added regression coverage for the revised studio workflow and shared section presentation; full verification passes with 62 frontend suites/253 tests, 709 backend tests, TypeScript and the optimized frontend build.
|
||||
- [x] Diagnosed release 271 as self-hosted-runner instability (test-host crash, then checksum-invalid NuGet cache entries) and added bounded clean-cache restore recovery without weakening signature, build or test gates.
|
||||
- [x] Fixed fresh SQLite/MySQL startup ordering so the migration-owned UI-language column is not pre-created by schema reconciliation, then proved the full fresh-database path in Playwright.
|
||||
- [x] Visually verified the revised builder at 375 px, 768 px, and 1440 px in light/dark mode, including multiple expanded sections, add-content focus return, Customize/AI surfaces, responsive overflow, multi-page preview and searchable PDF export.
|
||||
- [x] Rechecked branch/status, recent CV work, existing tests/build tooling, and current builder architecture.
|
||||
- [x] Traced builder persistence, shared preview/PDF rendering, AI endpoint, extraction pipeline, confidence/diff review, and reference CV assets.
|
||||
- [x] Rendered and inspected the supplied two-page reference PDF and reviewed its HTML typography/theme tokens without modifying the originals.
|
||||
|
||||
@@ -466,6 +466,39 @@ test("the Code template exports a long structured CV as searchable multi-page PD
|
||||
|
||||
await page.goto(`/career/builder/${variant.id}`);
|
||||
await expect(page.getByLabel("CV name")).toHaveValue("Code PDF Verification");
|
||||
await expect(page.getByRole("tab", { name: "Template" })).toHaveAttribute("aria-selected", "true");
|
||||
await page.getByRole("tab", { name: "Content" }).click();
|
||||
await page.getByRole("button", { name: "Expand Experience" }).click();
|
||||
await page.getByRole("button", { name: "Expand Education" }).click();
|
||||
await expect(page.getByRole("button", { name: "Collapse Experience" })).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: "Collapse Education" })).toBeVisible();
|
||||
|
||||
const addContentButton = page.getByRole("button", { name: "Add content" });
|
||||
await addContentButton.focus();
|
||||
await addContentButton.click();
|
||||
const addContentDialog = page.getByRole("dialog", { name: "Add content" });
|
||||
await expect(addContentDialog).toBeVisible();
|
||||
await expect(addContentDialog.getByRole("heading", { name: "Additional Experience" })).toBeVisible();
|
||||
await addContentDialog.getByRole("button", { name: "Cancel" }).click();
|
||||
await expect(addContentDialog).toBeHidden();
|
||||
await expect(addContentButton).toBeFocused();
|
||||
|
||||
await page.getByRole("tab", { name: "Customize" }).click();
|
||||
await expect(page.getByLabel("Page size")).toBeVisible();
|
||||
await expect(page.getByLabel("Skills presentation")).toBeVisible();
|
||||
await page.getByRole("tab", { name: "AI Tools" }).click();
|
||||
await expect(page.getByText("Translate resume", { exact: true })).toBeVisible();
|
||||
await expect(page.getByText("Check spelling and grammar", { exact: true })).toBeVisible();
|
||||
|
||||
for (const scheme of ["light", "dark"] as const) {
|
||||
await page.evaluate((value) => window.localStorage.setItem("jobtracker.themeMode", value), scheme);
|
||||
await page.reload();
|
||||
for (const width of [375, 768, 1440]) {
|
||||
await page.setViewportSize({ width, height: 900 });
|
||||
const overflow = await page.evaluate(() => document.documentElement.scrollWidth - document.documentElement.clientWidth);
|
||||
expect(overflow).toBeLessThanOrEqual(1);
|
||||
}
|
||||
}
|
||||
await expect(page.getByTitle("CV preview page 2")).toHaveCount(1, { timeout: 10_000 });
|
||||
const pagination = await page.getByTitle("CV preview", { exact: true }).evaluate((element) => {
|
||||
const frame = element as HTMLIFrameElement;
|
||||
|
||||
Reference in New Issue
Block a user