Files
site-builder/craft/src/hooks/useWhpApi.save.test.ts
T
shadowdaoandClaude Opus 4.8 cf56f2a388 refactor(builder): remove dead per-page headCode field (D9)
PageData.headCode was never populated from anything but '' and never
read anywhere -- the real, live concept is SiteDesign.headCode (set
via the Code modal, wired into Preview/export in D8). Remove the dead
field from the PageData interface and its ~7 hardcoded headCode: ''
seeds/discards in PageContext.tsx (DEFAULT_PAGE, DEFAULT_HEADER,
DEFAULT_FOOTER, the context default value, addPage, setPagesCraftState,
replaceAllPages). Update the PageData literals in
useWhpApi.save.test.ts to match the trimmed interface.

Verified via grep that nothing reads page.headCode, and `npm run
build` (strict tsc) is clean -- no live reader broke.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-12 13:30:17 -07:00

91 lines
3.7 KiB
TypeScript

import { describe, test, expect } from 'vitest';
import { buildSavePayload } from './useWhpApi';
import { PageData } from '../types';
const pageA: PageData = { id: 'home', name: 'Home', slug: 'index', craftState: 'STORED_HOME' };
const pageB: PageData = { id: 'page_2', name: 'About', slug: 'about', craftState: 'STORED_ABOUT' };
const headerPage: PageData = { id: '__header__', name: 'Header', slug: '__header__', craftState: 'STALE_HEADER' };
const footerPage: PageData = { id: '__footer__', name: 'Footer', slug: '__footer__', craftState: 'STALE_FOOTER' };
describe('buildSavePayload', () => {
test('editing header: live serialize lands in header_craft_state, not in any page slot', () => {
const payload = buildSavePayload({
siteId: 1,
siteName: 'Test Site',
liveCraftState: 'LIVE_HEADER',
pages: [pageA, pageB],
headerPage,
footerPage,
activePageId: '__header__',
isEditingHeader: true,
isEditingFooter: false,
});
// The fresh live canvas must be reflected in header_craft_state, not the stale stored one.
expect(payload.header_craft_state).toBe('LIVE_HEADER');
expect(payload.header_craft_state).not.toBe('STALE_HEADER');
// Footer must remain untouched (stored state, since we're not editing it).
expect(payload.footer_craft_state).toBe('STALE_FOOTER');
// Live header content must never leak into a page slot or the top-level page fields.
expect(payload.craft_state).not.toBe('LIVE_HEADER');
for (const p of payload.pages_craft_state) {
expect(p.craftState).not.toBe('LIVE_HEADER');
}
// Top-level page fields should fall back to the landing page's own stored state.
expect(payload.craft_state).toBe('STORED_HOME');
// Per-page slots must reflect each page's own stored state, untouched.
expect(payload.pages_craft_state.find((p) => p.id === 'home')?.craftState).toBe('STORED_HOME');
expect(payload.pages_craft_state.find((p) => p.id === 'page_2')?.craftState).toBe('STORED_ABOUT');
});
test('editing footer: live serialize lands in footer_craft_state, not in any page slot', () => {
const payload = buildSavePayload({
siteId: 1,
siteName: 'Test Site',
liveCraftState: 'LIVE_FOOTER',
pages: [pageA, pageB],
headerPage,
footerPage,
activePageId: '__footer__',
isEditingHeader: false,
isEditingFooter: true,
});
expect(payload.footer_craft_state).toBe('LIVE_FOOTER');
expect(payload.footer_craft_state).not.toBe('STALE_FOOTER');
expect(payload.header_craft_state).toBe('STALE_HEADER');
expect(payload.craft_state).not.toBe('LIVE_FOOTER');
for (const p of payload.pages_craft_state) {
expect(p.craftState).not.toBe('LIVE_FOOTER');
}
});
test('editing a real page: behavior unchanged — live serialize goes to that page + top-level, header/footer come from stored state', () => {
const payload = buildSavePayload({
siteId: 1,
siteName: 'Test Site',
liveCraftState: 'LIVE_PAGE_HOME',
pages: [pageA, pageB],
headerPage,
footerPage,
activePageId: 'home',
isEditingHeader: false,
isEditingFooter: false,
});
// Live canvas goes to the active page and top-level slots.
expect(payload.craft_state).toBe('LIVE_PAGE_HOME');
expect(payload.pages_craft_state.find((p) => p.id === 'home')?.craftState).toBe('LIVE_PAGE_HOME');
// Other pages keep their stored state.
expect(payload.pages_craft_state.find((p) => p.id === 'page_2')?.craftState).toBe('STORED_ABOUT');
// Header/footer come from stored (stale-but-correct, since we're not editing them) state.
expect(payload.header_craft_state).toBe('STALE_HEADER');
expect(payload.footer_craft_state).toBe('STALE_FOOTER');
});
});