open-design/apps/daemon/tests/design-file-score.test.ts
Chris Seifert 0f5ac37c22
Capture native (Swift) source in the GitHub design import (#2847)
A design system imported from a SwiftUI repo could never be published. The
import's file scorer was web-only, so every .swift file scored 0 while the
repo's config dotfiles (.zenflow, .vscode, .zed) scored on the generic text
bonus and won the top-N selection. Even when a source file was selected, the
snapshot writer's text-file allowlist didn't include .swift, so it was dropped.
The result: snapshots were all config dotfiles, which the project files API
hides, so the publish gate saw zero evidence snapshots and stayed blocked no
matter how many times the intake ran.

Three layers fixed in tools-connectors-cli.ts:
- scoreDesignFile now scores native/design-token source (Swift, Kotlin, Go,
  Rust, etc.), with a high boost for token files like ColorSystem.swift,
  Typography.swift, Spacing.swift.
- shouldSkipRepoPath skips editor/CI/agent tooling dirs (.vscode, .zed, .idea,
  .zenflow, .github, .husky, ...) so their files stop crowding out real source.
- isTextSnapshotPath recognizes native source extensions so selected files are
  actually written.

Also teach the design-system swatch extraction to read SwiftUI colors:
swift-colors.ts parses Color(red:green:blue:), Color(hue:saturation:brightness:)
(HSB), and Color(white:), evaluating decimal, hex-byte, and division component
expressions (0xF4 / 255, 220 / 360), and design-systems.ts uses it as a new
swatch form. scoreDesignFile, shouldSkipRepoPath, and isTextSnapshotPath are
exported for unit tests.

Verified against a real SwiftUI repo: the intake now captures ColorSystem,
TypographySystem, SpacingSystem and the view/model source instead of config
dotfiles.
2026-05-25 05:17:47 +00:00

50 lines
2.1 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import {
isTextSnapshotPath,
scoreDesignFile,
shouldSkipRepoPath,
} from '../src/tools-connectors-cli.js';
describe('shouldSkipRepoPath', () => {
it('skips editor / CI / agent-tooling directories', () => {
expect(shouldSkipRepoPath('.vscode/settings.json')).toBe(true);
expect(shouldSkipRepoPath('.zed/tasks.json')).toBe(true);
expect(shouldSkipRepoPath('.zenflow/tasks/cleanup/spec.md')).toBe(true);
expect(shouldSkipRepoPath('.idea/workspace.xml')).toBe(true);
expect(shouldSkipRepoPath('.github/workflows/ci.yml')).toBe(true);
});
it('keeps real source directories', () => {
expect(shouldSkipRepoPath('sources/stackme/theme/colorsystem.swift')).toBe(false);
expect(shouldSkipRepoPath('stackme/views/projectlist.swift')).toBe(false);
});
});
describe('scoreDesignFile (non-web source)', () => {
it('ranks Swift token source far above tooling config files', () => {
const colorSystem = scoreDesignFile('Sources/StackMe/Theme/ColorSystem.swift');
const typography = scoreDesignFile('Sources/StackMe/Theme/Typography.swift');
const view = scoreDesignFile('Sources/StackMe/Views/ProjectList.swift');
const tooling = scoreDesignFile('.zenflow/tasks/cleanup/spec.md');
// Tooling dirs are skipped outright.
expect(tooling).toBe(-1);
// Token source is high-signal; plain source still beats the skipped config.
expect(colorSystem).toBeGreaterThan(view);
expect(typography).toBeGreaterThan(view);
expect(view).toBeGreaterThan(0);
expect(view).toBeGreaterThan(tooling);
});
});
describe('isTextSnapshotPath', () => {
it('writes native source snapshots, not just web files', () => {
// Without this a selected Swift file was dropped at write time, so the
// import produced zero snapshots and publishing stayed blocked.
expect(isTextSnapshotPath('utilities/colorsystem.swift')).toBe(true);
expect(isTextSnapshotPath('app/main.kt')).toBe(true);
expect(isTextSnapshotPath('src/theme.css')).toBe(true);
expect(isTextSnapshotPath('assets/logo.png')).toBe(false);
});
});