Skip to content

Feat/fix blank page bug 3180#3188

Open
jp-doyon-pro wants to merge 2 commits into
amruthpillai:mainfrom
jp-doyon-pro:feat/fix-blank-page-bug-3180
Open

Feat/fix blank page bug 3180#3188
jp-doyon-pro wants to merge 2 commits into
amruthpillai:mainfrom
jp-doyon-pro:feat/fix-blank-page-bug-3180

Conversation

@jp-doyon-pro

@jp-doyon-pro jp-doyon-pro commented Jun 29, 2026

Copy link
Copy Markdown

Fix and e2e test for issue #3180 .
ps: I'm completely new in typescript, so please don't hesitate to tell me my errors.
Thanks.

Summary by CodeRabbit

  • Bug Fixes

    • Removing the last item from a custom section now also removes the empty section and cleans up any empty page layout entries.
    • Resume data moves are validated more thoroughly to help preserve imported/exported content accurately.
  • Tests

    • Added end-to-end coverage for an empty-page resume flow, including moving items across sections/pages and verifying JSON round-trip consistency.

@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

removeItemFromSource is extended to clean up empty custom sections and pages after item removal. A Playwright E2E test suite is introduced with a config, a JSON fixture, and a test that moves a resume item between sections and asserts round-trip JSON fidelity.

Changes

Empty page cleanup fix and E2E round-trip test

Layer / File(s) Summary
removeItemFromSource empty-section/page cleanup
apps/web/src/libs/resume/move-item.ts
After splicing the last item from a custom section, removes the custom section from draft.customSections, removes its ID from the page's main array, and removes the page entry if main becomes empty. JSDoc updated accordingly.
Playwright config and dotenv dependency
package.json, tests/e2e/playwright.config.ts
Adds dotenv ^17.4.2 to devDependencies and introduces the Playwright config with CI-aware parallelization, retries, HTML reporting, three browser projects, and a dev server definition.
E2E fixture and round-trip test
tests/e2e/specs/data/test-empty-page.json, tests/e2e/specs/test-empty-page.spec.ts
Adds the test-empty-page.json fixture (two experience items, full metadata) and a Playwright test that imports the resume, moves "Company 2" to a new page via custom sections and back, downloads the result as JSON, and asserts deep equality with the original input.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly references the blank page bug fix and issue 3180, matching the main change set.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
✨ Simplify code
  • Create PR with simplified code

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/web/src/libs/resume/move-item.ts`:
- Around line 164-173: The cleanup in move-item.ts leaves a stale
customSectionId in page.main when a custom section is removed, so update the
page’s main array before deciding whether to delete the page. In the removal
block inside the moveItem/custom section handling, use the found page from
draft.metadata.layout.pages to remove customSectionId from its main list, then
only splice the page if it becomes empty. This should keep draft.customSections,
draft.metadata.layout.pages, and the section-item render path consistent.

In `@tests/e2e/playwright.config.ts`:
- Around line 28-31: The Playwright webServer is starting the full workspace dev
graph via the npm run dev script instead of just the app under test, which can
pull in unrelated services and slow or block CI. Update the webServer command in
playwright.config.ts to use the dedicated web app script that serves the UI on
http://localhost:3000, keeping the rest of the Playwright configuration
unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: d7dbed5b-e723-4d0b-a06e-03dc973b5176

📥 Commits

Reviewing files that changed from the base of the PR and between d3735eb and d4271f1.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (5)
  • apps/web/src/libs/resume/move-item.ts
  • package.json
  • tests/e2e/playwright.config.ts
  • tests/e2e/specs/data/test-empty-page.json
  • tests/e2e/specs/test-empty-page.spec.ts

Comment on lines +164 to +173
if (customSection.items.length === 0) {
const sectionIndex = draft.customSections.indexOf(customSection);
draft.customSections.splice(sectionIndex, 1);

const customSectionPageIndex = draft.metadata.layout.pages.findIndex((page) =>
page.main.includes(customSectionId),
);
if (draft.metadata.layout.pages[customSectionPageIndex].main.length === 1) {
draft.metadata.layout.pages.splice(customSectionPageIndex, 1);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Remove the section ID from page.main before deciding whether to delete the page.

Line 168 only finds the page, but Lines 171-172 delete the page only when main.length === 1. On any page with other sections, this leaves a dangling customSectionId in draft.metadata.layout.pages[*].main after the custom section has already been removed from draft.customSections. The move/render path in apps/web/src/routes/builder/$resumeId/-sidebar/left/shared/section-item.tsx now sees a layout entry that points at nothing.

Suggested fix
 		if (customSection.items.length === 0) {
 			const sectionIndex = draft.customSections.indexOf(customSection);
 			draft.customSections.splice(sectionIndex, 1);

 			const customSectionPageIndex = draft.metadata.layout.pages.findIndex((page) =>
 				page.main.includes(customSectionId),
 			);
-			if (draft.metadata.layout.pages[customSectionPageIndex].main.length === 1) {
-				draft.metadata.layout.pages.splice(customSectionPageIndex, 1);
+			if (customSectionPageIndex !== -1) {
+				const page = draft.metadata.layout.pages[customSectionPageIndex];
+				page.main = page.main.filter((sectionId) => sectionId !== customSectionId);
+
+				if (page.main.length === 0) {
+					draft.metadata.layout.pages.splice(customSectionPageIndex, 1);
+				}
 			}
 		}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (customSection.items.length === 0) {
const sectionIndex = draft.customSections.indexOf(customSection);
draft.customSections.splice(sectionIndex, 1);
const customSectionPageIndex = draft.metadata.layout.pages.findIndex((page) =>
page.main.includes(customSectionId),
);
if (draft.metadata.layout.pages[customSectionPageIndex].main.length === 1) {
draft.metadata.layout.pages.splice(customSectionPageIndex, 1);
}
if (customSection.items.length === 0) {
const sectionIndex = draft.customSections.indexOf(customSection);
draft.customSections.splice(sectionIndex, 1);
const customSectionPageIndex = draft.metadata.layout.pages.findIndex((page) =>
page.main.includes(customSectionId),
);
if (customSectionPageIndex !== -1) {
const page = draft.metadata.layout.pages[customSectionPageIndex];
page.main = page.main.filter((sectionId) => sectionId !== customSectionId);
if (page.main.length === 0) {
draft.metadata.layout.pages.splice(customSectionPageIndex, 1);
}
}
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/libs/resume/move-item.ts` around lines 164 - 173, The cleanup in
move-item.ts leaves a stale customSectionId in page.main when a custom section
is removed, so update the page’s main array before deciding whether to delete
the page. In the removal block inside the moveItem/custom section handling, use
the found page from draft.metadata.layout.pages to remove customSectionId from
its main list, then only splice the page if it becomes empty. This should keep
draft.customSections, draft.metadata.layout.pages, and the section-item render
path consistent.

Comment on lines +28 to +31
webServer: {
command: "npm run dev",
url: "http://localhost:3000",
reuseExistingServer: !process.env.CI,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Start only the web app here, not the whole workspace dev graph.

Line 29 currently shells out to npm run dev, but package.json maps that to turbo run dev. That is much broader than the single app this config probes on http://localhost:3000 and can make CI wait on unrelated services instead of the builder UI. Point this at the dedicated web script instead.

Suggested fix
 	webServer: {
-		command: "npm run dev",
+		command: "pnpm dev:web",
 		url: "http://localhost:3000",
 		reuseExistingServer: !process.env.CI,
 	},
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
webServer: {
command: "npm run dev",
url: "http://localhost:3000",
reuseExistingServer: !process.env.CI,
webServer: {
command: "pnpm dev:web",
url: "http://localhost:3000",
reuseExistingServer: !process.env.CI,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/e2e/playwright.config.ts` around lines 28 - 31, The Playwright
webServer is starting the full workspace dev graph via the npm run dev script
instead of just the app under test, which can pull in unrelated services and
slow or block CI. Update the webServer command in playwright.config.ts to use
the dedicated web app script that serves the UI on http://localhost:3000,
keeping the rest of the Playwright configuration unchanged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant