Skip to content

Commit e895840

Browse files
committed
test: cover skill utilities
1 parent 9c574a7 commit e895840

File tree

1 file changed

+92
-0
lines changed

1 file changed

+92
-0
lines changed

packages/clawdhub/src/skills.test.ts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ import {
1111
hashSkillZip,
1212
listTextFiles,
1313
readLockfile,
14+
readSkillOrigin,
1415
sha256Hex,
1516
writeLockfile,
17+
writeSkillOrigin,
1618
} from './skills'
1719

1820
describe('skills', () => {
@@ -46,6 +48,18 @@ describe('skills', () => {
4648
expect(read).toEqual({ version: 1, skills: {} })
4749
})
4850

51+
it('returns empty lockfile on schema mismatch', async () => {
52+
const workdir = await mkdtemp(join(tmpdir(), 'clawdhub-work-schema-'))
53+
await mkdir(join(workdir, '.clawdhub'), { recursive: true })
54+
await writeFile(
55+
join(workdir, '.clawdhub', 'lock.json'),
56+
JSON.stringify({ version: 1, skills: 'nope' }),
57+
'utf8',
58+
)
59+
const read = await readLockfile(workdir)
60+
expect(read).toEqual({ version: 1, skills: {} })
61+
})
62+
4963
it('skips dotfiles and node_modules when listing text files', async () => {
5064
const workdir = await mkdtemp(join(tmpdir(), 'clawdhub-files-'))
5165
await writeFile(join(workdir, 'SKILL.md'), 'hi', 'utf8')
@@ -74,6 +88,16 @@ describe('skills', () => {
7488
)
7589
})
7690

91+
it('falls back to text/plain for unknown text extensions', async () => {
92+
const workdir = await mkdtemp(join(tmpdir(), 'clawdhub-env-'))
93+
await writeFile(join(workdir, 'SKILL.md'), 'hi', 'utf8')
94+
await writeFile(join(workdir, 'config.env'), 'TOKEN=demo', 'utf8')
95+
const files = await listTextFiles(workdir)
96+
expect(files.find((file) => file.relPath === 'config.env')?.contentType).toBe(
97+
'text/plain',
98+
)
99+
})
100+
77101
it('hashes skill files deterministically', async () => {
78102
const { fingerprint } = hashSkillFiles([
79103
{ relPath: 'b.txt', bytes: strToU8('b') },
@@ -99,4 +123,72 @@ describe('skills', () => {
99123
])
100124
expect(fingerprint).toBe(expected)
101125
})
126+
127+
it('ignores unsafe or non-text entries when hashing zips', () => {
128+
const zip = zipSync({
129+
'SKILL.md': strToU8('hello'),
130+
'folder/': strToU8(''),
131+
'../evil.txt': strToU8('nope'),
132+
'bad\\path.txt': strToU8('nope'),
133+
'image.png': strToU8('nope'),
134+
})
135+
const { files } = hashSkillZip(new Uint8Array(zip))
136+
expect(files).toEqual([
137+
{ path: 'SKILL.md', sha256: sha256Hex(strToU8('hello')), size: 5 },
138+
])
139+
})
140+
141+
it('builds fingerprints from valid entries only', () => {
142+
const fingerprint = buildSkillFingerprint([
143+
{ path: '', sha256: '' },
144+
{ path: 'valid.txt', sha256: sha256Hex(strToU8('ok')) },
145+
])
146+
const expected = buildSkillFingerprint([
147+
{ path: 'valid.txt', sha256: sha256Hex(strToU8('ok')) },
148+
])
149+
expect(fingerprint).toBe(expected)
150+
})
151+
152+
it('returns null for invalid skill origin metadata', async () => {
153+
const workdir = await mkdtemp(join(tmpdir(), 'clawdhub-origin-'))
154+
expect(await readSkillOrigin(workdir)).toBeNull()
155+
156+
await mkdir(join(workdir, '.clawdhub'), { recursive: true })
157+
await writeFile(
158+
join(workdir, '.clawdhub', 'origin.json'),
159+
JSON.stringify({ version: 2 }),
160+
'utf8',
161+
)
162+
expect(await readSkillOrigin(workdir)).toBeNull()
163+
164+
await writeFile(
165+
join(workdir, '.clawdhub', 'origin.json'),
166+
JSON.stringify({ version: 1, registry: 'demo', slug: 'x', installedAt: 1 }),
167+
'utf8',
168+
)
169+
expect(await readSkillOrigin(workdir)).toBeNull()
170+
171+
await writeFile(
172+
join(workdir, '.clawdhub', 'origin.json'),
173+
JSON.stringify({
174+
version: 1,
175+
registry: 'demo',
176+
slug: 'x',
177+
installedVersion: '0.1.0',
178+
installedAt: 'nope',
179+
}),
180+
'utf8',
181+
)
182+
expect(await readSkillOrigin(workdir)).toBeNull()
183+
184+
const origin = {
185+
version: 1,
186+
registry: 'https://example.com',
187+
slug: 'demo',
188+
installedVersion: '1.2.3',
189+
installedAt: 123,
190+
}
191+
await writeSkillOrigin(workdir, origin)
192+
expect(await readSkillOrigin(workdir)).toEqual(origin)
193+
})
102194
})

0 commit comments

Comments
 (0)