mirror of
https://github.com/Matysh/houseplan-card
synced 2026-10-04 21:58:56 +00:00
@@ -84,6 +84,22 @@ export function prepareGoldenFixture(scenario) {
|
||||
}
|
||||
space.openings = [...(space.openings || []), ...structuredClone(scenario.extraOpenings)];
|
||||
}
|
||||
if (scenario.openingGeometry) {
|
||||
const space = requireSpace();
|
||||
const opening = (space.openings || []).find(
|
||||
(item) => item.id === scenario.openingGeometry.id,
|
||||
);
|
||||
if (!opening || opening.type !== scenario.openingGeometry.type
|
||||
|| Math.abs(Number(opening.angle) - scenario.openingGeometry.angle) > 0.001) {
|
||||
throw new Error(
|
||||
`golden openingGeometry references a missing/mismatched opening: `
|
||||
+ `${scenario.openingGeometry.id}`,
|
||||
);
|
||||
}
|
||||
// This scenario must not remain byte-identical to the generic geometry
|
||||
// capture: isolate the intended diagonal symbol in the rendered fixture.
|
||||
space.openings = [opening];
|
||||
}
|
||||
if (scenario.wallReplacements?.length) {
|
||||
const space = requireSpace();
|
||||
const samePoint = (a, b) => Array.isArray(a) && Array.isArray(b)
|
||||
|
||||
@@ -19,7 +19,7 @@ export const GOLDEN_SCENARIOS = Object.freeze([
|
||||
// complete 90 cm door preset while still proving rotation, inner-face
|
||||
// offset and ruler placement on a thick wall.
|
||||
mode: 'plan', openingPreview: { type: 'door', pointer: [0.48, 0.65] },
|
||||
openingPreviewPixels: { minPixels: 40, minChannelDelta: 4 },
|
||||
openingPreviewPixels: { minPixels: 150, minChannelDelta: 4 },
|
||||
theme: 'dark', viewport: { width: 1180, height: 900 }, ...page },
|
||||
{ id: 'geometry-devices-editor-dark', fixture: 'visual', space: 'golden-geometry', mode: 'devices',
|
||||
theme: 'dark', viewport: { width: 1180, height: 900 }, ...page },
|
||||
@@ -46,6 +46,7 @@ export const GOLDEN_SCENARIOS = Object.freeze([
|
||||
editorTray: 'decor-tool', language: 'ru', theme: 'dark',
|
||||
viewport: { width: 390, height: 760 }, ...page },
|
||||
{ id: 'geometry-diagonal-45-opening-dark', fixture: 'visual', space: 'golden-geometry', mode: 'view',
|
||||
openingGeometry: { id: 'geo-diagonal-window', type: 'window', angle: 45 },
|
||||
theme: 'dark', viewport: { width: 1000, height: 900 }, ...stage },
|
||||
{ id: 'openings-thick-wall-dark', fixture: 'visual', space: 'golden-lighting', mode: 'view',
|
||||
fillMode: 'none', glowEnabled: false, theme: 'dark', viewport: { width: 1000, height: 900 }, ...stage },
|
||||
|
||||
@@ -385,6 +385,34 @@ try {
|
||||
pageErrors.length = 0;
|
||||
result.runtime = await prepareGoldenScenario(page, scenario);
|
||||
if (pageErrors.length) throw new Error(`browser exception: ${pageErrors.join(' | ')}`);
|
||||
if (scenario.openingGeometry) {
|
||||
result.openingGeometry = await page.evaluate((expected) => {
|
||||
const card = window.__goldenCard;
|
||||
const opening = card?.renderRoot?.querySelector(
|
||||
`.opening[data-id="${CSS.escape(expected.id)}"]`,
|
||||
);
|
||||
if (!opening) return null;
|
||||
const transform = opening.getAttribute('transform') || '';
|
||||
const angle = Number(transform.match(/rotate\(([-+0-9.eE]+)\)/)?.[1]);
|
||||
const bounds = opening.getBoundingClientRect();
|
||||
return {
|
||||
type: opening.getAttribute('data-kind'), angle,
|
||||
width: bounds.width, height: bounds.height,
|
||||
visibleParts: opening.querySelectorAll('.op-leaf, .op-arc, .op-glass').length,
|
||||
};
|
||||
}, scenario.openingGeometry);
|
||||
const expected = scenario.openingGeometry;
|
||||
const actualOpening = result.openingGeometry;
|
||||
if (!actualOpening || actualOpening.type !== expected.type
|
||||
|| Math.abs(actualOpening.angle - expected.angle) > 0.001
|
||||
|| actualOpening.width <= 0 || actualOpening.height <= 0
|
||||
|| actualOpening.visibleParts <= 0) {
|
||||
throw new Error(
|
||||
`semantic golden opening geometry failed for ${expected.id}: `
|
||||
+ JSON.stringify(actualOpening),
|
||||
);
|
||||
}
|
||||
}
|
||||
const clip = await goldenClip(page, scenario.capture);
|
||||
const screenshotOptions = {
|
||||
...(clip ? { clip } : {}),
|
||||
@@ -418,6 +446,11 @@ try {
|
||||
result.openingPreviewParts = control.parts;
|
||||
result.openingPreviewChangedPixels = sample.changed;
|
||||
result.openingPreviewMaxChannelDelta = sample.maxDelta;
|
||||
if (control.parts < 2) {
|
||||
throw new Error(
|
||||
`semantic golden assertion failed: opening preview is incomplete (${control.parts} parts)`,
|
||||
);
|
||||
}
|
||||
if (sample.changed < scenario.openingPreviewPixels.minPixels) {
|
||||
throw new Error(
|
||||
`semantic golden assertion failed: opening preview paints ${sample.changed} pixels, `
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user