Skip to content

Commit 15f8256

Browse files
committed
test: add even/odd header variant tests for layout engine and per-rId layout
- Layout engine: verify oddEvenHeadersFooters drives physical-page parity for margin inflation (odd pages get odd-header height, even pages get even-header height), and that the option being unset keeps default behavior - HeaderFooterPerRidLayout: verify even/odd header refs inherited from earlier sections produce per-section layout cache entries
1 parent 9e7b817 commit 15f8256

File tree

2 files changed

+157
-0
lines changed

2 files changed

+157
-0
lines changed

packages/layout-engine/layout-engine/src/index.test.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,92 @@ describe('layoutDocument', () => {
826826
expect(section2Page!.margins.top).toBeGreaterThanOrEqual(72 + tallFirst - 1);
827827
});
828828

829+
it('uses physical page number for even/odd variant selection when oddEvenHeadersFooters is enabled', () => {
830+
const m = { top: 72, bottom: 72, left: 72, right: 72, header: 36, footer: 36 };
831+
832+
// Single section with alternateHeaders. Odd physical pages get 'odd' variant,
833+
// even physical pages get 'even' variant. Each variant has a different header
834+
// height so we can verify the correct one drives margin inflation.
835+
const sb0: FlowBlock = {
836+
kind: 'sectionBreak',
837+
id: 'sb-0',
838+
type: 'continuous',
839+
margins: m,
840+
headerRefs: { default: 'd0', even: 'e0', odd: 'o0' },
841+
attrs: { isFirstSection: true, sectionIndex: 0 },
842+
};
843+
844+
const lineHeight = 20;
845+
const blocks: FlowBlock[] = [sb0, { kind: 'paragraph', id: 'p0', runs: [] }];
846+
const measures: Measure[] = [
847+
{ kind: 'sectionBreak' },
848+
makeMeasure(Array(80).fill(lineHeight)), // enough content for multiple pages
849+
];
850+
851+
const evenHeight = 120;
852+
const oddHeight = 80;
853+
const sectionMetadata: SectionMetadata[] = [
854+
{ sectionIndex: 0, headerRefs: { default: 'd0', even: 'e0', odd: 'o0' } },
855+
];
856+
857+
const layout = layoutDocument(blocks, measures, {
858+
pageSize: { w: 612, h: 792 },
859+
margins: m,
860+
sectionMetadata,
861+
oddEvenHeadersFooters: true,
862+
headerContentHeightsByRId: new Map([
863+
['e0', evenHeight],
864+
['o0', oddHeight],
865+
]),
866+
});
867+
868+
expect(layout.pages.length).toBeGreaterThanOrEqual(2);
869+
870+
// Page 1 (physical 1, odd): odd variant → margin inflated by oddHeight
871+
const page1 = layout.pages[0];
872+
expect(page1.margins.top).toBeGreaterThanOrEqual(36 + oddHeight - 1);
873+
874+
// Page 2 (physical 2, even): even variant → margin inflated by evenHeight
875+
const page2 = layout.pages[1];
876+
expect(page2.margins.top).toBeGreaterThanOrEqual(36 + evenHeight - 1);
877+
// Even margin should be larger than odd margin since evenHeight > oddHeight
878+
expect(page2.margins.top).toBeGreaterThan(page1.margins.top);
879+
});
880+
881+
it('does not use even/odd variants when oddEvenHeadersFooters is not set', () => {
882+
const m = { top: 72, bottom: 72, left: 72, right: 72, header: 36, footer: 36 };
883+
const sb0: FlowBlock = {
884+
kind: 'sectionBreak',
885+
id: 'sb-0',
886+
type: 'continuous',
887+
margins: m,
888+
headerRefs: { default: 'd0', even: 'e0' },
889+
attrs: { isFirstSection: true, sectionIndex: 0 },
890+
};
891+
892+
const lineHeight = 20;
893+
const blocks: FlowBlock[] = [sb0, { kind: 'paragraph', id: 'p0', runs: [] }];
894+
const measures: Measure[] = [{ kind: 'sectionBreak' }, makeMeasure(Array(80).fill(lineHeight))];
895+
896+
const tallEven = 200;
897+
const layout = layoutDocument(blocks, measures, {
898+
pageSize: { w: 612, h: 792 },
899+
margins: m,
900+
sectionMetadata: [{ sectionIndex: 0, headerRefs: { default: 'd0', even: 'e0' } }],
901+
// oddEvenHeadersFooters NOT set
902+
headerContentHeightsByRId: new Map([
903+
['e0', tallEven],
904+
['d0', 10],
905+
]),
906+
});
907+
908+
// Without oddEvenHeadersFooters, all pages use 'default' variant —
909+
// margins should NOT be inflated by the even header height
910+
for (const page of layout.pages) {
911+
expect(page.margins.top).toBeLessThan(36 + tallEven);
912+
}
913+
});
914+
829915
it('applies section break margins to subsequent pages', () => {
830916
const sectionBreakBlock: FlowBlock = {
831917
kind: 'sectionBreak',

packages/super-editor/src/editors/v1/core/header-footer/HeaderFooterPerRidLayout.test.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,4 +154,75 @@ describe('layoutPerRIdHeaderFooters', () => {
154154
expect(deps.headerLayoutsByRId.has('rId-header-first-shared::s0')).toBe(true);
155155
expect(deps.headerLayoutsByRId.has('rId-header-first-shared::s1')).toBe(true);
156156
});
157+
158+
it('lays out even/odd header refs inherited from earlier sections', async () => {
159+
const deps = {
160+
headerLayoutsByRId: new Map(),
161+
footerLayoutsByRId: new Map(),
162+
};
163+
164+
const layout: Layout = {
165+
pageSize: { w: 612, h: 792 },
166+
pages: [
167+
{ number: 1, fragments: [], sectionIndex: 0 },
168+
{ number: 2, fragments: [], sectionIndex: 0 },
169+
{ number: 3, fragments: [], sectionIndex: 1 },
170+
],
171+
};
172+
173+
const sectionMetadata: SectionMetadata[] = [
174+
{
175+
sectionIndex: 0,
176+
pageSize: { w: 612, h: 792 },
177+
margins: { top: 72, right: 72, bottom: 72, left: 72, header: 36 },
178+
headerRefs: {
179+
default: 'rId-default',
180+
even: 'rId-even',
181+
odd: 'rId-odd',
182+
},
183+
},
184+
{
185+
sectionIndex: 1,
186+
pageSize: { w: 612, h: 792 },
187+
margins: { top: 72, right: 72, bottom: 72, left: 72, header: 36 },
188+
headerRefs: {
189+
default: 'rId-default-s1',
190+
// even and odd NOT defined — should be inherited from section 0
191+
},
192+
},
193+
];
194+
195+
await layoutPerRIdHeaderFooters(
196+
{
197+
headerBlocksByRId: new Map([
198+
['rId-default', [makeParagraph('h-default', 'Default')]],
199+
['rId-even', [makeParagraph('h-even', 'Even header')]],
200+
['rId-odd', [makeParagraph('h-odd', 'Odd header')]],
201+
['rId-default-s1', [makeParagraph('h-default-s1', 'Section 1 default')]],
202+
]),
203+
footerBlocksByRId: new Map(),
204+
constraints: {
205+
width: 468,
206+
height: 648,
207+
pageWidth: 612,
208+
pageHeight: 792,
209+
margins: { left: 72, right: 72, top: 72, bottom: 72, header: 36 },
210+
overflowBaseHeight: 36,
211+
},
212+
},
213+
layout,
214+
sectionMetadata,
215+
deps,
216+
);
217+
218+
// Section 0 should have default, even, and odd layouts
219+
expect(deps.headerLayoutsByRId.has('rId-default::s0')).toBe(true);
220+
expect(deps.headerLayoutsByRId.has('rId-even::s0')).toBe(true);
221+
expect(deps.headerLayoutsByRId.has('rId-odd::s0')).toBe(true);
222+
223+
// Section 1 should have its own default, plus inherited even and odd from section 0
224+
expect(deps.headerLayoutsByRId.has('rId-default-s1::s1')).toBe(true);
225+
expect(deps.headerLayoutsByRId.has('rId-even::s1')).toBe(true);
226+
expect(deps.headerLayoutsByRId.has('rId-odd::s1')).toBe(true);
227+
});
157228
});

0 commit comments

Comments
 (0)