Files
gemini-cli/integration-tests/skill-creator-scripts.test.ts
T
2026-01-18 19:51:05 -08:00

105 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @license
* Copyright 2026 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { TestRig } from './test-helper.js';
import * as fs from 'node:fs';
import * as path from 'node:path';
import { execSync } from 'node:child_process';
describe('skill-creator scripts e2e', () => {
let rig: TestRig;
const initScript = path.resolve(
'packages/core/src/skills/builtin/skill-creator/scripts/init_skill.cjs',
);
const validateScript = path.resolve(
'packages/core/src/skills/builtin/skill-creator/scripts/validate_skill.cjs',
);
const packageScript = path.resolve(
'packages/core/src/skills/builtin/skill-creator/scripts/package_skill.cjs',
);
beforeEach(() => {
rig = new TestRig();
});
afterEach(async () => {
await rig.cleanup();
});
it('should initialize, validate, and package a skill', async () => {
await rig.setup('skill-creator scripts e2e');
const skillName = 'e2e-test-skill';
const tempDir = rig.testDir!;
// 1. Initialize
execSync(`node "${initScript}" ${skillName} --path "${tempDir}"`, {
stdio: 'inherit',
});
const skillDir = path.join(tempDir, skillName);
expect(fs.existsSync(skillDir)).toBe(true);
expect(fs.existsSync(path.join(skillDir, 'SKILL.md'))).toBe(true);
expect(
fs.existsSync(path.join(skillDir, 'scripts/example_script.cjs')),
).toBe(true);
// 2. Validate (should have warning initially due to TODOs)
const validateOutputInitial = execSync(
`node "${validateScript}" "${skillDir}" 2>&1`,
{ encoding: 'utf8' },
);
expect(validateOutputInitial).toContain(' Found unresolved TODO');
// 3. Package (should fail due to TODOs)
try {
execSync(`node "${packageScript}" "${skillDir}" "${tempDir}"`, {
stdio: 'pipe',
});
throw new Error('Packaging should have failed due to TODOs');
} catch (err: unknown) {
expect((err as Error).message).toContain('Command failed');
}
// 4. Fix SKILL.md (remove TODOs)
let content = fs.readFileSync(path.join(skillDir, 'SKILL.md'), 'utf8');
// More aggressive global replace for all TODO patterns
content = content.replace(/TODO:[^\n]*/g, 'Fixed');
content = content.replace(/\[TODO:[^\]]*\]/g, 'Fixed');
fs.writeFileSync(path.join(skillDir, 'SKILL.md'), content);
// Also remove TODOs from example scripts
const exampleScriptPath = path.join(skillDir, 'scripts/example_script.cjs');
let scriptContent = fs.readFileSync(exampleScriptPath, 'utf8');
scriptContent = scriptContent.replace(/TODO:[^\n]*/g, 'Fixed');
fs.writeFileSync(exampleScriptPath, scriptContent);
// 4. Validate again (should pass now)
const validateOutput = execSync(`node "${validateScript}" "${skillDir}"`, {
encoding: 'utf8',
});
expect(validateOutput).toContain('Skill is valid!');
// 5. Package
execSync(`node "${packageScript}" "${skillDir}" "${tempDir}"`, {
stdio: 'inherit',
});
const skillFile = path.join(tempDir, `${skillName}.skill`);
expect(fs.existsSync(skillFile)).toBe(true);
// 6. Verify zip content (should NOT have nested directory)
// Use unzip -l if available, otherwise fallback to tar -tf (common on Windows)
let zipList: string;
try {
zipList = execSync(`unzip -l "${skillFile}"`, { encoding: 'utf8' });
} catch {
zipList = execSync(`tar -tf "${skillFile}"`, { encoding: 'utf8' });
}
expect(zipList).toContain('SKILL.md');
expect(zipList).not.toContain(`${skillName}/SKILL.md`);
});
});