1import { describe, test, expect, beforeEach, afterEach } from 'bun:test';
2import fs from 'fs';
3import path from 'path';
4import { createTransformer } from '../../../scripts/lib/transformers/factory.js';
5
6const TEST_DIR = path.join(process.cwd(), 'test-tmp-provider-block-transformer');
7
8const baseConfig = {
9 provider: 'cursor',
10 providerTags: ['cursor'],
11 configDir: '.test',
12 displayName: 'Test Provider',
13 frontmatterFields: [],
14};
15
16describe('provider block transformer integration', () => {
17 beforeEach(() => {
18 if (fs.existsSync(TEST_DIR)) {
19 fs.rmSync(TEST_DIR, { recursive: true, force: true });
20 }
21 });
22
23 afterEach(() => {
24 if (fs.existsSync(TEST_DIR)) {
25 fs.rmSync(TEST_DIR, { recursive: true, force: true });
26 }
27 });
28
29 test('compiles provider blocks in skill bodies', () => {
30 const transform = createTransformer(baseConfig);
31 const skills = [{
32 name: 'test',
33 description: 'Test',
34 body: [
35 'Shared guidance.',
36 '<cursor>',
37 'Cursor-only guidance.',
38 '</cursor>',
39 '<codex>',
40 'Codex-only guidance.',
41 '</codex>',
42 ].join('\n')
43 }];
44 transform(skills, TEST_DIR);
45
46 const content = fs.readFileSync(path.join(TEST_DIR, 'cursor/.test/skills/test/SKILL.md'), 'utf-8');
47 expect(content).toContain('Shared guidance.');
48 expect(content).toContain('Cursor-only guidance.');
49 expect(content).not.toContain('Codex-only guidance.');
50 expect(content).not.toContain('<cursor>');
51 });
52
53 test('compiles provider blocks in reference files', () => {
54 const transform = createTransformer(baseConfig);
55 const skills = [{
56 name: 'test',
57 description: 'Test',
58 body: 'Body',
59 references: [
60 {
61 name: 'ref',
62 filePath: '/fake/ref.md',
63 content: [
64 'Shared reference.',
65 '<cursor>',
66 'Cursor reference.',
67 '</cursor>',
68 '<codex>',
69 'Codex reference.',
70 '</codex>',
71 ].join('\n')
72 },
73 ]
74 }];
75 transform(skills, TEST_DIR);
76
77 const ref = fs.readFileSync(path.join(TEST_DIR, 'cursor/.test/skills/test/reference/ref.md'), 'utf-8');
78 expect(ref).toContain('Shared reference.');
79 expect(ref).toContain('Cursor reference.');
80 expect(ref).not.toContain('Codex reference.');
81 expect(ref).not.toContain('<cursor>');
82 });
83
84 test('compiles provider blocks in generated agents', () => {
85 const config = {
86 ...baseConfig,
87 provider: 'codex',
88 providerTags: ['codex'],
89 agentFormat: 'codex-toml',
90 };
91 const transform = createTransformer(config);
92 const skills = [{
93 name: 'test',
94 description: 'Test',
95 body: 'Body',
96 agents: [{
97 name: 'review-helper',
98 codexName: 'review_helper',
99 description: 'Review helper',
100 body: [
101 'Shared agent guidance.',
102 '<codex>',
103 'Codex agent guidance.',
104 '</codex>',
105 '<claude-code>',
106 'Claude agent guidance.',
107 '</claude-code>',
108 ].join('\n')
109 }]
110 }];
111 transform(skills, TEST_DIR);
112
113 const agent = fs.readFileSync(path.join(TEST_DIR, 'codex/.test/agents/review_helper.toml'), 'utf-8');
114 expect(agent).toContain('Shared agent guidance.');
115 expect(agent).toContain('Codex agent guidance.');
116 expect(agent).not.toContain('Claude agent guidance.');
117 expect(agent).not.toContain('<codex>');
118 });
119
120 test('writes nested script artifacts', () => {
121 const transform = createTransformer(baseConfig);
122 const skills = [{
123 name: 'test',
124 description: 'Test',
125 body: 'Body',
126 scripts: [
127 { name: 'detect.mjs', content: 'export {};\n' },
128 { name: 'detector/detect-antipatterns.mjs', content: 'export const bundled = true;\n' },
129 ],
130 }];
131 transform(skills, TEST_DIR);
132
133 const detector = path.join(TEST_DIR, 'cursor/.test/skills/test/scripts/detector/detect-antipatterns.mjs');
134 expect(fs.existsSync(detector)).toBe(true);
135 expect(fs.readFileSync(detector, 'utf-8')).toContain('bundled = true');
136 });
137});