Skip to content
Open
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
41 changes: 41 additions & 0 deletions .github/workflows/unit-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,51 @@ on:
pull_request:
paths:
- 'template/nestJs/**'
- 'src/lib/**/*.ts'
workflow_dispatch:

jobs:
detect-changes:
runs-on: ubuntu-latest
outputs:
cli: ${{ steps.filter.outputs.cli }}
backend: ${{ steps.filter.outputs.backend }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Detect changed paths
uses: dorny/paths-filter@v3
id: filter
with:
filters: |
cli:
- 'src/lib/**/*.ts'
backend:
- 'template/nestJs/**'

Cli:
needs: detect-changes
if: needs.detect-changes.outputs.cli == 'true'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10
run_install: false
- name: Install depend
run: pnpm install --no-frozen-lockfile
- name: Run Init Command
run: pnpm test:cli
Backend:
needs: detect-changes
if: needs.detect-changes.outputs.backend == 'true'
runs-on: ubuntu-latest
permissions:
checks: write
Expand Down
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"test:unit:backend": "pnpm -F tinyui-nestjs-server test",
"test:cov:backend": "pnpm -F tinyui-nestjs-server test:cov",
"test:e2e": "playwright test",
"test:cli": "vitest",
"watch": "run-s clean build:main && run-p \"build:main -- -w\" ",
"cov": "run-s build test:unit cov:html && open-cli coverage/index.html",
"cov:html": "nyc report --reporter=html",
Expand Down Expand Up @@ -118,7 +119,8 @@
"tslint-config-airbnb": "^5.11.1",
"tslint-config-prettier": "^1.18.0",
"tslint-immutable": "^6.0.1",
"typescript": "^5.1.6"
"typescript": "^5.1.6",
"vitest": "^4.1.10"
},
"ava": {
"failFast": true,
Expand Down Expand Up @@ -166,4 +168,4 @@
]
}
]
}
}
877 changes: 688 additions & 189 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

34 changes: 34 additions & 0 deletions src/lib/__tests__/env-config.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { describe, it, expect } from 'vitest';
import { objToEnv } from '../init/env-config';

describe('objToEnv', () => {
it('should convert string values with single quotes', () => {
const result = objToEnv({ NAME: 'hello' });
expect(result).toBe("NAME = 'hello'");
});

it('should convert number values without quotes', () => {
const result = objToEnv({ PORT: 3306 });
expect(result).toBe('PORT = 3306');
});

it('should convert boolean values without quotes', () => {
const result = objToEnv({ ENABLED: true });
expect(result).toBe('ENABLED = true');
});

it('should convert false values without quotes', () => {
const result = objToEnv({ DISABLED: false });
expect(result).toBe('DISABLED = false');
});

it('should join multiple entries with newlines', () => {
const result = objToEnv({ HOST: 'localhost', PORT: 3306, SYNC: false });
expect(result).toBe("HOST = 'localhost'\nPORT = 3306\nSYNC = false");
});

it('should handle empty object', () => {
const result = objToEnv({});
expect(result).toBe('');
});
});
173 changes: 173 additions & 0 deletions src/lib/__tests__/package-json.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import * as path from 'path';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { BuildTool } from '../interfaces';

vi.mock('fs', () => ({
existsSync: vi.fn(),
rmSync: vi.fn(),
}));

vi.mock('@opentiny/cli-devkit', () => ({
logs: () => ({
error: vi.fn(),
success: vi.fn(),
info: vi.fn(),
}),
}));

import { existsSync, rmSync } from 'fs';
import { packageJsonProcess } from '../init/package-json';

const mockExistsSync = vi.mocked(existsSync);
const mockRmSync = vi.mocked(rmSync);

describe('packageJsonProcess', () => {
beforeEach(() => {
vi.clearAllMocks();
});

const basePackages = () => ({
name: 'test',
description: 'test project',
scripts: {
build: 'webpack --config webpack.config.js',
start: 'webpack-dev-server',
dev: 'vite',
'dev:wp': 'webpack-dev-server',
'build:wp': 'webpack build',
'dev:rp': 'rspack serve',
'build:rp': 'rspack build',
'dev:fr': 'farm',
'build:fr': 'farm build',
},
devDependencies: {
vite: '^5.0.0',
'@vitejs/plugin-vue': '^4.0.0',
'vite-plugin-mock': '^2.0.0',
webpack: '^5.0.0',
'webpack-cli': '^5.0.0',
'webpack-dev-server': '^4.0.0',
'@rspack/cli': '^0.3.0',
'@rspack/core': '^0.3.0',
'@farmfe/core': '^1.0.0',
'style-resources-loader': '^1.0.0',
'vue-style-loader': '^4.0.0',
},
dependencies: {
vue: '^3.0.0',
'style-resources-loader': '^1.0.0',
'vue-style-loader': '^4.0.0',
},
});

it('should remove obsolete scripts', () => {
const packages = basePackages();
packageJsonProcess(BuildTool.Vite, packages, '/fake/path');

expect(packages.scripts['dev:wp']).toBeUndefined();
expect(packages.scripts['build:wp']).toBeUndefined();
expect(packages.scripts['dev:rp']).toBeUndefined();
expect(packages.scripts['build:rp']).toBeUndefined();
expect(packages.scripts['dev']).toBeUndefined();
expect(packages.scripts['dev:fr']).toBeUndefined();
expect(packages.scripts['build:fr']).toBeUndefined();
});

it('should apply vite build tool scripts', () => {
const packages = basePackages();
packageJsonProcess(BuildTool.Vite, packages, '/fake/path');

expect(packages.scripts['build']).toBe('vite build --config ./config/vite.config.prod.ts');
expect(packages.scripts['start']).toBe('vite --config ./config/vite.config.dev.ts --port 3031');
});

it('should apply webpack build tool scripts', () => {
const packages = basePackages();
packageJsonProcess(BuildTool.Webpack, packages, '/fake/path');

expect(packages.scripts['build']).toBe('webpack --config webpack.config.js');
expect(packages.scripts['start']).toBe('webpack-dev-server --progress --config webpack.config.js');
});

it('should apply rspack build tool scripts', () => {
const packages = basePackages();
packageJsonProcess(BuildTool.Rspack, packages, '/fake/path');

expect(packages.scripts['build']).toBe('rspack build');
expect(packages.scripts['start']).toBe('rspack serve');
});

it('should apply farm build tool scripts', () => {
const packages = basePackages();
packageJsonProcess(BuildTool.Farm, packages, '/fake/path');

expect(packages.scripts['build']).toBe('farm build');
expect(packages.scripts['start']).toBe('farm');
});

it('should remove vite devDependencies when buildTool is webpack', () => {
const packages = basePackages();
packageJsonProcess(BuildTool.Webpack, packages, '/fake/path');

expect(packages.devDependencies['vite']).toBeUndefined();
expect(packages.devDependencies['@vitejs/plugin-vue']).toBeUndefined();
expect(packages.devDependencies['vite-plugin-mock']).toBeUndefined();
});

it('should remove webpack devDependencies when buildTool is vite', () => {
const packages = basePackages();
packageJsonProcess(BuildTool.Vite, packages, '/fake/path');

expect(packages.devDependencies['webpack']).toBeUndefined();
expect(packages.devDependencies['webpack-cli']).toBeUndefined();
expect(packages.devDependencies['webpack-dev-server']).toBeUndefined();
expect(packages.devDependencies['@rspack/cli']).toBeUndefined();
expect(packages.devDependencies['@rspack/core']).toBeUndefined();
expect(packages.devDependencies['@farmfe/core']).toBeUndefined();
});

it('should remove style-resources-loader and vue-style-loader from dependencies when buildTool is vite', () => {
const packages = basePackages();
packageJsonProcess(BuildTool.Vite, packages, '/fake/path');

expect(packages.dependencies['style-resources-loader']).toBeUndefined();
expect(packages.dependencies['vue-style-loader']).toBeUndefined();
});

it('should return a function that removes build config files', () => {
mockExistsSync.mockReturnValue(true);
const packages = basePackages();
const removeConfigFiles = packageJsonProcess(BuildTool.Vite, packages, '/fake/path');

removeConfigFiles();

expect(mockRmSync).toHaveBeenCalled();
const calls = mockRmSync.mock.calls.map((call) => call[0]);
expect(calls).toContain(path.join('/fake/path', 'webpack.config.js'));
expect(calls).toContain(path.join('/fake/path', 'rspack.config.js'));
expect(calls).toContain(path.join('/fake/path', 'farm.config.ts'));
});

it('should not remove build config files if they do not exist', () => {
mockExistsSync.mockReturnValue(false);
const packages = basePackages();
const removeConfigFiles = packageJsonProcess(BuildTool.Vite, packages, '/fake/path');

removeConfigFiles();

expect(mockRmSync).not.toHaveBeenCalled();
});

it('should handle regex pattern matching for devDependencies removal', () => {
const packages = basePackages();
packageJsonProcess(BuildTool.Rspack, packages, '/fake/path');

expect(packages.devDependencies['vite']).toBeUndefined();
expect(packages.devDependencies['@vitejs/plugin-vue']).toBeUndefined();
expect(packages.devDependencies['vite-plugin-mock']).toBeUndefined();
expect(packages.devDependencies['webpack']).toBeUndefined();
expect(packages.devDependencies['webpack-cli']).toBeUndefined();
expect(packages.devDependencies['webpack-dev-server']).toBeUndefined();
expect(packages.devDependencies['@farmfe/core']).toBeUndefined();
});
});
Loading
Loading