From 38fa88d5bb58f17e2ec19a48630a8a73a200693c Mon Sep 17 00:00:00 2001 From: Keshav Malik Date: Wed, 28 Jan 2026 13:54:41 +0530 Subject: [PATCH 01/12] chore: add vitest and test scripts --- package.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 1f45667..aa3dd51 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,9 @@ "type": "module", "main": "./bin/servergen.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "vitest run", + "test:watch": "vitest", + "test:coverage": "vitest run --coverage" }, "repository": { "type": "git", @@ -32,5 +34,8 @@ "chalk": "^5.4.1", "commander": "^14.0.2", "fs-extra": "^11.3.3" + }, + "devDependencies": { + "vitest": "^4.0.18" } } From 94b864d4270e8a607e78107d505cff4e8fbdc208 Mon Sep 17 00:00:00 2001 From: Keshav Malik Date: Wed, 28 Jan 2026 13:54:48 +0530 Subject: [PATCH 02/12] feat: add --skip-install CLI option --- bin/servergen.js | 5 ++++- lib/app_generator.js | 8 +++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/bin/servergen.js b/bin/servergen.js index 39cb81b..7a78433 100644 --- a/bin/servergen.js +++ b/bin/servergen.js @@ -32,6 +32,7 @@ program .option('-v --view ', 'Name of View Engine: Pug | Jade | EJS | HBS') .option('--db', 'Install Mongoose & the Folder Directory for it') .option('-p, --port ', 'Set default port for the app', '3000') + .option('--skip-install', 'Skip npm install step') .option('--debug', 'Enable debug logging') .parse(process.argv); @@ -48,8 +49,9 @@ handleValidationErrors(validationResult); const appName = fileName.cleanAppName(options.name); const port = parseInt(options.port, 10) || 3000; +const skipInstall = options.skipInstall || false; -logger.debug('Parsed configuration', { appName, port, framework: options.framework }); +logger.debug('Parsed configuration', { appName, port, framework: options.framework, skipInstall }); /** * Main function to run the application generator. @@ -62,6 +64,7 @@ const main = async () => { view: options.view, db: options.db, port, + skipInstall, config, }, { diff --git a/lib/app_generator.js b/lib/app_generator.js index db2e604..eaf08b2 100644 --- a/lib/app_generator.js +++ b/lib/app_generator.js @@ -24,6 +24,7 @@ class AppGenerator { * @param {string|null} options.view - The view engine name. * @param {boolean} options.db - Whether to include database configuration. * @param {number} options.port - The port number for the app. + * @param {boolean} options.skipInstall - Whether to skip npm install. * @param {Object} options.config - Configuration object from lib/config. * @param {Object} dependencies - Injected dependencies. * @param {Object} dependencies.fsHelper - File system helper module. @@ -37,6 +38,7 @@ class AppGenerator { this.view = options.view; this.db = options.db; this.port = options.port || 3000; + this.skipInstall = options.skipInstall || false; this.config = options.config; this.fsHelper = dependencies.fsHelper; @@ -59,6 +61,7 @@ class AppGenerator { appName: this.appName, framework: this.framework, port: this.port, + skipInstall: this.skipInstall, }); this.createAppFolder(); @@ -67,7 +70,10 @@ class AppGenerator { this.setupViews(); this.setupDatabase(); this.addSupportFiles(); - await this.installDependencies(); + + if (!this.skipInstall) { + await this.installDependencies(); + } this.logger?.success(`Application ${this.appName} created successfully`); } From f56d95b7e821f856dfc68c422fac00724c279c5b Mon Sep 17 00:00:00 2001 From: Keshav Malik Date: Wed, 28 Jan 2026 13:54:53 +0530 Subject: [PATCH 03/12] test: add fileName unit tests --- tests/fileName.test.js | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 tests/fileName.test.js diff --git a/tests/fileName.test.js b/tests/fileName.test.js new file mode 100644 index 0000000..dc56905 --- /dev/null +++ b/tests/fileName.test.js @@ -0,0 +1,32 @@ +import { describe, it, expect } from 'vitest'; +import { cleanAppName } from '../lib/fileName.js'; + +describe('cleanAppName', () => { + it('converts to lowercase', () => { + expect(cleanAppName('MyApp')).toBe('myapp'); + }); + + it('removes spaces', () => { + expect(cleanAppName('my app')).toBe('myapp'); + }); + + it('removes special characters', () => { + expect(cleanAppName('my-app_test!@#')).toBe('myapptest'); + }); + + it('removes hyphens and underscores', () => { + expect(cleanAppName('my-app_name')).toBe('myappname'); + }); + + it('handles numbers', () => { + expect(cleanAppName('app123')).toBe('app123'); + }); + + it('handles empty string', () => { + expect(cleanAppName('')).toBe(''); + }); + + it('handles only special characters', () => { + expect(cleanAppName('---___!!!')).toBe(''); + }); +}); From f82155eff1bebdb77bb363c46f863f9fbd77a589 Mon Sep 17 00:00:00 2001 From: Keshav Malik Date: Wed, 28 Jan 2026 13:54:58 +0530 Subject: [PATCH 04/12] test: add validator unit tests --- tests/validator.test.js | 76 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 tests/validator.test.js diff --git a/tests/validator.test.js b/tests/validator.test.js new file mode 100644 index 0000000..a297da9 --- /dev/null +++ b/tests/validator.test.js @@ -0,0 +1,76 @@ +import { describe, it, expect } from 'vitest'; +import { validateOptions } from '../lib/validator.js'; + +const validationRules = { + frameworks: ['node', 'express'], + views: ['ejs', 'jade', 'pug', 'hbs'], +}; + +describe('validateOptions', () => { + describe('framework validation', () => { + it('accepts valid framework: express', () => { + const result = validateOptions({ framework: 'express' }, validationRules); + expect(result.isValid).toBe(true); + expect(result.errors).toHaveLength(0); + }); + + it('accepts valid framework: node', () => { + const result = validateOptions({ framework: 'node' }, validationRules); + expect(result.isValid).toBe(true); + }); + + it('rejects invalid framework', () => { + const result = validateOptions({ framework: 'invalid' }, validationRules); + expect(result.isValid).toBe(false); + expect(result.errors).toHaveLength(1); + expect(result.errors[0]).toContain('Invalid framework'); + }); + + it('passes when no framework specified', () => { + const result = validateOptions({}, validationRules); + expect(result.isValid).toBe(true); + }); + }); + + describe('view validation', () => { + it('accepts valid view: ejs', () => { + const result = validateOptions({ view: 'ejs' }, validationRules); + expect(result.isValid).toBe(true); + }); + + it('accepts valid view: pug', () => { + const result = validateOptions({ view: 'pug' }, validationRules); + expect(result.isValid).toBe(true); + }); + + it('rejects invalid view', () => { + const result = validateOptions({ view: 'invalid' }, validationRules); + expect(result.isValid).toBe(false); + expect(result.errors[0]).toContain('Invalid view engine'); + }); + + it('passes when no view specified', () => { + const result = validateOptions({}, validationRules); + expect(result.isValid).toBe(true); + }); + }); + + describe('combined validation', () => { + it('validates both framework and view', () => { + const result = validateOptions( + { framework: 'express', view: 'ejs' }, + validationRules + ); + expect(result.isValid).toBe(true); + }); + + it('returns multiple errors for multiple invalid options', () => { + const result = validateOptions( + { framework: 'bad', view: 'worse' }, + validationRules + ); + expect(result.isValid).toBe(false); + expect(result.errors).toHaveLength(2); + }); + }); +}); From 46a61bdfa7047b3345adf185f6815d405d7bd0cf Mon Sep 17 00:00:00 2001 From: Keshav Malik Date: Wed, 28 Jan 2026 13:55:03 +0530 Subject: [PATCH 05/12] test: add config unit tests --- tests/config.test.js | 72 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 tests/config.test.js diff --git a/tests/config.test.js b/tests/config.test.js new file mode 100644 index 0000000..9ca76d5 --- /dev/null +++ b/tests/config.test.js @@ -0,0 +1,72 @@ +import { describe, it, expect } from 'vitest'; +import { getConfig } from '../lib/config.js'; +import path from 'path'; + +describe('getConfig', () => { + const baseDir = '/test/base'; + const cwd = '/test/cwd'; + + it('returns configuration object', () => { + const config = getConfig(baseDir, cwd); + expect(config).toBeDefined(); + expect(config.paths).toBeDefined(); + expect(config.validation).toBeDefined(); + expect(config.defaults).toBeDefined(); + }); + + describe('paths', () => { + it('sets express template path', () => { + const config = getConfig(baseDir, cwd); + expect(config.paths.templates.express).toBe( + path.join(baseDir, '..', 'templates', 'express') + ); + }); + + it('sets node template path', () => { + const config = getConfig(baseDir, cwd); + expect(config.paths.templates.node).toBe( + path.join(baseDir, '..', 'templates', 'node') + ); + }); + + it('sets views path', () => { + const config = getConfig(baseDir, cwd); + expect(config.paths.templates.views).toBe( + path.join(baseDir, '..', 'templates', 'express', 'views') + ); + }); + + it('sets cwd correctly', () => { + const config = getConfig(baseDir, cwd); + expect(config.paths.cwd).toBe(cwd); + }); + }); + + describe('validation rules', () => { + it('includes valid frameworks', () => { + const config = getConfig(baseDir, cwd); + expect(config.validation.frameworks).toContain('node'); + expect(config.validation.frameworks).toContain('express'); + }); + + it('includes valid views', () => { + const config = getConfig(baseDir, cwd); + expect(config.validation.views).toContain('ejs'); + expect(config.validation.views).toContain('pug'); + expect(config.validation.views).toContain('jade'); + expect(config.validation.views).toContain('hbs'); + }); + }); + + describe('defaults', () => { + it('sets default framework to express', () => { + const config = getConfig(baseDir, cwd); + expect(config.defaults.framework).toBe('express'); + }); + + it('sets default port to 3000', () => { + const config = getConfig(baseDir, cwd); + expect(config.defaults.port).toBe(3000); + }); + }); +}); From e66da31db2eb251d0c45da66a09fbaa3aab327cd Mon Sep 17 00:00:00 2001 From: Keshav Malik Date: Wed, 28 Jan 2026 13:55:10 +0530 Subject: [PATCH 06/12] test: add constants unit tests --- tests/constants.test.js | 76 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 tests/constants.test.js diff --git a/tests/constants.test.js b/tests/constants.test.js new file mode 100644 index 0000000..ec5e16e --- /dev/null +++ b/tests/constants.test.js @@ -0,0 +1,76 @@ +import { describe, it, expect } from 'vitest'; +import { + LOG_LEVELS, + VIEW_ENGINES, + VALID_VIEWS, + DEPENDENCY_VERSIONS, +} from '../lib/constants.js'; + +describe('constants', () => { + describe('LOG_LEVELS', () => { + it('defines ERROR as 0', () => { + expect(LOG_LEVELS.ERROR).toBe(0); + }); + + it('defines WARN as 1', () => { + expect(LOG_LEVELS.WARN).toBe(1); + }); + + it('defines INFO as 2', () => { + expect(LOG_LEVELS.INFO).toBe(2); + }); + + it('defines DEBUG as 3', () => { + expect(LOG_LEVELS.DEBUG).toBe(3); + }); + }); + + describe('VIEW_ENGINES', () => { + it('includes ejs', () => { + expect(VIEW_ENGINES.ejs).toBeDefined(); + }); + + it('includes pug', () => { + expect(VIEW_ENGINES.pug).toBeDefined(); + }); + + it('includes jade', () => { + expect(VIEW_ENGINES.jade).toBeDefined(); + }); + + it('includes hbs', () => { + expect(VIEW_ENGINES.hbs).toBeDefined(); + }); + }); + + describe('VALID_VIEWS', () => { + it('is array of view engine names', () => { + expect(VALID_VIEWS).toContain('ejs'); + expect(VALID_VIEWS).toContain('pug'); + expect(VALID_VIEWS).toContain('jade'); + expect(VALID_VIEWS).toContain('hbs'); + }); + + it('matches VIEW_ENGINES keys', () => { + expect(VALID_VIEWS).toEqual(Object.keys(VIEW_ENGINES)); + }); + }); + + describe('DEPENDENCY_VERSIONS', () => { + it('includes nodemon', () => { + expect(DEPENDENCY_VERSIONS.nodemon).toBeDefined(); + }); + + it('includes cors', () => { + expect(DEPENDENCY_VERSIONS.cors).toBeDefined(); + }); + + it('includes express', () => { + expect(DEPENDENCY_VERSIONS.express).toBeDefined(); + }); + + it('includes mongoose', () => { + expect(DEPENDENCY_VERSIONS.mongoose).toBeDefined(); + }); + }); +}); From 10854dd48c5432375bad10f27fd8d77d11ef196c Mon Sep 17 00:00:00 2001 From: Keshav Malik Date: Wed, 28 Jan 2026 13:55:17 +0530 Subject: [PATCH 07/12] test: add build_helper unit tests --- tests/build_helper.test.js | 68 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 tests/build_helper.test.js diff --git a/tests/build_helper.test.js b/tests/build_helper.test.js new file mode 100644 index 0000000..33b9dc4 --- /dev/null +++ b/tests/build_helper.test.js @@ -0,0 +1,68 @@ +import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; +import fs from 'fs-extra'; +import path from 'path'; +import { fileURLToPath } from 'url'; +import * as buildHelper from '../lib/build_helper.js'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const testDir = path.join(__dirname, '.test-output'); + +describe('build_helper', () => { + beforeEach(() => { + fs.ensureDirSync(testDir); + }); + + afterEach(() => { + fs.removeSync(testDir); + }); + + describe('createDir', () => { + it('creates a directory inside app directory', () => { + buildHelper.createDir(testDir, 'controllers'); + const dirPath = path.join(testDir, 'controllers'); + expect(fs.existsSync(dirPath)).toBe(true); + }); + + it('creates nested directory structure', () => { + buildHelper.createDir(testDir, 'config'); + buildHelper.createDir(testDir, 'routes'); + expect(fs.existsSync(path.join(testDir, 'config'))).toBe(true); + expect(fs.existsSync(path.join(testDir, 'routes'))).toBe(true); + }); + }); + + describe('buildFilewithContents', () => { + it('copies file content to destination', () => { + const sourceFile = path.join(testDir, 'source.txt'); + fs.writeFileSync(sourceFile, 'test content'); + + buildHelper.buildFilewithContents(sourceFile, testDir, 'dest.txt'); + + const destContent = fs.readFileSync(path.join(testDir, 'dest.txt'), 'utf-8'); + expect(destContent).toBe('test content'); + }); + }); + + describe('buildFolderforApp', () => { + it('creates a new folder', () => { + const newFolder = path.join(testDir, 'new-app'); + buildHelper.buildFolderforApp(newFolder); + expect(fs.existsSync(newFolder)).toBe(true); + }); + + it('exits if folder already exists', () => { + const existingFolder = path.join(testDir, 'existing'); + fs.mkdirSync(existingFolder); + + const mockExit = vi.spyOn(process, 'exit').mockImplementation(() => { + throw new Error('process.exit called'); + }); + + expect(() => { + buildHelper.buildFolderforApp(existingFolder); + }).toThrow('process.exit called'); + + mockExit.mockRestore(); + }); + }); +}); From d71ff073cc2c4631856bb29c9b794e02cddcf742 Mon Sep 17 00:00:00 2001 From: Keshav Malik Date: Wed, 28 Jan 2026 13:55:22 +0530 Subject: [PATCH 08/12] test: add CLI integration tests --- tests/integration.test.js | 136 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 tests/integration.test.js diff --git a/tests/integration.test.js b/tests/integration.test.js new file mode 100644 index 0000000..e1ead2f --- /dev/null +++ b/tests/integration.test.js @@ -0,0 +1,136 @@ +import { describe, it, expect, beforeEach, afterEach } from 'vitest'; +import fs from 'fs-extra'; +import path from 'path'; +import { fileURLToPath } from 'url'; +import { execSync } from 'child_process'; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const projectRoot = path.join(__dirname, '..'); +const testOutput = path.join(__dirname, '.integration-output'); + +describe('CLI Integration', () => { + beforeEach(() => { + fs.ensureDirSync(testOutput); + }); + + afterEach(() => { + fs.removeSync(testOutput); + }); + + const runCLI = (args) => { + const cmd = `node ${path.join(projectRoot, 'bin', 'servergen.js')} ${args}`; + return execSync(cmd, { + cwd: testOutput, + encoding: 'utf-8', + timeout: 60000, + }); + }; + + describe('help command', () => { + it('displays help information', () => { + const output = runCLI('--help'); + expect(output).toContain('Usage:'); + expect(output).toContain('-n, --name'); + expect(output).toContain('-f, --framework'); + }); + + it('displays version', () => { + const output = runCLI('--version'); + expect(output).toMatch(/\d+\.\d+\.\d+/); + }); + }); + + describe('Express app generation', () => { + it('generates Express app with correct structure', () => { + runCLI('-n testapp -f express --skip-install'); + + const appDir = path.join(testOutput, 'testapp'); + expect(fs.existsSync(appDir)).toBe(true); + expect(fs.existsSync(path.join(appDir, 'index.js'))).toBe(true); + expect(fs.existsSync(path.join(appDir, 'package.json'))).toBe(true); + expect(fs.existsSync(path.join(appDir, 'routes'))).toBe(true); + expect(fs.existsSync(path.join(appDir, 'controllers'))).toBe(true); + expect(fs.existsSync(path.join(appDir, 'model'))).toBe(true); + }); + + it('generates package.json with express dependency', () => { + runCLI('-n expresstest -f express --skip-install'); + + const pkgPath = path.join(testOutput, 'expresstest', 'package.json'); + const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')); + + expect(pkg.name).toBe('expresstest'); + expect(pkg.dependencies.express).toBeDefined(); + expect(pkg.dependencies.nodemon).toBeDefined(); + expect(pkg.dependencies.cors).toBeDefined(); + }); + + it('includes view engine when specified', () => { + runCLI('-n viewtest -f express -v ejs --skip-install'); + + const pkgPath = path.join(testOutput, 'viewtest', 'package.json'); + const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')); + + expect(pkg.dependencies.ejs).toBeDefined(); + }); + + it('includes mongoose when --db flag used', () => { + runCLI('-n dbtest -f express --db --skip-install'); + + const pkgPath = path.join(testOutput, 'dbtest', 'package.json'); + const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')); + + expect(pkg.dependencies.mongoose).toBeDefined(); + expect(fs.existsSync(path.join(testOutput, 'dbtest', 'config'))).toBe(true); + }); + }); + + describe('Node app generation', () => { + it('generates Node app with correct structure', () => { + runCLI('-n nodetest -f node --skip-install'); + + const appDir = path.join(testOutput, 'nodetest'); + expect(fs.existsSync(appDir)).toBe(true); + expect(fs.existsSync(path.join(appDir, 'index.js'))).toBe(true); + expect(fs.existsSync(path.join(appDir, 'package.json'))).toBe(true); + }); + + it('generates package.json without express dependency', () => { + runCLI('-n purenode -f node --skip-install'); + + const pkgPath = path.join(testOutput, 'purenode', 'package.json'); + const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8')); + + expect(pkg.dependencies.express).toBeUndefined(); + expect(pkg.dependencies.nodemon).toBeDefined(); + }); + }); + + describe('support files', () => { + it('includes .gitignore', () => { + runCLI('-n gittest -f express --skip-install'); + expect(fs.existsSync(path.join(testOutput, 'gittest', '.gitignore'))).toBe(true); + }); + + it('includes Dockerfile', () => { + runCLI('-n dockertest -f express --skip-install'); + expect(fs.existsSync(path.join(testOutput, 'dockertest', 'Dockerfile'))).toBe(true); + }); + + it('includes .dockerignore', () => { + runCLI('-n dockertest2 -f express --skip-install'); + expect(fs.existsSync(path.join(testOutput, 'dockertest2', '.dockerignore'))).toBe(true); + }); + }); + + describe('custom port', () => { + it('configures custom port in index.js', () => { + runCLI('-n porttest -f express -p 8080 --skip-install'); + + const indexPath = path.join(testOutput, 'porttest', 'index.js'); + const content = fs.readFileSync(indexPath, 'utf-8'); + + expect(content).toContain('8080'); + }); + }); +}); From 26fca503453aa6839698750c84eb0d77aab89d99 Mon Sep 17 00:00:00 2001 From: Keshav Malik Date: Wed, 28 Jan 2026 13:55:29 +0530 Subject: [PATCH 09/12] ci: add GitHub Actions workflow for tests --- .github/workflows/ci.yml | 48 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..1a936a8 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,48 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + test: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [18, 20, 22] + + steps: + - uses: actions/checkout@v4 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Run tests + run: npm test + + lint: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Use Node.js 20 + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Check syntax + run: node --check bin/servergen.js From 1f32c46e24bef4e1bd37890ee9a5342aa5afbe70 Mon Sep 17 00:00:00 2001 From: Keshav Malik Date: Wed, 28 Jan 2026 14:14:17 +0530 Subject: [PATCH 10/12] fix: use npm install instead of npm ci, remove lint job --- .github/workflows/ci.yml | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1a936a8..5fa595f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,28 +21,9 @@ jobs: uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} - cache: 'npm' - name: Install dependencies - run: npm ci + run: npm install - name: Run tests run: npm test - - lint: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Use Node.js 20 - uses: actions/setup-node@v4 - with: - node-version: 20 - cache: 'npm' - - - name: Install dependencies - run: npm ci - - - name: Check syntax - run: node --check bin/servergen.js From 7989909dfeb1e9a65e36d0d22bdba9da0a34f377 Mon Sep 17 00:00:00 2001 From: Keshav Malik Date: Wed, 28 Jan 2026 14:14:23 +0530 Subject: [PATCH 11/12] feat: add vitest config with coverage thresholds --- vitest.config.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 vitest.config.js diff --git a/vitest.config.js b/vitest.config.js new file mode 100644 index 0000000..b0b9d4b --- /dev/null +++ b/vitest.config.js @@ -0,0 +1,18 @@ +import { defineConfig } from 'vitest/config'; + +export default defineConfig({ + test: { + include: ['tests/unit/**/*.test.js', 'tests/integration/**/*.test.js'], + coverage: { + provider: 'v8', + reporter: ['text', 'html'], + exclude: ['tests/**', 'node_modules/**'], + thresholds: { + statements: 70, + branches: 60, + functions: 70, + lines: 70, + }, + }, + }, +}); From 0f3abdae70f0cb320eb882885e42463fa614b06b Mon Sep 17 00:00:00 2001 From: Keshav Malik Date: Wed, 28 Jan 2026 14:14:28 +0530 Subject: [PATCH 12/12] refactor: split tests into unit and integration directories --- tests/{ => integration}/integration.test.js | 2 +- tests/{ => unit}/build_helper.test.js | 2 +- tests/{ => unit}/config.test.js | 2 +- tests/{ => unit}/constants.test.js | 2 +- tests/{ => unit}/fileName.test.js | 2 +- tests/{ => unit}/validator.test.js | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) rename tests/{ => integration}/integration.test.js (98%) rename tests/{ => unit}/build_helper.test.js (97%) rename tests/{ => unit}/config.test.js (97%) rename tests/{ => unit}/constants.test.js (98%) rename tests/{ => unit}/fileName.test.js (93%) rename tests/{ => unit}/validator.test.js (97%) diff --git a/tests/integration.test.js b/tests/integration/integration.test.js similarity index 98% rename from tests/integration.test.js rename to tests/integration/integration.test.js index e1ead2f..25942f0 100644 --- a/tests/integration.test.js +++ b/tests/integration/integration.test.js @@ -5,7 +5,7 @@ import { fileURLToPath } from 'url'; import { execSync } from 'child_process'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); -const projectRoot = path.join(__dirname, '..'); +const projectRoot = path.join(__dirname, '..', '..'); const testOutput = path.join(__dirname, '.integration-output'); describe('CLI Integration', () => { diff --git a/tests/build_helper.test.js b/tests/unit/build_helper.test.js similarity index 97% rename from tests/build_helper.test.js rename to tests/unit/build_helper.test.js index 33b9dc4..9d7cb97 100644 --- a/tests/build_helper.test.js +++ b/tests/unit/build_helper.test.js @@ -2,7 +2,7 @@ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import fs from 'fs-extra'; import path from 'path'; import { fileURLToPath } from 'url'; -import * as buildHelper from '../lib/build_helper.js'; +import * as buildHelper from '../../lib/build_helper.js'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const testDir = path.join(__dirname, '.test-output'); diff --git a/tests/config.test.js b/tests/unit/config.test.js similarity index 97% rename from tests/config.test.js rename to tests/unit/config.test.js index 9ca76d5..8dac9b5 100644 --- a/tests/config.test.js +++ b/tests/unit/config.test.js @@ -1,5 +1,5 @@ import { describe, it, expect } from 'vitest'; -import { getConfig } from '../lib/config.js'; +import { getConfig } from '../../lib/config.js'; import path from 'path'; describe('getConfig', () => { diff --git a/tests/constants.test.js b/tests/unit/constants.test.js similarity index 98% rename from tests/constants.test.js rename to tests/unit/constants.test.js index ec5e16e..1d17006 100644 --- a/tests/constants.test.js +++ b/tests/unit/constants.test.js @@ -4,7 +4,7 @@ import { VIEW_ENGINES, VALID_VIEWS, DEPENDENCY_VERSIONS, -} from '../lib/constants.js'; +} from '../../lib/constants.js'; describe('constants', () => { describe('LOG_LEVELS', () => { diff --git a/tests/fileName.test.js b/tests/unit/fileName.test.js similarity index 93% rename from tests/fileName.test.js rename to tests/unit/fileName.test.js index dc56905..6660f77 100644 --- a/tests/fileName.test.js +++ b/tests/unit/fileName.test.js @@ -1,5 +1,5 @@ import { describe, it, expect } from 'vitest'; -import { cleanAppName } from '../lib/fileName.js'; +import { cleanAppName } from '../../lib/fileName.js'; describe('cleanAppName', () => { it('converts to lowercase', () => { diff --git a/tests/validator.test.js b/tests/unit/validator.test.js similarity index 97% rename from tests/validator.test.js rename to tests/unit/validator.test.js index a297da9..73ea7ac 100644 --- a/tests/validator.test.js +++ b/tests/unit/validator.test.js @@ -1,5 +1,5 @@ import { describe, it, expect } from 'vitest'; -import { validateOptions } from '../lib/validator.js'; +import { validateOptions } from '../../lib/validator.js'; const validationRules = { frameworks: ['node', 'express'],