Skip to content

Commit e412562

Browse files
Merge branch 'main' into replace-semvar
2 parents 654e13b + 0c62985 commit e412562

2 files changed

Lines changed: 192 additions & 1 deletion

File tree

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
import { rmSync } from 'node:fs'
2+
import { afterAll, beforeAll, describe, expect, it } from 'vitest'
3+
import {
4+
publishFixtures,
5+
runLoad,
6+
scaffoldProject,
7+
startRegistry,
8+
} from './scaffold.js'
9+
import type { PackageManager, Registry } from './scaffold.js'
10+
11+
const PACKAGE_MANAGERS: Array<PackageManager> = ['npm', 'pnpm', 'yarn', 'bun']
12+
const SKILL_USE = '@test-intent/skills-leaf#core'
13+
14+
let registry: Registry
15+
const tempDirs: Array<string> = []
16+
17+
beforeAll(async () => {
18+
registry = await startRegistry()
19+
publishFixtures(registry.url)
20+
}, 30_000)
21+
22+
afterAll(() => {
23+
registry?.stop()
24+
for (const dir of tempDirs) {
25+
rmSync(dir, { recursive: true, force: true })
26+
}
27+
})
28+
29+
function expectSkillContent(stdout: string): void {
30+
expect(stdout).toContain('# Core Skill')
31+
expect(stdout).toContain('This is a test skill used by integration tests.')
32+
expect(stdout).not.toMatch(/^TanStack Intent\b/m)
33+
expect(stdout).not.toMatch(/^Usage:/m)
34+
}
35+
36+
describe.each(PACKAGE_MANAGERS)('intent load via installed bin (%s)', (pm) => {
37+
it('prints the resolved skill content', () => {
38+
const { root, cwd } = scaffoldProject({
39+
pm,
40+
structure: 'single',
41+
dependency: '@test-intent/skills-leaf',
42+
registryUrl: registry.url,
43+
})
44+
tempDirs.push(root)
45+
46+
const result = runLoad(cwd, SKILL_USE)
47+
48+
if (result.exitCode !== 0) {
49+
throw new Error(
50+
`intent load failed\nstdout:\n${result.stdout}\nstderr:\n${result.stderr}`,
51+
)
52+
}
53+
expectSkillContent(result.stdout)
54+
}, 60_000)
55+
})
56+
57+
describe('intent load resolution variants', () => {
58+
it('returns the resolved path with --path', () => {
59+
const { root, cwd } = scaffoldProject({
60+
pm: 'npm',
61+
structure: 'single',
62+
dependency: '@test-intent/skills-leaf',
63+
registryUrl: registry.url,
64+
})
65+
tempDirs.push(root)
66+
67+
const result = runLoad(cwd, SKILL_USE, { path: true })
68+
69+
if (result.exitCode !== 0) {
70+
throw new Error(
71+
`intent load --path failed\nstdout:\n${result.stdout}\nstderr:\n${result.stderr}`,
72+
)
73+
}
74+
expect(result.stdout.trim()).toMatch(/skills[/\\]core[/\\]SKILL\.md\s*$/)
75+
}, 60_000)
76+
77+
it('returns structured JSON with --json', () => {
78+
const { root, cwd } = scaffoldProject({
79+
pm: 'npm',
80+
structure: 'single',
81+
dependency: '@test-intent/skills-leaf',
82+
registryUrl: registry.url,
83+
})
84+
tempDirs.push(root)
85+
86+
const result = runLoad(cwd, SKILL_USE, { json: true })
87+
88+
if (result.exitCode !== 0) {
89+
throw new Error(
90+
`intent load --json failed\nstdout:\n${result.stdout}\nstderr:\n${result.stderr}`,
91+
)
92+
}
93+
expect(result.parsed).toMatchObject({
94+
package: '@test-intent/skills-leaf',
95+
skill: 'core',
96+
version: '1.0.0',
97+
})
98+
expect(typeof result.parsed.content).toBe('string')
99+
expect(result.parsed.content).toContain('# Core Skill')
100+
}, 60_000)
101+
102+
it('prints content when invoked through a symlink (mimics node_modules/.bin)', () => {
103+
const { root, cwd } = scaffoldProject({
104+
pm: 'npm',
105+
structure: 'single',
106+
dependency: '@test-intent/skills-leaf',
107+
registryUrl: registry.url,
108+
})
109+
tempDirs.push(root)
110+
111+
const result = runLoad(cwd, SKILL_USE, { method: 'symlink' })
112+
113+
if (result.exitCode !== 0) {
114+
throw new Error(
115+
`intent load via symlink failed\nstdout:\n${result.stdout}\nstderr:\n${result.stderr}`,
116+
)
117+
}
118+
expectSkillContent(result.stdout)
119+
}, 60_000)
120+
121+
it('resolves a workspace-dep skill from a monorepo workspace package', () => {
122+
const { root, cwd } = scaffoldProject({
123+
pm: 'pnpm',
124+
structure: 'monorepo-workspace',
125+
dependency: '@test-intent/skills-leaf',
126+
registryUrl: registry.url,
127+
})
128+
tempDirs.push(root)
129+
130+
const result = runLoad(cwd, SKILL_USE)
131+
132+
if (result.exitCode !== 0) {
133+
throw new Error(
134+
`intent load in monorepo-workspace failed\nstdout:\n${result.stdout}\nstderr:\n${result.stderr}`,
135+
)
136+
}
137+
expectSkillContent(result.stdout)
138+
}, 60_000)
139+
})

packages/intent/tests/integration/scaffold.ts

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { execSync, execFileSync, spawn } from 'node:child_process'
1+
import { execFileSync, execSync, spawn } from 'node:child_process'
22
import {
33
mkdirSync,
44
mkdtempSync,
@@ -358,6 +358,58 @@ export function runScanner(
358358
}
359359
}
360360

361+
export interface RunLoadOptions {
362+
method?: 'direct' | 'symlink'
363+
path?: boolean
364+
json?: boolean
365+
}
366+
367+
export function runLoad(
368+
cwd: string,
369+
use: string,
370+
options: RunLoadOptions = {},
371+
): CliResult {
372+
const method = options.method ?? 'direct'
373+
let binPath = cliPath
374+
let linkDir: string | undefined
375+
376+
if (method === 'symlink') {
377+
linkDir = mkdtempSync(join(realTmpdir, 'intent-link-'))
378+
const linkPath = join(linkDir, 'intent-cli.mjs')
379+
symlinkSync(cliPath, linkPath)
380+
binPath = linkPath
381+
}
382+
383+
const args: Array<string> = [binPath, 'load', use]
384+
if (options.path) args.push('--path')
385+
if (options.json) args.push('--json')
386+
387+
try {
388+
const stdout = execFileSync('node', args, {
389+
cwd,
390+
encoding: 'utf8',
391+
stdio: ['ignore', 'pipe', 'pipe'],
392+
})
393+
return {
394+
stdout,
395+
stderr: '',
396+
exitCode: 0,
397+
parsed: options.json ? JSON.parse(stdout) : null,
398+
}
399+
} catch (err: any) {
400+
return {
401+
stdout: err.stdout ?? '',
402+
stderr: err.stderr ?? '',
403+
exitCode: err.status ?? 1,
404+
parsed: null,
405+
}
406+
} finally {
407+
if (linkDir) {
408+
rmSync(linkDir, { recursive: true, force: true })
409+
}
410+
}
411+
}
412+
361413
// ---------------------------------------------------------------------------
362414
// Helpers
363415
// ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)