Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file

version: 2
updates:
- package-ecosystem: 'npm' # See documentation for possible values
directory: '/' # Location of package manifest
schedule:
interval: 'weekly'
24 changes: 24 additions & 0 deletions .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs

name: Run Tests

on:
push:
branches: ['main']
pull_request:
branches: ['main']

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: volta-cli/action@v4
- run: node -v
- run: yarn -v
- run: printenv
- run: ls -la
- run: yarn install
- run: yarn test
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,7 @@ dist-ssr
# Env
.env
.env.*

# Test coverage
coverage/
*.lcov
1 change: 1 addition & 0 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nodeLinker: node-modules
139 changes: 139 additions & 0 deletions TESTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# Testing Guide

This document explains how to run and maintain the test suite for the Gavant CLI tool.

## Test Setup

The project uses Jest as the testing framework with the following configuration:

- **Test Environment**: Node.js
- **Test Files**: Located in the `tests/` directory
- **Coverage Collection**: Enabled for `bin/`, `blueprints/`, and `utils/` directories

## Running Tests

### All Tests

```bash
npm test
```

### Tests with Coverage

```bash
npm run test:coverage
```

### Watch Mode (for development)

```bash
npm run test:watch
```

### Specific Test Files

```bash
npm test -- --testPathPattern="smoke"
npm test -- --testPathPattern="utils"
```

## Test Categories

### 1. Smoke Tests (`tests/smoke.test.js`)

Basic tests to ensure modules can be imported and core functionality exists.

### 2. Package Validation (`tests/package.test.js`)

Validates that `package.json` has all required fields and proper configuration.

### 3. Utility Tests (`tests/utils/node.test.js`)

Tests the Node.js version checking utility.

### 4. Blueprint Tests (`tests/blueprints/react-app.test.js`)

Tests the React app blueprint functionality with mocked dependencies.

### 5. CLI Interface Tests (`tests/bin/index.test.js`)

Tests the command-line interface argument parsing and command handling.

### 6. Integration Tests (`tests/integration/cli.integration.test.js`)

End-to-end tests that spawn the actual CLI process.

## Test Structure

```
tests/
├── setup.js # Global test setup
├── smoke.test.js # Basic functionality tests
├── package.test.js # Package.json validation
├── __mocks__/ # Mock helpers
├── utils/
│ └── node.test.js # Node version checker tests
├── blueprints/
│ └── react-app.test.js # Blueprint functionality tests
├── bin/
│ └── index.test.js # CLI interface tests
└── integration/
└── cli.integration.test.js # End-to-end tests
```

## Key Testing Features

### Mocking

The tests use extensive mocking to isolate functionality:

- File system operations
- Child process execution
- External dependencies (degit, ora, etc.)
- Console output

### Coverage

Current coverage targets:

- **Statements**: ~36%
- **Branches**: ~29%
- **Functions**: ~29%
- **Lines**: ~36%

### Test Utilities

- Custom mock setup for common dependencies
- Temporary directory management for integration tests
- Process mocking for version checking

## Adding New Tests

When adding new functionality:

1. **Unit Tests**: Create tests in the appropriate directory structure
2. **Integration Tests**: Add end-to-end scenarios to integration tests
3. **Mocking**: Use the existing mock patterns for external dependencies
4. **Coverage**: Ensure new code paths are covered

## Test Commands Summary

| Command | Description |
| ----------------------- | ------------------------------ |
| `npm test` | Run all tests |
| `npm run test:watch` | Run tests in watch mode |
| `npm run test:coverage` | Run tests with coverage report |

## Common Issues

1. **Integration Test Timeouts**: Some integration tests may take longer due to process spawning
2. **Mock Dependencies**: Complex dependencies like `degit` require careful mocking
3. **Process Mocking**: Testing process.exit requires proper setup/teardown

## Coverage Reports

Coverage reports are generated in the `coverage/` directory when running `npm run test:coverage`. The reports include:

- HTML report: `coverage/lcov-report/index.html`
- LCOV format: `coverage/lcov.info`
- Text summary in console output
2 changes: 1 addition & 1 deletion bin/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env node

const yargs = require('yargs/yargs');
const yargs = require('yargs');
const { hideBin } = require('yargs/helpers');
const chalk = require('chalk');

Expand Down
6 changes: 4 additions & 2 deletions blueprints/react-app.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,10 @@ async function installDependencies(appName, options) {

return runCommand(
async () => {
await exec(`cd ${rootDir} && yarn install`);
await exec(`cd ${appDir} && yarn install`);
// Increase maxBuffer to handle large yarn output
const execOptions = { maxBuffer: 1024 * 1024 * 10 }; // 10MB buffer
await exec(`cd ${rootDir} && yarn install`, execOptions);
await exec(`cd ${appDir} && yarn install`, execOptions);
},
{
loadingMsg: 'Installing dependencies, this could take awhile...',
Expand Down
21 changes: 20 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
],
"main": "./bin/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"release": "release-it"
},
"publishConfig": {
Expand All @@ -32,8 +34,25 @@
"yargs": "^17.7.2"
},
"devDependencies": {
"jest": "^29.7.0",
"release-it": "^16.2.1"
},
"jest": {
"testEnvironment": "node",
"collectCoverageFrom": [
"bin/**/*.js",
"blueprints/**/*.js",
"utils/**/*.js",
"!**/node_modules/**"
],
"testMatch": [
"**/__tests__/**/*.js",
"**/?(*.)+(spec|test).js"
],
"setupFilesAfterEnv": [
"<rootDir>/tests/setup.js"
]
},
"blueprints": {
"react-app": "gavant/react-app-blueprint"
}
Expand Down
29 changes: 29 additions & 0 deletions tests/__mocks__/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Mock implementations for testing
const mockSpinner = {
start: jest.fn(),
succeed: jest.fn(),
fail: jest.fn(),
text: '',
};

const mockOra = jest.fn(() => mockSpinner);

const mockDegitInstance = {
on: jest.fn(),
clone: jest.fn(),
};

const mockDegit = jest.fn(() => mockDegitInstance);

const mockReplace = jest.fn();

const mockExec = jest.fn();

module.exports = {
mockSpinner,
mockOra,
mockDegitInstance,
mockDegit,
mockReplace,
mockExec,
};
Loading