mirror of
https://github.com/nexu-io/open-design.git
synced 2026-05-31 19:04:39 +07:00
* Add design system import manifest schema * Generate hybrid design system imports * Read design system usage and cached manifests * Add design system pull-file tool * Show design system package evidence * Wire design system import semantics * Add design system package quality guard --------- Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local>
145 lines
4.8 KiB
TypeScript
145 lines
4.8 KiB
TypeScript
import fs from 'node:fs';
|
|
import os from 'node:os';
|
|
import path from 'node:path';
|
|
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
|
|
import {
|
|
importGitHubDesignSystemProject,
|
|
parseGitHubRepoUrl,
|
|
} from '../src/design-system-github-import.js';
|
|
|
|
describe('parseGitHubRepoUrl', () => {
|
|
it('normalizes public GitHub repository URLs to clone URLs', () => {
|
|
expect(parseGitHubRepoUrl('https://github.com/acme/design-system')).toEqual({
|
|
owner: 'acme',
|
|
repo: 'design-system',
|
|
cloneUrl: 'https://github.com/acme/design-system.git',
|
|
});
|
|
expect(parseGitHubRepoUrl('https://github.com/acme/design-system.git')).toEqual({
|
|
owner: 'acme',
|
|
repo: 'design-system',
|
|
cloneUrl: 'https://github.com/acme/design-system.git',
|
|
});
|
|
});
|
|
|
|
it('rejects non-root or non-GitHub URLs', () => {
|
|
expect(() => parseGitHubRepoUrl('https://example.com/acme/design-system')).toThrow(
|
|
/github\.com/,
|
|
);
|
|
expect(() => parseGitHubRepoUrl('https://github.com/acme/design-system/tree/main')).toThrow(
|
|
/repository root/,
|
|
);
|
|
});
|
|
});
|
|
|
|
describe('importGitHubDesignSystemProject', () => {
|
|
let tempRoot: string;
|
|
let fixtureRoot: string;
|
|
let tmpRoot: string;
|
|
let userDesignSystemsRoot: string;
|
|
let fakeGit: string;
|
|
|
|
beforeEach(() => {
|
|
tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'od-ds-github-import-'));
|
|
fixtureRoot = path.join(tempRoot, 'fixture-repo');
|
|
tmpRoot = path.join(tempRoot, '.tmp');
|
|
userDesignSystemsRoot = path.join(tempRoot, 'user-design-systems');
|
|
fs.mkdirSync(path.join(fixtureRoot, 'src', 'components'), { recursive: true });
|
|
fs.mkdirSync(path.join(fixtureRoot, 'src', 'styles'), { recursive: true });
|
|
fs.writeFileSync(
|
|
path.join(fixtureRoot, 'package.json'),
|
|
JSON.stringify({
|
|
name: 'github-design-kit',
|
|
description: 'A GitHub-hosted design kit.',
|
|
dependencies: { react: '^18.0.0' },
|
|
}),
|
|
);
|
|
fs.writeFileSync(path.join(fixtureRoot, 'README.md'), '# GitHub Design Kit\n\nRemote style source.\n');
|
|
fs.writeFileSync(path.join(fixtureRoot, 'src', 'styles', 'tokens.css'), ':root { --primary: #22c55e; }');
|
|
fs.writeFileSync(path.join(fixtureRoot, 'src', 'components', 'Card.tsx'), 'export function Card() {}');
|
|
|
|
fakeGit = path.join(tempRoot, 'fake-git.sh');
|
|
fs.writeFileSync(
|
|
fakeGit,
|
|
`#!/bin/sh
|
|
set -eu
|
|
if [ "$1" = "clone" ]; then
|
|
target=""
|
|
for arg in "$@"; do target="$arg"; done
|
|
mkdir -p "$target"
|
|
cp -R "$FAKE_GIT_SOURCE"/. "$target"/
|
|
exit 0
|
|
fi
|
|
if [ "$1" = "-C" ] && [ "$3" = "rev-parse" ] && [ "$4" = "--abbrev-ref" ]; then
|
|
printf 'main\\n'
|
|
exit 0
|
|
fi
|
|
if [ "$1" = "-C" ] && [ "$3" = "rev-parse" ] && [ "$4" = "HEAD" ]; then
|
|
printf 'abc123def456\\n'
|
|
exit 0
|
|
fi
|
|
echo "unexpected git args: $*" >&2
|
|
exit 1
|
|
`,
|
|
);
|
|
fs.chmodSync(fakeGit, 0o755);
|
|
process.env.FAKE_GIT_SOURCE = fixtureRoot;
|
|
});
|
|
|
|
afterEach(() => {
|
|
delete process.env.FAKE_GIT_SOURCE;
|
|
fs.rmSync(tempRoot, { recursive: true, force: true });
|
|
});
|
|
|
|
it('clones a public GitHub URL and imports through the local project format', async () => {
|
|
const result = await importGitHubDesignSystemProject(
|
|
'https://github.com/acme/design-kit',
|
|
tmpRoot,
|
|
userDesignSystemsRoot,
|
|
{
|
|
gitBin: fakeGit,
|
|
now: new Date('2026-05-18T10:00:00.000Z'),
|
|
importMode: 'normalized',
|
|
craftApplies: ['color'],
|
|
},
|
|
);
|
|
|
|
expect(result.id).toBe('github-design-kit');
|
|
const manifest = JSON.parse(fs.readFileSync(path.join(result.dir, 'manifest.json'), 'utf8')) as Record<string, unknown>;
|
|
expect(manifest).toMatchObject({
|
|
schemaVersion: 'od-design-system-project/v1',
|
|
id: 'github-design-kit',
|
|
source: {
|
|
type: 'github',
|
|
url: 'https://github.com/acme/design-kit.git',
|
|
branch: 'main',
|
|
commit: 'abc123def456',
|
|
importedAt: '2026-05-18T10:00:00.000Z',
|
|
},
|
|
files: {
|
|
design: 'DESIGN.md',
|
|
tokens: 'tokens.css',
|
|
components: 'components.html',
|
|
},
|
|
usage: 'USAGE.md',
|
|
componentsManifest: 'components.manifest.json',
|
|
importMode: 'normalized',
|
|
craft: {
|
|
applies: ['color'],
|
|
},
|
|
sourceFiles: {
|
|
scanned: 'source/scanned-files.json',
|
|
evidence: 'source/evidence.md',
|
|
tokens: 'source/tokens.source.json',
|
|
snippets: 'source/snippets/INDEX.json',
|
|
},
|
|
});
|
|
expect(fs.readFileSync(path.join(result.dir, 'DESIGN.md'), 'utf8')).toContain(
|
|
'A GitHub-hosted design kit.',
|
|
);
|
|
expect(fs.existsSync(path.join(result.dir, 'USAGE.md'))).toBe(true);
|
|
expect(fs.existsSync(path.join(result.dir, 'components.manifest.json'))).toBe(true);
|
|
expect(fs.existsSync(path.join(result.dir, 'preview', 'app.html'))).toBe(true);
|
|
expect(fs.existsSync(path.join(result.dir, 'source', 'snippets', 'card.tsx'))).toBe(true);
|
|
});
|
|
});
|