Rebuild the Classic template on the engine with A4/Letter and a template harness
Classic now renders through buildRenderModel, computeFrame, the template and renderCore, with S.No and HSN/SAC columns, GST slots only through checked Slot components, taxable value, reverse-charge line, cancelled tag, continuation band and Page n of N. Letter absorbs its height deficit in elastic gaps. A harness runs 15 fixtures on A4 and Letter plus an item sweep and asserts zero audit errors, repeated headers, no split blocks, rupee extraction and deterministic output. The legacy InvoiceDocument is removed.
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { computeLogoPlacement } from "./logo";
|
||||
|
||||
const BOX = { w: 170, h: 54 };
|
||||
const base = { box: BOX, availableWidth: 299, minTextWidth: 160 };
|
||||
|
||||
describe("computeLogoPlacement", () => {
|
||||
it("the Test Vendor trimmed 4.6:1 logo is width-limited and stacks above the text", () => {
|
||||
const p = computeLogoPlacement({ ...base, aspect: 4.6 });
|
||||
expect(p.w).toBeCloseTo(170, 6);
|
||||
expect(p.h).toBeCloseTo(170 / 4.6, 6);
|
||||
expect(p.stacked).toBe(true);
|
||||
});
|
||||
|
||||
it("an untrimmed 3:1 logo is height-limited (54 pt) and still stacks", () => {
|
||||
const p = computeLogoPlacement({ ...base, aspect: 3 });
|
||||
expect(p.h).toBe(54);
|
||||
expect(p.w).toBeCloseTo(162, 6);
|
||||
expect(p.stacked).toBe(true);
|
||||
});
|
||||
|
||||
it("a square logo is 54 x 54 and sits beside the text", () => {
|
||||
const p = computeLogoPlacement({ ...base, aspect: 1 });
|
||||
expect(p).toEqual({ w: 54, h: 54, stacked: false });
|
||||
});
|
||||
|
||||
it("stacks exactly when the text beside the logo would drop under the minimum", () => {
|
||||
// 299 - 54 - 14 = 231 beside a square; a 2:1 logo (108 wide) leaves 177; a 2.5:1 one (135) leaves 150.
|
||||
expect(computeLogoPlacement({ ...base, aspect: 2 }).stacked).toBe(false);
|
||||
expect(computeLogoPlacement({ ...base, aspect: 2.5 }).stacked).toBe(true);
|
||||
// The boundary: leaves exactly 160.
|
||||
const w = 299 - 14 - 160;
|
||||
expect(computeLogoPlacement({ ...base, aspect: w / 54 }).stacked).toBe(false);
|
||||
expect(computeLogoPlacement({ ...base, aspect: (w + 0.01) / 54 }).stacked).toBe(true);
|
||||
});
|
||||
|
||||
it("gives the logo more room on a wider column (Letter)", () => {
|
||||
const a4 = computeLogoPlacement({ ...base, aspect: 2.4, availableWidth: 299.28 });
|
||||
const letter = computeLogoPlacement({ ...base, aspect: 2.4, availableWidth: 316 });
|
||||
expect(a4.stacked).toBe(true);
|
||||
expect(letter.stacked).toBe(false);
|
||||
});
|
||||
|
||||
it("never exceeds the box, whatever the aspect", () => {
|
||||
for (const aspect of [0.2, 0.5, 1, 1.5, 3, 4.6, 10, 40]) {
|
||||
const p = computeLogoPlacement({ ...base, aspect });
|
||||
expect(p.w).toBeLessThanOrEqual(170 + 1e-9);
|
||||
expect(p.h).toBeLessThanOrEqual(54 + 1e-9);
|
||||
expect(p.w / p.h).toBeCloseTo(aspect, 6);
|
||||
}
|
||||
});
|
||||
|
||||
it("falls back to the box aspect for a bad aspect", () => {
|
||||
const p = computeLogoPlacement({ ...base, aspect: Number.NaN });
|
||||
expect(p.w).toBeCloseTo(170, 6);
|
||||
expect(p.h).toBeCloseTo(54, 6);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user