feat: add testing using vitest
This commit is contained in:
@@ -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
@@ -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",
|
||||||
|
|||||||
@@ -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)})`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -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);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import { defineConfig } from 'vitest/config';
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
test: {
|
||||||
|
globals: true,
|
||||||
|
environment: 'node',
|
||||||
|
coverage: {
|
||||||
|
provider: 'v8',
|
||||||
|
reporter: ['text', 'json', 'html'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user