feat: add testing using vitest

This commit is contained in:
Space-Banane
2026-03-20 14:56:19 +01:00
parent 1b3851d0af
commit 6ad74bb991
5 changed files with 83 additions and 3 deletions
+1
View File
@@ -28,6 +28,7 @@ jobs:
node-version: '24' node-version: '24'
- run: pnpm install --no-frozen-lockfile - run: pnpm install --no-frozen-lockfile
- run: pnpm test
- run: pnpm build - run: pnpm build
- name: Zip dist directory - name: Zip dist directory
+7 -3
View File
@@ -1,6 +1,6 @@
{ {
"name": "shsf-cli", "name": "shsf-cli",
"version": "2.1.5", "version": "2.1.6",
"description": "", "description": "",
"type": "module", "type": "module",
"files": [ "files": [
@@ -12,7 +12,9 @@
"scripts": { "scripts": {
"build": "rimraf dist && tsc", "build": "rimraf dist && tsc",
"start": "node dist/index.js", "start": "node dist/index.js",
"test": "echo \"Error: no test specified\" && exit 1" "test": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage"
}, },
"keywords": [], "keywords": [],
"author": "", "author": "",
@@ -21,9 +23,11 @@
"devDependencies": { "devDependencies": {
"@types/inquirer": "^9.0.9", "@types/inquirer": "^9.0.9",
"@types/node": "^25.5.0", "@types/node": "^25.5.0",
"@vitest/coverage-v8": "^4.1.0",
"rimraf": "^6.1.3", "rimraf": "^6.1.3",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"typescript": "^5.9.3" "typescript": "^5.9.3",
"vitest": "^4.1.0"
}, },
"dependencies": { "dependencies": {
"axios": "^1.13.6", "axios": "^1.13.6",
+52
View File
@@ -0,0 +1,52 @@
import { describe, it, expect, vi } from 'vitest';
import path from 'path';
import fs from 'fs';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
describe('Command Loading', () => {
it('all command files should export a valid definition', async () => {
const commandsDir = path.resolve(__dirname, '../commands');
function getCommandFiles(dir: string): string[] {
const files = fs.readdirSync(dir);
let commandFiles: string[] = [];
for (const file of files) {
const fullPath = path.join(dir, file);
if (fs.statSync(fullPath).isDirectory()) {
commandFiles = commandFiles.concat(getCommandFiles(fullPath));
} else if (file.endsWith('.ts') || file.endsWith('.js')) {
commandFiles.push(fullPath);
}
}
return commandFiles;
}
const files = getCommandFiles(commandsDir);
expect(files.length).toBeGreaterThan(0);
for (const file of files) {
// Use dynamic import to check the module
// We convert absolute path to file:// URL for ESM import on Linux/Windows
const module = await import(`file://${file}`);
const definition = module.default || Object.values(module).find((val: any) =>
val && typeof val === 'object' && val.name && typeof val.action === 'function'
);
if (!definition) {
throw new Error(`Command file ${file} does not export a valid command definition (needs name and action function)`);
}
expect(definition).toBeDefined();
expect(typeof definition.name).toBe('string');
expect(typeof definition.action).toBe('function');
console.log(`✓ Validated command: ${definition.name} (${path.relative(commandsDir, file)})`);
}
});
});
+11
View File
@@ -0,0 +1,11 @@
import { describe, it, expect, vi } from 'vitest';
import path from 'path';
import os from 'os';
import { getConfigPath } from '../config.js';
describe('config', () => {
it('should return the correct config path', () => {
const expectedPath = path.join(os.homedir(), '.shsf_config');
expect(getConfigPath()).toBe(expectedPath);
});
});
+12
View File
@@ -0,0 +1,12 @@
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
globals: true,
environment: 'node',
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html'],
},
},
});