@ordojs/cli
Version:
Command-line interface for OrdoJS framework
331 lines (279 loc) • 11.4 kB
text/typescript
/**
* @fileoverview Tests for the CI/CD generator
*/
import { beforeEach, describe, expect, it } from 'vitest';
import type { DeploymentConfig } from './adapter-interface.js';
import { CICDGenerator } from './cicd-generator.js';
describe('CICDGenerator', () => {
let cicdGenerator: CICDGenerator;
let mockDeploymentConfig: DeploymentConfig;
beforeEach(() => {
cicdGenerator = new CICDGenerator();
mockDeploymentConfig = {
outputDir: 'dist',
isStatic: false,
includeServerFunctions: true,
env: {
NODE_ENV: 'production',
PORT: '3000'
}
};
});
describe('generatePipeline', () => {
it('should generate GitHub Actions pipeline by default', () => {
const pipeline = cicdGenerator.generatePipeline(mockDeploymentConfig);
expect(pipeline).toContain('name: OrdoJS CI/CD Pipeline');
expect(pipeline).toContain('on:');
expect(pipeline).toContain('push:');
expect(pipeline).toContain('pull_request:');
expect(pipeline).toContain('jobs:');
expect(pipeline).toContain('test:');
expect(pipeline).toContain('build:');
});
it('should generate GitLab CI pipeline', () => {
const pipeline = cicdGenerator.generatePipeline(mockDeploymentConfig, {
platform: 'gitlab'
});
expect(pipeline).toContain('# GitLab CI/CD Pipeline for OrdoJS');
expect(pipeline).toContain('image: node:18-alpine');
expect(pipeline).toContain('stages:');
expect(pipeline).toContain('- test');
expect(pipeline).toContain('- build');
});
it('should generate Jenkins pipeline', () => {
const pipeline = cicdGenerator.generatePipeline(mockDeploymentConfig, {
platform: 'jenkins'
});
expect(pipeline).toContain('pipeline {');
expect(pipeline).toContain('agent {');
expect(pipeline).toContain('stages {');
expect(pipeline).toContain('stage(\'Setup\')');
expect(pipeline).toContain('stage(\'Build\')');
});
it('should throw error for unsupported platform', () => {
expect(() => {
cicdGenerator.generatePipeline(mockDeploymentConfig, {
platform: 'unsupported' as any
});
}).toThrow('Unsupported platform: unsupported');
});
});
describe('generateGitHubActions', () => {
it('should generate complete GitHub Actions workflow', () => {
const config = {
platform: 'github' as const,
nodeVersion: '18',
pnpmVersion: '8',
testCommand: 'pnpm test',
buildCommand: 'pnpm build',
deployCommand: 'pnpm deploy',
cacheDependencies: true,
runTests: true,
runLinting: true,
runSecurityScan: true,
autoDeploy: false,
environments: ['production', 'staging'],
secrets: []
};
const workflow = cicdGenerator.generateGitHubActions(config, mockDeploymentConfig);
expect(workflow).toContain('name: OrdoJS CI/CD Pipeline');
expect(workflow).toContain('on:');
expect(workflow).toContain('push:');
expect(workflow).toContain('branches: [ main, develop ]');
expect(workflow).toContain('pull_request:');
expect(workflow).toContain('branches: [ main ]');
expect(workflow).toContain('env:');
expect(workflow).toContain('NODE_VERSION: \'18\'');
expect(workflow).toContain('PNPM_VERSION: \'8\'');
expect(workflow).toContain('jobs:');
expect(workflow).toContain('test:');
expect(workflow).toContain('build:');
expect(workflow).toContain('runs-on: ubuntu-latest');
expect(workflow).toContain('uses: actions/checkout@v4');
expect(workflow).toContain('uses: actions/setup-node@v4');
expect(workflow).toContain('uses: pnpm/action-setup@v2');
expect(workflow).toContain('run: pnpm install --frozen-lockfile');
});
it('should include linting step when enabled', () => {
const config = {
...cicdGenerator['defaultConfig'],
runLinting: true
};
const workflow = cicdGenerator.generateGitHubActions(config, mockDeploymentConfig);
expect(workflow).toContain('Run linting');
expect(workflow).toContain('run: pnpm lint');
});
it('should include test step when enabled', () => {
const config = {
...cicdGenerator['defaultConfig'],
runTests: true
};
const workflow = cicdGenerator.generateGitHubActions(config, mockDeploymentConfig);
expect(workflow).toContain('Run tests');
expect(workflow).toContain('run: pnpm test');
expect(workflow).toContain('CI: true');
});
it('should include security scan step when enabled', () => {
const config = {
...cicdGenerator['defaultConfig'],
runSecurityScan: true
};
const workflow = cicdGenerator.generateGitHubActions(config, mockDeploymentConfig);
expect(workflow).toContain('Security scan');
expect(workflow).toContain('run: pnpm audit');
});
it('should include deployment job when autoDeploy is enabled', () => {
const config = {
...cicdGenerator['defaultConfig'],
autoDeploy: true,
secrets: ['DEPLOY_TOKEN', 'API_KEY']
};
const workflow = cicdGenerator.generateGitHubActions(config, mockDeploymentConfig);
expect(workflow).toContain('deploy:');
expect(workflow).toContain('needs: build');
expect(workflow).toContain('environment: production');
expect(workflow).toContain('DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}');
expect(workflow).toContain('API_KEY: ${{ secrets.API_KEY }}');
});
});
describe('generateGitLabCI', () => {
it('should generate complete GitLab CI configuration', () => {
const config = {
platform: 'gitlab' as const,
nodeVersion: '18',
pnpmVersion: '8',
testCommand: 'pnpm test',
buildCommand: 'pnpm build',
deployCommand: 'pnpm deploy',
cacheDependencies: true,
runTests: true,
runLinting: true,
runSecurityScan: true,
autoDeploy: false,
environments: ['production', 'staging'],
secrets: []
};
const gitlabCI = cicdGenerator.generateGitLabCI(config, mockDeploymentConfig);
expect(gitlabCI).toContain('# GitLab CI/CD Pipeline for OrdoJS');
expect(gitlabCI).toContain('image: node:18-alpine');
expect(gitlabCI).toContain('variables:');
expect(gitlabCI).toContain('PNPM_VERSION: "8"');
expect(gitlabCI).toContain('cache:');
expect(gitlabCI).toContain('paths:');
expect(gitlabCI).toContain('- node_modules/');
expect(gitlabCI).toContain('- .pnpm-store/');
expect(gitlabCI).toContain('stages:');
expect(gitlabCI).toContain('- test');
expect(gitlabCI).toContain('- build');
expect(gitlabCI).toContain('before_script:');
expect(gitlabCI).toContain('npm install -g pnpm@8');
expect(gitlabCI).toContain('pnpm install --frozen-lockfile');
});
it('should include linting in test stage', () => {
const config = {
...cicdGenerator['defaultConfig'],
runLinting: true
};
const gitlabCI = cicdGenerator.generateGitLabCI(config, mockDeploymentConfig);
expect(gitlabCI).toContain('test:');
expect(gitlabCI).toContain('stage: test');
expect(gitlabCI).toContain('- pnpm lint');
});
it('should include deployment stage when autoDeploy is enabled', () => {
const config = {
...cicdGenerator['defaultConfig'],
autoDeploy: true
};
const gitlabCI = cicdGenerator.generateGitLabCI(config, mockDeploymentConfig);
expect(gitlabCI).toContain('- deploy');
expect(gitlabCI).toContain('deploy:');
expect(gitlabCI).toContain('stage: deploy');
expect(gitlabCI).toContain('environment:');
expect(gitlabCI).toContain('name: production');
expect(gitlabCI).toContain('when: manual');
});
});
describe('generateJenkinsPipeline', () => {
it('should generate complete Jenkins pipeline', () => {
const config = {
platform: 'jenkins' as const,
nodeVersion: '18',
pnpmVersion: '8',
testCommand: 'pnpm test',
buildCommand: 'pnpm build',
deployCommand: 'pnpm deploy',
cacheDependencies: true,
runTests: true,
runLinting: true,
runSecurityScan: true,
autoDeploy: false,
environments: ['production', 'staging'],
secrets: []
};
const jenkinsfile = cicdGenerator.generateJenkinsPipeline(config, mockDeploymentConfig);
expect(jenkinsfile).toContain('pipeline {');
expect(jenkinsfile).toContain('agent {');
expect(jenkinsfile).toContain('docker {');
expect(jenkinsfile).toContain('image \'node:18-alpine\'');
expect(jenkinsfile).toContain('environment {');
expect(jenkinsfile).toContain('PNPM_VERSION = \'8\'');
expect(jenkinsfile).toContain('NODE_ENV = \'production\'');
expect(jenkinsfile).toContain('stages {');
expect(jenkinsfile).toContain('stage(\'Setup\')');
expect(jenkinsfile).toContain('stage(\'Build\')');
expect(jenkinsfile).toContain('sh \'npm install -g pnpm@8\'');
expect(jenkinsfile).toContain('sh \'pnpm install --frozen-lockfile\'');
});
it('should include linting stage when enabled', () => {
const config = {
...cicdGenerator['defaultConfig'],
runLinting: true
};
const jenkinsfile = cicdGenerator.generateJenkinsPipeline(config, mockDeploymentConfig);
expect(jenkinsfile).toContain('stage(\'Lint\')');
expect(jenkinsfile).toContain('sh \'pnpm lint\'');
});
it('should include test stage when enabled', () => {
const config = {
...cicdGenerator['defaultConfig'],
runTests: true
};
const jenkinsfile = cicdGenerator.generateJenkinsPipeline(config, mockDeploymentConfig);
expect(jenkinsfile).toContain('stage(\'Test\')');
expect(jenkinsfile).toContain('sh \'pnpm test\'');
expect(jenkinsfile).toContain('publishHTML');
});
it('should include security scan stage when enabled', () => {
const config = {
...cicdGenerator['defaultConfig'],
runSecurityScan: true
};
const jenkinsfile = cicdGenerator.generateJenkinsPipeline(config, mockDeploymentConfig);
expect(jenkinsfile).toContain('stage(\'Security Scan\')');
expect(jenkinsfile).toContain('sh \'pnpm audit\'');
});
it('should include deployment stage when autoDeploy is enabled', () => {
const config = {
...cicdGenerator['defaultConfig'],
autoDeploy: true
};
const jenkinsfile = cicdGenerator.generateJenkinsPipeline(config, mockDeploymentConfig);
expect(jenkinsfile).toContain('stage(\'Deploy\')');
expect(jenkinsfile).toContain('when {');
expect(jenkinsfile).toContain('branch \'main\'');
expect(jenkinsfile).toContain('sh \'pnpm deploy\'');
});
});
describe('error handling', () => {
it('should throw CLIError when pipeline generation fails', () => {
// Mock a scenario that would cause generation to fail
const invalidConfig = {
...mockDeploymentConfig,
outputDir: null as any
};
expect(() => {
cicdGenerator.generatePipeline(invalidConfig);
}).toThrow();
});
});
});