|
1 | 1 | /** biome-ignore-all lint/suspicious/noTemplateCurlyInString: Fixtures contain proposed source text. */ |
2 | 2 | import { readFileSync } from 'node:fs' |
3 | 3 | import { expect, test } from 'vitest' |
4 | | -import type { ControlSource } from '#control-analysis/model' |
| 4 | +import { associateFindings } from '#control-analysis/associations' |
| 5 | +import type { ControlSource, InventoryFinding } from '#control-analysis/model' |
5 | 6 | import { ReviewCollector } from '#control-analysis/review' |
6 | 7 | import { findingFingerprint, matchReviews } from '#control-analysis/review-ledger' |
7 | 8 | import { productScope } from '#control-analysis/scope' |
8 | 9 | import { inspectSimplifications } from '#control-analysis/simplifications' |
9 | 10 | import { extract } from '#design-conformance/extract' |
10 | 11 | import type { GeneratedContracts } from '#design-conformance/generated-contracts' |
| 12 | +import { inspectionFailure } from '#design-conformance/model' |
11 | 13 |
|
12 | 14 | const globals = 'apps/sim/app/_styles/globals.css' |
13 | 15 | const ui = 'apps/sim/components/example.tsx' |
@@ -431,3 +433,55 @@ test('hidden false and runtime visibility cannot hide local control styling', () |
431 | 433 | }).review.findings.some((f) => f.rule === 'local-control') |
432 | 434 | ).toBe(false) |
433 | 435 | }) |
| 436 | + |
| 437 | +test.each([ |
| 438 | + 'export const View=()=> <style>{".label {color: #abc}"}</style>', |
| 439 | + 'export const View=()=> <style>.label {color: #abc}</style>', |
| 440 | +])('literal JSX styles remain visible: %s', (code) => { |
| 441 | + const report = inspect({ [ui]: code }) |
| 442 | + expect(report.review.findings.some((f) => f.rule === 'runtime-style')).toBe(true) |
| 443 | + expect(report.review.unchecked.some((n) => n.file === ui && n.reason.includes('style'))).toBe( |
| 444 | + true |
| 445 | + ) |
| 446 | +}) |
| 447 | + |
| 448 | +test('conditional input branches remain directly associated with their control', () => { |
| 449 | + const finding: InventoryFinding = { |
| 450 | + id: 'branch', |
| 451 | + rule: 'component-chrome', |
| 452 | + category: 'colours', |
| 453 | + property: 'color', |
| 454 | + file: ui, |
| 455 | + line: 1, |
| 456 | + column: 10, |
| 457 | + context: 'View / @sim/emcn#Button / className/then', |
| 458 | + value: 'text-white', |
| 459 | + reason: 'owned chrome', |
| 460 | + observedFrom: [ui], |
| 461 | + } |
| 462 | + const uses = [ |
| 463 | + { |
| 464 | + id: 'control', |
| 465 | + file: ui, |
| 466 | + line: 1, |
| 467 | + column: 1, |
| 468 | + endLine: 1, |
| 469 | + endColumn: 40, |
| 470 | + owner: 'View', |
| 471 | + tag: 'Button', |
| 472 | + slots: [{ name: 'className', line: 1, column: 5, endLine: 1, endColumn: 30 }], |
| 473 | + }, |
| 474 | + ] |
| 475 | + expect(associateFindings(uses, [finding], () => ['@sim/emcn#Button']).get('control')).toEqual({ |
| 476 | + direct: ['branch'], |
| 477 | + potential: [], |
| 478 | + }) |
| 479 | +}) |
| 480 | +test.each([ |
| 481 | + 'CSS assignment source is nonregular or exceeds the parsing limit', |
| 482 | + 'Artwork parser failure; only blob change is known', |
| 483 | + 'Artwork source exceeds the 2 MiB parsing limit', |
| 484 | + 'Artwork symlink/submodule is not followed', |
| 485 | +])('inspection failures are not unresolved styling: %s', (reason) => { |
| 486 | + expect(inspectionFailure(reason)).toBe(true) |
| 487 | +}) |
0 commit comments