Setting the file. One moment.
Finalize Gap Review Test · Wix Headless Replatform · wix/skills · Skills Docs
ContentsBack to the top of the page 28.10
Workflow
scripts/finalize-gap-review.test.mjs
scripts/ finalize-gap-review.test.mjs
JavaScript · 98 lines · 5 KB
function
writeJson
(
filePath
,
value
) {
9 await mkdir (path. dirname (filePath), { recursive: true });
10 await writeFile (filePath, `${ JSON . stringify ( value , null , 2 ) } \n ` );
11 }
12
13 async function fixture () {
14 const outputDir = await mkdtemp (path. join (os. tmpdir (), "gap-review-" ));
15 const iterationDir = path. join (outputDir, "docs" , "site-clone" , "gap-analysis" , "iterations" , "001" );
16 const reportPath = path. join (iterationDir, "gap-analysis.json" );
17 const report = {
18 iteration: 1 ,
19 summary: { score: 90 , findingCount: 1 , counts: { critical: 0 , high: 0 , medium: 1 , low: 0 }, blockingCount: 0 , finalAcceptance: false },
20 findings: [{ id: "gap-001" , severity: "medium" , status: "open" , category: "layout" , message: "Example" , scope: {}, repairHint: "Fix" }],
21 screenshotPairs: [{ id: "home-desktop" , page: "/" , viewport: "desktop" , source: { path: "source.png" }, result: { path: "result.png" } }],
22 visualReview: { status: "pending" , required: true , reviewedPairs: [], notes: [] },
23 fixOrder: [],
24 acceptance: { passed: false },
25 paths: { reportJson: reportPath, reportMarkdown: path. join (iterationDir, "gap-analysis.md" ), fixPlan: path. join (iterationDir, "gap-fix-plan.md" ) },
26 };
27 await writeJson (reportPath, report);
28 await writeJson (path. join (outputDir, "docs" , "site-clone" , "gap-analysis" , "latest.json" ), report);
29 await writeJson (path. join (iterationDir, "iteration-manifest.json" ), { iteration: 1 , status: "comparison-complete-visual-review-pending" });
30 return { outputDir, iterationDir };
31 }
32
33 test ( "finalizeGapReview rejects a missing visual review artifact" , async () => {
34 const { outputDir } = await fixture ();
35 try {
36 await assert. rejects (() => finalizeGapReview ({ outputDir }), /Missing required visual review evidence/ );
37 } finally {
38 await rm (outputDir, { recursive: true , force: true });
39 }
40 });
41
42 test ( "finalizeGapReview records evidence and synchronizes the iteration manifest" , async () => {
43 const { outputDir , iterationDir } = await fixture ();
44 try {
45 await writeJson (path. join (iterationDir, "visual-review.json" ), {
46 pairs: [{ pairId: "home-desktop" , viewport: "desktop" , observation: "The hero composition differs from the source." , verdict: "findings-recorded" , findingIds: [ "gap-001" ] }],
47 });
48 const report = await finalizeGapReview ({ outputDir });
49 assert. equal (report.visualReview.status, "reviewed" );
50 assert. equal (report.visualReview.records[ 0 ].findingIds[ 0 ], "gap-001" );
51 const manifest = JSON . parse ( await ( await import ( "node:fs/promises" )). readFile (path. join (iterationDir, "iteration-manifest.json" ), "utf8" ));
52 assert. equal (manifest.status, "visual-review-complete" );
53 } finally {
54 await rm (outputDir, { recursive: true , force: true });
55 }
56 });
57
58 test ( "finalizeGapReview requires traceable before/after proof after a prior blocking finding" , async () => {
59 const { outputDir , iterationDir } = await fixture ();
60 try {
61 const reportPath = path. join (iterationDir, "gap-analysis.json" );
62 const report = JSON . parse ( await ( await import ( "node:fs/promises" )). readFile (reportPath, "utf8" ));
63 const previousDir = path. join (outputDir, "docs" , "site-clone" , "gap-analysis" , "iterations" , "000" );
64 const previousReportPath = path. join (previousDir, "gap-analysis.json" );
65 await writeJson (previousReportPath, {
66 iteration: 0 ,
67 findings: [{ id: "gap-previous" , severity: "high" , status: "open" }],
68 screenshotPairs: [{ id: "home-desktop" , page: "/" , viewport: "desktop" , source: { path: "source.png" }, result: { path: "before.png" } }],
69 paths: { reportJson: previousReportPath },
70 });
71 report.visualProgress = { required: true , status: "pending" , previousIteration: 0 , previousReportPath, previousBlockingFindingIds: [ "gap-previous" ] };
72 report.paths.visualProgress = path. join (iterationDir, "visual-progress.json" );
73 await writeJson (reportPath, report);
74 await writeJson (path. join (outputDir, "docs" , "site-clone" , "gap-analysis" , "latest.json" ), report);
75 await writeJson (path. join (iterationDir, "visual-review.json" ), {
76 pairs: [{ pairId: "home-desktop" , viewport: "desktop" , observation: "The hero now matches." , verdict: "no-identity-gap" , rationale: "No identity gap remains." }],
77 });
78 await assert. rejects (() => finalizeGapReview ({ outputDir }), /Missing required visual progress proof/ );
79 await writeJson (report.paths.visualProgress, {
80 entries: [{
81 priorFindingId: "gap-previous" ,
82 target: "Hero section" ,
83 pairId: "home-desktop" ,
84 sourceScreenshotPath: "source.png" ,
85 beforeResultScreenshotPath: "before.png" ,
86 afterResultScreenshotPath: "result.png" ,
87 beforeObservation: "The hero heading was misplaced." ,
88 afterObservation: "The hero heading now aligns with the source." ,
89 verdict: "improved" ,
90 evidence: "The same desktop screenshot pair shows the corrected heading alignment." ,
91 }],
92 });
93 const finalized = await finalizeGapReview ({ outputDir });
94 assert. equal (finalized.visualProgress.records[ 0 ].verdict, "improved" );
95 } finally {
96 await rm (outputDir, { recursive: true , force: true });
97 }
98 });