diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 019aa15..5721024 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -14,6 +14,9 @@ jobs:
test:
runs-on: ubuntu-latest
steps:
+ -
+ name: Set up Docker Compose
+ uses: docker/setup-compose-action@v1
- uses: actions/checkout@v4
- run: npm ci
- run: npm run build
diff --git a/README.md b/README.md
index 6bc26bc..8c0dd6b 100644
--- a/README.md
+++ b/README.md
@@ -62,6 +62,7 @@ The projects that can be added to a Monux monorepo also provide a lot of functio
- [Angular website](#angular-website)
- [Angular library](#angular-library)
- [LoopBack](#loopback)
+ - [Nest](#nest)
- [Typescript library](#typescript-library)
- [Wordpress](#wordpress)
- [Add projects manually](#add-projects-manually)
@@ -301,13 +302,14 @@ They will give you a nice overview of all monorepos on your machine and their re
## Angular website
## Angular library
## LoopBack
+## Nest
## Typescript library
## Wordpress
## Add projects manually
One of the reasons that Monux was created was the amount of abstraction layers added by tools like Nx.
The magic was really cool as long as everything worked, but made debugging issues much harder.
-For that reason, Monux is simply using npm workspaces under the hood and none of its magic is hidden from the developer, besides maybe validating and creating environment files, which is explained in detail in [Handling environment variables](#handling-environment-variables).
+For that reason, Monux is simply using npm workspaces under the hood and none of its magic is hidden from the developer. Besides maybe validating and creating environment files, which is explained in detail in [Handling environment variables](#handling-environment-variables).
Because of that it should be fairly simple to add any project/framework/library manually by just taking a look at existing projects.
diff --git a/jest.config.mjs b/jest.config.mjs
index 38e6a21..b13d51f 100644
--- a/jest.config.mjs
+++ b/jest.config.mjs
@@ -12,6 +12,7 @@ const config = {
modulePathIgnorePatterns: ['tmp'],
// coverage
collectCoverage: true,
+ coverageProvider: 'v8',
coverageDirectory: '/__testing__/coverage',
coveragePathIgnorePatterns: [
'/node_modules/',
diff --git a/package.json b/package.json
index 045f9c5..82a3277 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "monux-cli",
- "version": "2.2.2",
+ "version": "2.2.3",
"license": "MIT",
"main": "index.js",
"engines": {
@@ -33,10 +33,10 @@
"start": "npm run build && cd sandbox && node ../dist/index.js",
"build": "tsc",
"clear": "rm -rf sandbox && mkdir sandbox && npm run start i",
- "test": "node --max_old_space_size=4096 ./node_modules/jest/bin/jest.js",
+ "test": "jest --runInBand",
"lint": "eslint . --max-warnings=0",
"lint:fix": "eslint . --max-warnings=0 --fix",
- "prepublishOnly": "npm i && npm run lint && npm run build"
+ "prepublishOnly": "npm i && npm run build"
},
"dependencies": {
"chalk": "^4.1.2",
diff --git a/src/__testing__/mock/constants.ts b/src/__testing__/mock/constants.ts
index e403382..eee3779 100644
--- a/src/__testing__/mock/constants.ts
+++ b/src/__testing__/mock/constants.ts
@@ -1,71 +1,53 @@
-import { ANGULAR_JSON_FILE_NAME, ANGULAR_ROUTES_FILE_NAME, APP_CONFIG_FILE_NAME, APPS_DIRECTORY_NAME, DEV_DOCKER_COMPOSE_FILE_NAME, PROD_DOCKER_COMPOSE_FILE_NAME, ENV_FILE_NAME, ENVIRONMENT_MODEL_TS_FILE_NAME, ENVIRONMENT_TS_FILE_NAME, ESLINT_CONFIG_FILE_NAME, GLOBAL_ENVIRONMENT_MODEL_FILE_NAME, LIBS_DIRECTORY_NAME, PACKAGE_JSON_FILE_NAME, LOCAL_DOCKER_COMPOSE_FILE_NAME } from '../../constants';
+/* eslint-disable jsdoc/require-jsdoc */
+import { ANGULAR_JSON_FILE_NAME, ANGULAR_ROUTES_FILE_NAME, APP_CONFIG_FILE_NAME, APPS_DIRECTORY_NAME, DEV_DOCKER_COMPOSE_FILE_NAME, PROD_DOCKER_COMPOSE_FILE_NAME, ENV_FILE_NAME, ENVIRONMENT_MODEL_TS_FILE_NAME, ENVIRONMENT_TS_FILE_NAME, ESLINT_CONFIG_FILE_NAME, GLOBAL_ENVIRONMENT_MODEL_FILE_NAME, LIBS_DIRECTORY_NAME, PACKAGE_JSON_FILE_NAME, LOCAL_DOCKER_COMPOSE_FILE_NAME, WORKSPACE_FILE_NAME, BASE_TS_CONFIG_FILE_NAME } from '../../constants';
import { OmitStrict } from '../../types';
import { getPath, Path } from '../../utilities';
-// eslint-disable-next-line jsdoc/require-jsdoc
+export const MAX_ADD_TIME: number = 60000;
+
+export const MAX_GEN_CODE_TIME: number = 10000;
+
+export const MAX_FAST_TIME: number = 300;
+
+export const MAX_INSTANT_TIME: number = 100;
+
export type MockConstants = {
- // eslint-disable-next-line jsdoc/require-jsdoc
readonly PROJECT_DIR: Path,
- // eslint-disable-next-line jsdoc/require-jsdoc
readonly APPS_DIR: Path,
- // eslint-disable-next-line jsdoc/require-jsdoc
readonly LIBS_DIR: Path,
- // eslint-disable-next-line jsdoc/require-jsdoc
readonly DOCKER_COMPOSE_YAML: Path,
- // eslint-disable-next-line jsdoc/require-jsdoc
readonly DEV_DOCKER_COMPOSE_YAML: Path,
- // eslint-disable-next-line jsdoc/require-jsdoc
readonly LOCAL_DOCKER_COMPOSE_YAML: Path,
- // eslint-disable-next-line jsdoc/require-jsdoc
readonly ANGULAR_ESLINT_CONFIG_MJS: Path,
- // eslint-disable-next-line jsdoc/require-jsdoc
readonly ANGULAR_PACKAGE_JSON: Path,
- // eslint-disable-next-line jsdoc/require-jsdoc
readonly ANGULAR_APP_NAME: string,
- // eslint-disable-next-line jsdoc/require-jsdoc
readonly ANGULAR_APP_DIR: Path,
- // eslint-disable-next-line jsdoc/require-jsdoc
readonly ANGULAR_APP_COMPONENT_TS: Path,
- // eslint-disable-next-line jsdoc/require-jsdoc
readonly ANGULAR_APP_COMPONENT_HTML: Path,
- // eslint-disable-next-line jsdoc/require-jsdoc
readonly ANGULAR_APP_ROUTES_TS: Path,
- // eslint-disable-next-line jsdoc/require-jsdoc
readonly ANGULAR_ROUTES_TS: Path,
- // eslint-disable-next-line jsdoc/require-jsdoc
readonly ANGULAR_APP_CONFIG_TS: Path,
- // eslint-disable-next-line jsdoc/require-jsdoc
readonly ANGULAR_JSON: Path,
- // eslint-disable-next-line jsdoc/require-jsdoc
readonly ANGULAR_ENVIRONMENT_MODEL: Path,
- // eslint-disable-next-line jsdoc/require-jsdoc
readonly ANGULAR_ENVIRONMENT: Path,
- // eslint-disable-next-line jsdoc/require-jsdoc
readonly TS_LIBRARY_DIR: Path,
- // eslint-disable-next-line jsdoc/require-jsdoc
readonly TS_LIBRARY_SCOPE: string,
- // eslint-disable-next-line jsdoc/require-jsdoc
readonly TS_LIBRARY_PACKAGE_JSON: Path,
- // eslint-disable-next-line jsdoc/require-jsdoc
readonly ROOT_PACKAGE_JSON: Path,
- // eslint-disable-next-line jsdoc/require-jsdoc
readonly TS_LIBRARY_NAME: string,
- // eslint-disable-next-line jsdoc/require-jsdoc
readonly ENV: Path,
- // eslint-disable-next-line jsdoc/require-jsdoc
readonly GLOBAL_ENV_MODEL: Path,
- // eslint-disable-next-line jsdoc/require-jsdoc
- readonly GITHUB_WORKFLOW_DIR: Path
+ readonly GITHUB_WORKFLOW_DIR: Path,
+ readonly WORKSPACE_JSON: Path,
+ readonly BASE_TS_CONFIG_JSON: Path
};
-// eslint-disable-next-line jsdoc/require-jsdoc
export type FileMockConstants = OmitStrict<
MockConstants,
'ANGULAR_APP_DIR' | 'APPS_DIR' | 'LIBS_DIR' | 'PROJECT_DIR' | 'TS_LIBRARY_DIR' | 'GITHUB_WORKFLOW_DIR'
| 'ANGULAR_APP_NAME' | 'TS_LIBRARY_SCOPE' | 'TS_LIBRARY_NAME'
>;
-// eslint-disable-next-line jsdoc/require-jsdoc
export type DirMockConstants = OmitStrict<
MockConstants,
keyof FileMockConstants | 'TS_LIBRARY_NAME' | 'ANGULAR_APP_NAME' | 'TS_LIBRARY_SCOPE'
@@ -114,7 +96,9 @@ export function getMockConstants(projectName: string): MockConstants {
ROOT_PACKAGE_JSON: getPath(PROJECT_DIR, PACKAGE_JSON_FILE_NAME),
ENV: getPath(PROJECT_DIR, ENV_FILE_NAME),
GLOBAL_ENV_MODEL: getPath(PROJECT_DIR, GLOBAL_ENVIRONMENT_MODEL_FILE_NAME),
- GITHUB_WORKFLOW_DIR: getPath(PROJECT_DIR, '.github', 'workflows')
+ GITHUB_WORKFLOW_DIR: getPath(PROJECT_DIR, '.github', 'workflows'),
+ WORKSPACE_JSON: getPath(PROJECT_DIR, WORKSPACE_FILE_NAME),
+ BASE_TS_CONFIG_JSON: getPath(PROJECT_DIR, BASE_TS_CONFIG_FILE_NAME)
} as const;
return mockConstants;
}
\ No newline at end of file
diff --git a/src/__testing__/mock/file-mock.utilities.ts b/src/__testing__/mock/file-mock.utilities.ts
index f06afb7..2d20922 100644
--- a/src/__testing__/mock/file-mock.utilities.ts
+++ b/src/__testing__/mock/file-mock.utilities.ts
@@ -3,9 +3,27 @@ import { MockConstants, FileMockConstants, DirMockConstants } from './constants'
import { AngularJson } from '../../angular';
import { CPUtilities, FsUtilities, JsonUtilities } from '../../encapsulation';
import { EnvUtilities } from '../../env';
+import { TsConfigUtilities } from '../../tsconfig';
import { getPath } from '../../utilities';
import { WorkspaceUtilities } from '../../workspace';
+export const defaultFilesToMock: (keyof FileMockConstants)[] = [
+ 'WORKSPACE_JSON',
+ 'BASE_TS_CONFIG_JSON',
+ 'ENV',
+ 'GLOBAL_ENV_MODEL',
+ 'ROOT_PACKAGE_JSON',
+ 'DOCKER_COMPOSE_YAML',
+ 'DEV_DOCKER_COMPOSE_YAML',
+ 'LOCAL_DOCKER_COMPOSE_YAML'
+] as const;
+
+export const defaultFoldersToMock: (keyof DirMockConstants)[] = [
+ 'LIBS_DIR',
+ 'APPS_DIR',
+ 'PROJECT_DIR'
+] as const;
+
export abstract class FileMockUtilities {
private static readonly mockMethodForFile: Record<
@@ -27,33 +45,27 @@ export abstract class FileMockUtilities {
ANGULAR_ENVIRONMENT: this.createEmptyFile,
TS_LIBRARY_PACKAGE_JSON: this.createEmptyFile,
ROOT_PACKAGE_JSON: this.createRootPackageJson,
- ENV: this.createEmptyFile,
- GLOBAL_ENV_MODEL: this.createGlobalEnvModel
+ ENV: this.createEnv,
+ GLOBAL_ENV_MODEL: this.createGlobalEnvModel,
+ WORKSPACE_JSON: WorkspaceUtilities.createConfig,
+ BASE_TS_CONFIG_JSON: TsConfigUtilities.createBaseTsConfig
};
static async setup(
mockConstants: MockConstants,
- filesToMock: (keyof FileMockConstants)[] = [],
- contentOverrides: Partial> = {}
+ filesToMock: (keyof FileMockConstants)[] = defaultFilesToMock,
+ contentOverrides: Partial> = {},
+ foldersToMock: (keyof DirMockConstants)[] = defaultFoldersToMock
): Promise {
- await FsUtilities.rm(getPath(mockConstants.PROJECT_DIR));
+ await FsUtilities.rm(mockConstants.PROJECT_DIR);
CPUtilities['cwd'] = mockConstants.PROJECT_DIR;
- await this.mockFolders(mockConstants);
+ await this.mockFolders(foldersToMock, mockConstants);
await this.mockFiles(filesToMock, contentOverrides, mockConstants);
- await WorkspaceUtilities.createConfig();
}
- private static async mockFolders(mockConstants: MockConstants): Promise {
- const dirMockConstants: DirMockConstants = {
- ANGULAR_APP_DIR: mockConstants.ANGULAR_APP_DIR,
- APPS_DIR: mockConstants.APPS_DIR,
- LIBS_DIR: mockConstants.LIBS_DIR,
- PROJECT_DIR: mockConstants.PROJECT_DIR,
- TS_LIBRARY_DIR: mockConstants.TS_LIBRARY_DIR,
- GITHUB_WORKFLOW_DIR: mockConstants.GITHUB_WORKFLOW_DIR
- };
- for (const entry of Object.values(dirMockConstants)) {
- await FsUtilities.mkdir(getPath(entry), true, false);
+ private static async mockFolders(foldersToMock: (keyof DirMockConstants)[], mockConstants: MockConstants): Promise {
+ for (const entry of foldersToMock) {
+ await FsUtilities.mkdir(mockConstants[entry], true, false);
}
}
@@ -117,7 +129,7 @@ export abstract class FileMockUtilities {
private static async createRootPackageJson(mockConstants: MockConstants): Promise {
await FsUtilities.createFile(mockConstants.ROOT_PACKAGE_JSON, [
'{',
- ' "name": "@library/library",',
+ ' "name": "sandbox",',
' "version": "1.0.0",',
' "main": "index.js",',
' "scripts": {',
@@ -126,7 +138,18 @@ export abstract class FileMockUtilities {
' "keywords": [],',
' "author": "",',
' "license": "ISC",',
- ' "description": ""',
+ ' "description": "",',
+ ' "devDependencies": {',
+ ' "autoprefixer": "^10.4.21",',
+ ' "eslint": "^9.25.1",',
+ ' "eslint-config-service-soft": "^2.0.8",',
+ ' "postcss": "^8.5.3",',
+ ' "tailwindcss": "^4.1.4"',
+ ' },',
+ ' "workspaces": [',
+ ' "apps/*",',
+ ' "libs/*"',
+ ' ]',
'}'
], true, false);
}
@@ -176,4 +199,8 @@ export abstract class FileMockUtilities {
private static async createGlobalEnvModel(): Promise {
await EnvUtilities['createGlobalEnvironmentModel']();
}
+
+ private static async createEnv(mockConstants: MockConstants): Promise {
+ await FsUtilities.createFile(mockConstants.ENV, ['prod_root_domain=test.com', 'is_public=false']);
+ }
}
\ No newline at end of file
diff --git a/src/__testing__/mock/helpers/fake-unique-string.function.ts b/src/__testing__/mock/helpers/fake-unique-string.function.ts
index 346488c..2f53653 100644
--- a/src/__testing__/mock/helpers/fake-unique-string.function.ts
+++ b/src/__testing__/mock/helpers/fake-unique-string.function.ts
@@ -3,7 +3,7 @@ import { faker } from '@faker-js/faker';
const usedKeys: string[] = [];
export function fakeUniqueString(): string {
- const key: string = faker.string.alpha({ length: { min: 1, max: 20 }, exclude: usedKeys });
+ const key: string = faker.string.alpha({ length: { min: 2, max: 20 }, exclude: usedKeys });
usedKeys.push(key);
return key;
}
\ No newline at end of file
diff --git a/src/angular/angular-utilities.test.ts b/src/angular/angular-utilities.test.ts
index d33cbf4..fba9944 100644
--- a/src/angular/angular-utilities.test.ts
+++ b/src/angular/angular-utilities.test.ts
@@ -1,7 +1,7 @@
import { afterEach, beforeEach, describe, expect, jest, test } from '@jest/globals';
import { AngularUtilities } from './angular.utilities';
-import { fakeAddNavElementConfig, fakeTsImportDefinition, FileMockUtilities, getMockConstants, MockConstants } from '../__testing__';
+import { fakeAddNavElementConfig, fakeTsImportDefinition, FileMockUtilities, getMockConstants, MAX_GEN_CODE_TIME, MockConstants } from '../__testing__';
import { CPUtilities, FsUtilities } from '../encapsulation';
import { NpmUtilities } from '../npm';
import { TsImportDefinition } from '../ts';
@@ -255,7 +255,7 @@ describe('AngularUtilities', () => {
'',
'export const routes: NavRoute[] = NavUtilities.getAngularRoutes(navbarRows, footerRows, [notFoundRoute]);'
]);
- }, 20000);
+ }, MAX_GEN_CODE_TIME);
test('generatePage for footer', async () => {
await AngularUtilities.setupNavigation(mockConstants.ANGULAR_APP_DIR, mockConstants.ANGULAR_APP_NAME);
@@ -319,7 +319,7 @@ describe('AngularUtilities', () => {
'',
'export const routes: NavRoute[] = NavUtilities.getAngularRoutes(navbarRows, footerRows, [notFoundRoute]);'
]);
- }, 10000);
+ }, MAX_GEN_CODE_TIME);
test('addPwaSupport', async () => {
await AngularUtilities.setupPwa(mockConstants.ANGULAR_APP_DIR, mockConstants.ANGULAR_APP_NAME);
diff --git a/src/angular/angular.utilities.ts b/src/angular/angular.utilities.ts
index d6d93a7..3755f1e 100644
--- a/src/angular/angular.utilities.ts
+++ b/src/angular/angular.utilities.ts
@@ -799,7 +799,6 @@ export abstract class AngularUtilities {
{ defaultImport: false, element: 'OfflineService', path: './services/offline.service' }
]
);
- // TODO: enable OfflineRequestInterceptor. Need to fix parsing of provideServiceWorker first.
await this.addProvider(
root,
// eslint-disable-next-line typescript/no-unsafe-assignment, typescript/no-explicit-any
diff --git a/src/commands/add/add-angular-library/add-angular-library-command.test.ts b/src/commands/add/add-angular-library/add-angular-library-command.test.ts
new file mode 100644
index 0000000..439ea04
--- /dev/null
+++ b/src/commands/add/add-angular-library/add-angular-library-command.test.ts
@@ -0,0 +1,28 @@
+import { afterEach, beforeEach, describe, expect, jest, test } from '@jest/globals';
+
+import { FileMockUtilities, getMockConstants, MAX_ADD_TIME, MockConstants, mockInquire } from '../../../__testing__';
+import { InquirerUtilities } from '../../../encapsulation';
+import { AddConfiguration, AddType } from '../models';
+import { AddAngularLibraryCommand } from './add-angular-library.command';
+
+const mockConstants: MockConstants = getMockConstants('add-angular-library-command');
+
+describe('AddAngularLibraryCommand', () => {
+ beforeEach(async () => {
+ await FileMockUtilities.setup(mockConstants);
+ InquirerUtilities['inquire'] = jest.fn(mockInquire({
+ scope: '@sandbox'
+ }));
+ });
+
+ test('should run', async () => {
+ const baseConfig: AddConfiguration = { name: 'ui', type: AddType.ANGULAR_LIBRARY };
+ const command: AddAngularLibraryCommand = new AddAngularLibraryCommand(baseConfig);
+ await command.run();
+ expect(true).toBe(true);
+ }, MAX_ADD_TIME);
+
+ afterEach(() => {
+ jest.restoreAllMocks();
+ });
+});
\ No newline at end of file
diff --git a/src/commands/add/add-angular-library/add-angular-library.command.ts b/src/commands/add/add-angular-library/add-angular-library.command.ts
index 00ae89f..a346ae7 100644
--- a/src/commands/add/add-angular-library/add-angular-library.command.ts
+++ b/src/commands/add/add-angular-library/add-angular-library.command.ts
@@ -1,5 +1,5 @@
import { AngularUtilities } from '../../../angular';
-import { ANGULAR_JSON_FILE_NAME, GIT_IGNORE_FILE_NAME, LIBS_DIRECTORY_NAME, PACKAGE_JSON_FILE_NAME } from '../../../constants';
+import { ANGULAR_JSON_FILE_NAME, BASE_TS_CONFIG_FILE_NAME, GIT_IGNORE_FILE_NAME, LIBS_DIRECTORY_NAME, PACKAGE_JSON_FILE_NAME } from '../../../constants';
import { FsUtilities, JsonUtilities, QuestionsFor } from '../../../encapsulation';
import { EslintUtilities } from '../../../eslint';
import { NpmUtilities, PackageJson } from '../../../npm';
@@ -149,7 +149,7 @@ export class AddAngularLibraryCommand extends BaseAddCommand {
+ beforeEach(async () => {
+ await FileMockUtilities.setup(mockConstants);
+ InquirerUtilities['inquire'] = jest.fn(mockInquire({
+ port: 4200,
+ 'sub domain': undefined,
+ 'title suffix (eg. "| My Company")': '| Website',
+ 'Add tracking?': false
+ }));
+ });
+
+ test('should run', async () => {
+ const baseConfig: AddConfiguration = { name: 'website', type: AddType.ANGULAR_WEBSITE };
+ const command: AddAngularWebsiteCommand = new AddAngularWebsiteCommand(baseConfig);
+ await command.run();
+ expect(true).toBe(true);
+ }, MAX_ADD_TIME);
+
+ afterEach(() => {
+ jest.restoreAllMocks();
+ });
+});
\ No newline at end of file
diff --git a/src/commands/add/add-angular-website/add-angular-website.command.ts b/src/commands/add/add-angular-website/add-angular-website.command.ts
index 4be8d90..66398ac 100644
--- a/src/commands/add/add-angular-website/add-angular-website.command.ts
+++ b/src/commands/add/add-angular-website/add-angular-website.command.ts
@@ -1,5 +1,5 @@
import { AngularUtilities, NavElementTypes } from '../../../angular';
-import { ANGULAR_JSON_FILE_NAME, APPS_DIRECTORY_NAME, DOCKER_FILE_NAME, GIT_IGNORE_FILE_NAME } from '../../../constants';
+import { ANGULAR_JSON_FILE_NAME, APPS_DIRECTORY_NAME, BASE_TS_CONFIG_FILE_NAME, DOCKER_FILE_NAME, GIT_IGNORE_FILE_NAME } from '../../../constants';
import { DockerUtilities } from '../../../docker';
import { FsUtilities, JsonUtilities, QuestionsFor } from '../../../encapsulation';
import { DefaultEnvKeys, EnvUtilities } from '../../../env';
@@ -200,14 +200,14 @@ export class AddAngularWebsiteCommand extends BaseAddCommand {
// eslint-disable-next-line no-console
console.log('sets up tsconfig');
- await TsConfigUtilities.updateTsConfig(projectName, { extends: '../../tsconfig.base.json' });
+ await TsConfigUtilities.updateTsConfig(projectName, { extends: `../../${BASE_TS_CONFIG_FILE_NAME}` });
const eslintTsconfig: TsConfig = {
compilerOptions: {
outDir: './out-tsc/eslint',
types: ['jasmine', 'node']
},
- extends: '../../tsconfig.base.json',
+ extends: `../../${BASE_TS_CONFIG_FILE_NAME}`,
files: [
'src/main.ts',
'src/main.server.ts',
diff --git a/src/commands/add/add-angular/add-angular-command.test.ts b/src/commands/add/add-angular/add-angular-command.test.ts
new file mode 100644
index 0000000..2580415
--- /dev/null
+++ b/src/commands/add/add-angular/add-angular-command.test.ts
@@ -0,0 +1,31 @@
+import { afterEach, beforeEach, describe, expect, jest, test } from '@jest/globals';
+
+import { AddAngularCommand } from './add-angular.command';
+import { FileMockUtilities, getMockConstants, MAX_ADD_TIME, MockConstants, mockInquire } from '../../../__testing__';
+import { InquirerUtilities } from '../../../encapsulation';
+import { AddConfiguration, AddType } from '../models';
+
+const mockConstants: MockConstants = getMockConstants('add-angular-command');
+
+describe('AddAngularCommand', () => {
+ beforeEach(async () => {
+ await FileMockUtilities.setup(mockConstants);
+ InquirerUtilities['inquire'] = jest.fn(mockInquire({
+ port: 4200,
+ 'sub domain': 'admin',
+ 'title suffix (eg. "| My Company")': '| Admin',
+ 'name of the api to use': 'api'
+ }));
+ });
+
+ test('should run', async () => {
+ const baseConfig: AddConfiguration = { name: 'admin', type: AddType.ANGULAR };
+ const command: AddAngularCommand = new AddAngularCommand(baseConfig);
+ await command.run();
+ expect(true).toBe(true);
+ }, MAX_ADD_TIME);
+
+ afterEach(() => {
+ jest.restoreAllMocks();
+ });
+});
\ No newline at end of file
diff --git a/src/commands/add/add-angular/add-angular.command.ts b/src/commands/add/add-angular/add-angular.command.ts
index 2ac6d79..2b34caa 100644
--- a/src/commands/add/add-angular/add-angular.command.ts
+++ b/src/commands/add/add-angular/add-angular.command.ts
@@ -1,6 +1,6 @@
/* eslint-disable no-console */
import { AngularUtilities, NavElementTypes } from '../../../angular';
-import { ANGULAR_JSON_FILE_NAME, APP_CONFIG_FILE_NAME, APPS_DIRECTORY_NAME, DOCKER_FILE_NAME, GIT_IGNORE_FILE_NAME } from '../../../constants';
+import { ANGULAR_JSON_FILE_NAME, APP_CONFIG_FILE_NAME, APPS_DIRECTORY_NAME, BASE_TS_CONFIG_FILE_NAME, DOCKER_FILE_NAME, GIT_IGNORE_FILE_NAME } from '../../../constants';
import { DockerUtilities } from '../../../docker';
import { FsUtilities, JsonUtilities, QuestionsFor } from '../../../encapsulation';
import { DefaultEnvKeys, EnvUtilities } from '../../../env';
@@ -239,14 +239,14 @@ export class AddAngularCommand extends BaseAddCommand {
private async setupTsConfig(root: string, projectName: string): Promise {
console.log('sets up tsconfig');
- await TsConfigUtilities.updateTsConfig(projectName, { extends: '../../tsconfig.base.json' });
+ await TsConfigUtilities.updateTsConfig(projectName, { extends: `../../${BASE_TS_CONFIG_FILE_NAME}` });
const eslintTsconfig: TsConfig = {
compilerOptions: {
outDir: './out-tsc/eslint',
types: ['jasmine', 'node']
},
- extends: '../../tsconfig.base.json',
+ extends: `../../${BASE_TS_CONFIG_FILE_NAME}`,
files: [
'src/main.ts',
'src/main.server.ts',
diff --git a/src/commands/add/add-loopback/add-loopback-command.test.ts b/src/commands/add/add-loopback/add-loopback-command.test.ts
index 2d3c41d..4675046 100644
--- a/src/commands/add/add-loopback/add-loopback-command.test.ts
+++ b/src/commands/add/add-loopback/add-loopback-command.test.ts
@@ -1,14 +1,16 @@
import { afterEach, beforeEach, describe, expect, jest, test } from '@jest/globals';
-import { FileMockUtilities, getMockConstants, MockConstants, mockInquire } from '../../../__testing__';
+import { FileMockUtilities, getMockConstants, MAX_ADD_TIME, MockConstants, mockInquire } from '../../../__testing__';
import { DbType } from '../../../db';
import { InquirerUtilities } from '../../../encapsulation';
+import { AddConfiguration, AddType } from '../models';
+import { AddLoopbackCommand } from './add-loopback.command';
const mockConstants: MockConstants = getMockConstants('add-loopback-command');
describe('AddLoopbackCommand', () => {
beforeEach(async () => {
- await FileMockUtilities.setup(mockConstants, ['DOCKER_COMPOSE_YAML', 'LOCAL_DOCKER_COMPOSE_YAML', 'GLOBAL_ENV_MODEL', 'DEV_DOCKER_COMPOSE_YAML', 'ENV']);
+ await FileMockUtilities.setup(mockConstants);
InquirerUtilities['inquire'] = jest.fn(mockInquire({
port: 3000,
'sub domain': 'api',
@@ -22,12 +24,12 @@ describe('AddLoopbackCommand', () => {
}));
});
- test('should run and create new database', () => {
- // const baseConfig: AddConfiguration = { name: 'api', type: AddType.LOOPBACK };
- // const command: AddLoopbackCommand = new AddLoopbackCommand(baseConfig);
- // await command.run(); // TODO: enable test
+ test('should run and create new database', async () => {
+ const baseConfig: AddConfiguration = { name: 'api', type: AddType.LOOPBACK };
+ const command: AddLoopbackCommand = new AddLoopbackCommand(baseConfig);
+ await command.run();
expect(true).toBe(true);
- }, 50000);
+ }, MAX_ADD_TIME);
afterEach(() => {
jest.restoreAllMocks();
diff --git a/src/commands/add/add-loopback/add-loopback.command.ts b/src/commands/add/add-loopback/add-loopback.command.ts
index 5657919..875dab3 100644
--- a/src/commands/add/add-loopback/add-loopback.command.ts
+++ b/src/commands/add/add-loopback/add-loopback.command.ts
@@ -1,5 +1,5 @@
import { loopbackWebpackContent } from './loopback-webpack.content';
-import { APPS_DIRECTORY_NAME, PROD_DOCKER_COMPOSE_FILE_NAME, DOCKER_FILE_NAME, ENVIRONMENT_MODEL_TS_FILE_NAME, GIT_IGNORE_FILE_NAME, TS_CONFIG_FILE_NAME, WEBPACK_CONFIG } from '../../../constants';
+import { APPS_DIRECTORY_NAME, PROD_DOCKER_COMPOSE_FILE_NAME, DOCKER_FILE_NAME, ENVIRONMENT_MODEL_TS_FILE_NAME, GIT_IGNORE_FILE_NAME, TS_CONFIG_FILE_NAME, WEBPACK_CONFIG, BASE_TS_CONFIG_FILE_NAME } from '../../../constants';
import { DbType, DbUtilities } from '../../../db';
import { DockerUtilities } from '../../../docker';
import { FsUtilities, QuestionsFor } from '../../../encapsulation';
@@ -347,7 +347,7 @@ export class AddLoopbackCommand extends BaseAddCommand
await TsConfigUtilities.updateTsConfig(
projectName,
{
- extends: ['../../tsconfig.base.json', '@loopback/build/config/tsconfig.common.json'],
+ extends: [`../../${BASE_TS_CONFIG_FILE_NAME}`, '@loopback/build/config/tsconfig.common.json'],
compilerOptions: { rootDir: undefined }
}
);
diff --git a/src/commands/add/add-nest/add-nest-command.test.ts b/src/commands/add/add-nest/add-nest-command.test.ts
new file mode 100644
index 0000000..367e02c
--- /dev/null
+++ b/src/commands/add/add-nest/add-nest-command.test.ts
@@ -0,0 +1,37 @@
+import { afterEach, beforeEach, describe, expect, jest, test } from '@jest/globals';
+
+import { FileMockUtilities, getMockConstants, MAX_ADD_TIME, MockConstants, mockInquire } from '../../../__testing__';
+import { InquirerUtilities } from '../../../encapsulation';
+import { AddConfiguration, AddType } from '../models';
+import { AddNestCommand } from './add-nest.command';
+import { DbType } from '../../../db';
+
+const mockConstants: MockConstants = getMockConstants('add-nest-command');
+
+describe('AddNestCommand', () => {
+ beforeEach(async () => {
+ await FileMockUtilities.setup(mockConstants);
+ InquirerUtilities['inquire'] = jest.fn(mockInquire({
+ 'sub domain': 'api',
+ port: 3000,
+ 'Email of the default user': 'test@test.com',
+ 'Password of the default user': 'stringstring',
+ 'Name of the frontend where the reset password ui is implemented': 'admin',
+ 'Database compose service': 'NEW',
+ 'Compose service name': 'db',
+ 'Database name': 'sandbox',
+ 'database type': DbType.POSTGRES
+ }));
+ });
+
+ test('should run and add a new database', async () => {
+ const baseConfig: AddConfiguration = { name: 'api', type: AddType.NEST };
+ const command: AddNestCommand = new AddNestCommand(baseConfig);
+ await command.run();
+ expect(true).toBe(true);
+ }, MAX_ADD_TIME);
+
+ afterEach(() => {
+ jest.restoreAllMocks();
+ });
+});
\ No newline at end of file
diff --git a/src/commands/add/add-nest/add-nest.command.ts b/src/commands/add/add-nest/add-nest.command.ts
index fd78d89..ce985a1 100644
--- a/src/commands/add/add-nest/add-nest.command.ts
+++ b/src/commands/add/add-nest/add-nest.command.ts
@@ -1,7 +1,7 @@
import { Type } from '@nestjs/common';
-import { APPS_DIRECTORY_NAME, DOCKER_FILE_NAME, ENVIRONMENT_MODEL_TS_FILE_NAME, ESLINT_CONFIG_FILE_NAME, NEST_CLI_FILE_NAME, PROD_DOCKER_COMPOSE_FILE_NAME, WEBPACK_CONFIG } from '../../../constants';
+import { APPS_DIRECTORY_NAME, BASE_TS_CONFIG_FILE_NAME, DOCKER_FILE_NAME, ENVIRONMENT_MODEL_TS_FILE_NAME, ESLINT_CONFIG_FILE_NAME, NEST_CLI_FILE_NAME, PROD_DOCKER_COMPOSE_FILE_NAME, WEBPACK_CONFIG } from '../../../constants';
import { DbType, DbUtilities, defaultPortForDbType } from '../../../db';
import { DockerUtilities } from '../../../docker';
import { FsUtilities, QuestionsFor } from '../../../encapsulation';
@@ -256,7 +256,7 @@ export class AddNestCommand extends BaseAddCommand {
await TsConfigUtilities.updateTsConfig(
projectName,
{
- extends: '../../tsconfig.base.json',
+ extends: `../../${BASE_TS_CONFIG_FILE_NAME}`,
compilerOptions: {
removeComments: undefined,
emitDecoratorMetadata: undefined,
diff --git a/src/commands/add/add-ts-library/add-ts-library-command.test.ts b/src/commands/add/add-ts-library/add-ts-library-command.test.ts
new file mode 100644
index 0000000..4eb8fa2
--- /dev/null
+++ b/src/commands/add/add-ts-library/add-ts-library-command.test.ts
@@ -0,0 +1,28 @@
+import { afterEach, beforeEach, describe, expect, jest, test } from '@jest/globals';
+
+import { FileMockUtilities, getMockConstants, MAX_ADD_TIME, MockConstants, mockInquire } from '../../../__testing__';
+import { AddConfiguration, AddType } from '../models';
+import { AddTsLibraryCommand } from './add-ts-library.command';
+import { InquirerUtilities } from '../../../encapsulation';
+
+const mockConstants: MockConstants = getMockConstants('add-ts-library-command');
+
+describe('AddTsLibraryCommand', () => {
+ beforeEach(async () => {
+ await FileMockUtilities.setup(mockConstants);
+ InquirerUtilities['inquire'] = jest.fn(mockInquire({
+ scope: '@sandbox'
+ }));
+ });
+
+ test('should run', async () => {
+ const baseConfig: AddConfiguration = { name: 'shared', type: AddType.TS_LIBRARY };
+ const command: AddTsLibraryCommand = new AddTsLibraryCommand(baseConfig);
+ await command.run();
+ expect(true).toBe(true);
+ }, MAX_ADD_TIME);
+
+ afterEach(() => {
+ jest.restoreAllMocks();
+ });
+});
\ No newline at end of file
diff --git a/src/commands/add/add-ts-library/add-ts-library.command.ts b/src/commands/add/add-ts-library/add-ts-library.command.ts
index a28ab93..23153a6 100644
--- a/src/commands/add/add-ts-library/add-ts-library.command.ts
+++ b/src/commands/add/add-ts-library/add-ts-library.command.ts
@@ -54,8 +54,7 @@ export class AddTsLibraryCommand extends BaseAddCommand
]);
await FsUtilities.createFile(getPath(root, 'src', 'index.ts'), '');
- await NpmUtilities.install(config.name, [NpmPackage.VITE_PLUGIN_DTS], true);
- await NpmUtilities.run(config.name, 'build');
+ await NpmUtilities.run(config.name, 'build', false);
await this.installInProjects(config);
}
@@ -100,6 +99,7 @@ export class AddTsLibraryCommand extends BaseAddCommand
'\t}',
'});'
]);
+ await NpmUtilities.install(config.name, [NpmPackage.VITE_PLUGIN_DTS], true);
// const originalPackageJson: PackageJson = await FsUtilities.parseFileAs(getPath(libraryPath, PACKAGE_JSON_FILE_NAME));
await NpmUtilities.updatePackageJson(
config.name,
diff --git a/src/commands/add/add-wordpress/add-wordpress-command.test.ts b/src/commands/add/add-wordpress/add-wordpress-command.test.ts
new file mode 100644
index 0000000..552e969
--- /dev/null
+++ b/src/commands/add/add-wordpress/add-wordpress-command.test.ts
@@ -0,0 +1,33 @@
+import { afterEach, beforeEach, describe, expect, jest, test } from '@jest/globals';
+
+import { FileMockUtilities, getMockConstants, MAX_ADD_TIME, MockConstants, mockInquire } from '../../../__testing__';
+import { InquirerUtilities } from '../../../encapsulation';
+import { AddConfiguration, AddType } from '../models';
+import { AddWordpressCommand } from './add-wordpress.command';
+import { DbType } from '../../../db';
+
+const mockConstants: MockConstants = getMockConstants('add-wordpress-command');
+
+describe('AddWordpressCommand', () => {
+ beforeEach(async () => {
+ await FileMockUtilities.setup(mockConstants);
+ InquirerUtilities['inquire'] = jest.fn(mockInquire({
+ 'sub domain': 'wordpress',
+ 'Database compose service': 'NEW',
+ 'Compose service name': 'db',
+ 'Database name': 'sandbox',
+ 'database type': DbType.MARIADB
+ }));
+ });
+
+ test('should run', async () => {
+ const baseConfig: AddConfiguration = { name: 'wordpress', type: AddType.WORDPRESS };
+ const command: AddWordpressCommand = new AddWordpressCommand(baseConfig);
+ await command.run();
+ expect(true).toBe(true);
+ }, MAX_ADD_TIME);
+
+ afterEach(() => {
+ jest.restoreAllMocks();
+ });
+});
\ No newline at end of file
diff --git a/src/commands/add/models/base-add-command.model.ts b/src/commands/add/models/base-add-command.class.ts
similarity index 100%
rename from src/commands/add/models/base-add-command.model.ts
rename to src/commands/add/models/base-add-command.class.ts
diff --git a/src/commands/add/models/index.ts b/src/commands/add/models/index.ts
index 35b0478..0ae107d 100644
--- a/src/commands/add/models/index.ts
+++ b/src/commands/add/models/index.ts
@@ -1,3 +1,3 @@
-export * from './base-add-command.model';
+export * from './base-add-command.class';
export * from './add-configuration.model';
export * from './add-type.enum';
\ No newline at end of file
diff --git a/src/commands/down/down-command.test.ts b/src/commands/down/down-command.test.ts
new file mode 100644
index 0000000..b5c59b8
--- /dev/null
+++ b/src/commands/down/down-command.test.ts
@@ -0,0 +1,49 @@
+import { describe, beforeEach, jest, test, expect, afterEach } from '@jest/globals';
+
+import { DownCommand } from './down.command';
+import { FileMockUtilities, getMockConstants, MAX_FAST_TIME, MockConstants, mockInquire } from '../../__testing__';
+import { FullyParsedDockerService, getDockerServices } from '../../docker';
+import { InquirerUtilities } from '../../encapsulation';
+import { UpCommand } from '../up';
+
+const mockConstants: MockConstants = getMockConstants('down-command');
+
+describe('DownCommand', () => {
+ beforeEach(async () => {
+ await FileMockUtilities.setup(mockConstants, undefined, {
+ DEV_DOCKER_COMPOSE_YAML: [
+ 'services:',
+ '',
+ ' adminer:',
+ ' image: adminer',
+ ' restart: unless-stopped',
+ ' ports:',
+ ' - 8080:8080'
+ ]
+ });
+ InquirerUtilities['inquire'] = jest.fn(mockInquire({
+ env: 'dev.docker-compose.yaml'
+ }));
+ });
+
+ test('should run', async () => {
+ const runningDockerServicesBeforeUp: FullyParsedDockerService[] = await getDockerServices(false);
+
+ const upCommand: UpCommand = new UpCommand();
+ await upCommand.start(['u']);
+
+ const runningDockerServicesAfterUp: FullyParsedDockerService[] = await getDockerServices(false);
+ expect(runningDockerServicesBeforeUp.length + 1).toEqual(runningDockerServicesAfterUp.length);
+
+ const command: DownCommand = new DownCommand();
+ await command.start(['d']);
+
+ const runningDockerServicesAfterDown: FullyParsedDockerService[] = await getDockerServices(false);
+
+ expect(runningDockerServicesAfterDown.length).toEqual(runningDockerServicesBeforeUp.length);
+ }, MAX_FAST_TIME * 2 /** We call up and down. */);
+
+ afterEach(() => {
+ jest.restoreAllMocks();
+ });
+});
\ No newline at end of file
diff --git a/src/commands/generate-page/generate-page-command.test.ts b/src/commands/generate-page/generate-page-command.test.ts
new file mode 100644
index 0000000..d01d502
--- /dev/null
+++ b/src/commands/generate-page/generate-page-command.test.ts
@@ -0,0 +1,39 @@
+import { afterEach, beforeEach, describe, expect, jest, test } from '@jest/globals';
+
+import { GeneratePageCommand } from './generate-page.command';
+import { FileMockUtilities, getMockConstants, MAX_ADD_TIME, MAX_GEN_CODE_TIME, MockConstants, mockInquire } from '../../__testing__';
+import { InquirerUtilities } from '../../encapsulation';
+import { AddAngularWebsiteCommand } from '../add/add-angular-website';
+import { AddConfiguration, AddType } from '../add/models';
+
+const mockConstants: MockConstants = getMockConstants('generate-page-command');
+
+describe('GeneratePageCommand', () => {
+ beforeEach(async () => {
+ await FileMockUtilities.setup(mockConstants);
+ InquirerUtilities['inquire'] = jest.fn(mockInquire({
+ Project: 'website',
+ 'Page name': 'dashboard',
+ Route: 'dashboard',
+ Title: 'Dashboard | Website',
+ port: 4200,
+ 'sub domain': undefined,
+ 'title suffix (eg. "| My Company")': '| Website',
+ 'Add tracking?': false
+ }));
+ });
+
+ test('should run', async () => {
+ const baseConfig: AddConfiguration = { name: 'website', type: AddType.ANGULAR_WEBSITE };
+ const addWebsiteCommand: AddAngularWebsiteCommand = new AddAngularWebsiteCommand(baseConfig);
+ await addWebsiteCommand.run();
+
+ const command: GeneratePageCommand = new GeneratePageCommand();
+ await command.start(['gp']);
+ expect(true).toBe(true);
+ }, MAX_ADD_TIME + MAX_GEN_CODE_TIME);
+
+ afterEach(() => {
+ jest.restoreAllMocks();
+ });
+});
\ No newline at end of file
diff --git a/src/commands/help/help-command.test.ts b/src/commands/help/help-command.test.ts
new file mode 100644
index 0000000..a7a8b7b
--- /dev/null
+++ b/src/commands/help/help-command.test.ts
@@ -0,0 +1,18 @@
+import { beforeEach, describe, expect, test } from '@jest/globals';
+
+import { HelpCommand } from './help.command';
+import { FileMockUtilities, getMockConstants, MAX_INSTANT_TIME, MockConstants } from '../../__testing__';
+
+const mockConstants: MockConstants = getMockConstants('help-command');
+
+describe('GeneratePageCommand', () => {
+ beforeEach(async () => {
+ await FileMockUtilities.setup(mockConstants);
+ });
+
+ test('should run', async () => {
+ const command: HelpCommand = new HelpCommand();
+ await command.start(['h']);
+ expect(true).toBe(true);
+ }, MAX_INSTANT_TIME);
+});
\ No newline at end of file
diff --git a/src/commands/init/init-command.test.ts b/src/commands/init/init-command.test.ts
new file mode 100644
index 0000000..fd7d8eb
--- /dev/null
+++ b/src/commands/init/init-command.test.ts
@@ -0,0 +1,28 @@
+import { afterEach, beforeEach, describe, expect, jest, test } from '@jest/globals';
+
+import { InitCommand } from './init.command';
+import { FileMockUtilities, getMockConstants, MAX_ADD_TIME, MockConstants, mockInquire } from '../../__testing__';
+import { InquirerUtilities } from '../../encapsulation';
+
+const mockConstants: MockConstants = getMockConstants('init-command');
+
+describe('InitCommand', () => {
+ beforeEach(async () => {
+ await FileMockUtilities.setup(mockConstants, []);
+ InquirerUtilities['inquire'] = jest.fn(mockInquire({
+ 'prod root domain (eg. "test.com")': 'test.com',
+ 'E-Mail (needed for ssl certificates)': 'user@test.com',
+ 'Setup Github Actions?': true
+ }));
+ });
+
+ test('should run', async () => {
+ const command: InitCommand = new InitCommand();
+ await command.start(['i']);
+ expect(true).toBe(true);
+ }, MAX_ADD_TIME);
+
+ afterEach(() => {
+ jest.restoreAllMocks();
+ });
+});
\ No newline at end of file
diff --git a/src/commands/list/list-command.test.ts b/src/commands/list/list-command.test.ts
new file mode 100644
index 0000000..b617244
--- /dev/null
+++ b/src/commands/list/list-command.test.ts
@@ -0,0 +1,43 @@
+import { describe, beforeEach, jest, test, afterEach } from '@jest/globals';
+
+import { ListCommand } from './list.command';
+import { FileMockUtilities, getMockConstants, MAX_FAST_TIME, MockConstants, mockInquire } from '../../__testing__';
+import { InquirerUtilities } from '../../encapsulation';
+import { DownCommand } from '../down';
+import { UpCommand } from '../up';
+
+const mockConstants: MockConstants = getMockConstants('list-command');
+
+describe('ListCommand', () => {
+ beforeEach(async () => {
+ await FileMockUtilities.setup(mockConstants, undefined, {
+ DEV_DOCKER_COMPOSE_YAML: [
+ 'services:',
+ '',
+ ' adminer:',
+ ' image: adminer',
+ ' restart: unless-stopped',
+ ' ports:',
+ ' - 8080:8080'
+ ]
+ });
+ InquirerUtilities['inquire'] = jest.fn(mockInquire({
+ env: 'dev.docker-compose.yaml'
+ }));
+ });
+
+ test('should run', async () => {
+ const upCommand: UpCommand = new UpCommand();
+ await upCommand.start(['u']);
+
+ const listCommand: ListCommand = new ListCommand(true);
+ await listCommand.start(['l']);
+
+ const command: DownCommand = new DownCommand();
+ await command.start(['d']);
+ }, MAX_FAST_TIME * 3 /** We call up, list and down. */);
+
+ afterEach(() => {
+ jest.restoreAllMocks();
+ });
+});
\ No newline at end of file
diff --git a/src/commands/prepare/prepare-command.test.ts b/src/commands/prepare/prepare-command.test.ts
new file mode 100644
index 0000000..698856e
--- /dev/null
+++ b/src/commands/prepare/prepare-command.test.ts
@@ -0,0 +1,26 @@
+import { describe, beforeEach, jest, test, afterEach, expect } from '@jest/globals';
+
+import { PrepareCommand } from './prepare.command';
+import { FileMockUtilities, getMockConstants, MAX_INSTANT_TIME, MockConstants, mockInquire } from '../../__testing__';
+import { InquirerUtilities } from '../../encapsulation';
+
+const mockConstants: MockConstants = getMockConstants('prepare-command');
+
+describe('PrepareCommand', () => {
+ beforeEach(async () => {
+ await FileMockUtilities.setup(mockConstants);
+ InquirerUtilities['inquire'] = jest.fn(mockInquire({
+ env: 'dev.docker-compose.yaml'
+ }));
+ });
+
+ test('should run', async () => {
+ const command: PrepareCommand = new PrepareCommand();
+ await command.start(['p']);
+ expect(true).toEqual(true);
+ }, MAX_INSTANT_TIME);
+
+ afterEach(() => {
+ jest.restoreAllMocks();
+ });
+});
\ No newline at end of file
diff --git a/src/commands/run-all/run-all-command.test.ts b/src/commands/run-all/run-all-command.test.ts
new file mode 100644
index 0000000..013fbe4
--- /dev/null
+++ b/src/commands/run-all/run-all-command.test.ts
@@ -0,0 +1,33 @@
+import { describe, beforeEach, jest, test, afterEach, expect } from '@jest/globals';
+
+import { RunAllCommand } from './run-all.command';
+import { FileMockUtilities, getMockConstants, MAX_ADD_TIME, MAX_GEN_CODE_TIME, MockConstants, mockInquire } from '../../__testing__';
+import { InquirerUtilities } from '../../encapsulation';
+import { AddTsLibraryCommand } from '../add/add-ts-library';
+import { AddType } from '../add/models';
+
+const mockConstants: MockConstants = getMockConstants('run-all-command');
+
+describe('RunAllCommand', () => {
+ beforeEach(async () => {
+ await FileMockUtilities.setup(mockConstants);
+ InquirerUtilities['inquire'] = jest.fn(mockInquire({
+ scope: '@sandbox'
+ }));
+ });
+
+ test('should run', async () => {
+ const addCommand1: AddTsLibraryCommand = new AddTsLibraryCommand({ name: 'shared', type: AddType.TS_LIBRARY });
+ await addCommand1.run();
+ const addCommand2: AddTsLibraryCommand = new AddTsLibraryCommand({ name: 'shared2', type: AddType.TS_LIBRARY });
+ await addCommand2.run();
+
+ const command: RunAllCommand = new RunAllCommand();
+ await command.start(['ra', 'build']);
+ expect(true).toEqual(true);
+ }, MAX_ADD_TIME + MAX_GEN_CODE_TIME);
+
+ afterEach(() => {
+ jest.restoreAllMocks();
+ });
+});
\ No newline at end of file
diff --git a/src/commands/run/run-command.test.ts b/src/commands/run/run-command.test.ts
new file mode 100644
index 0000000..8244e97
--- /dev/null
+++ b/src/commands/run/run-command.test.ts
@@ -0,0 +1,41 @@
+import { describe, beforeEach, jest, test, afterEach, expect } from '@jest/globals';
+
+import { RunCommand } from './run.command';
+import { FileMockUtilities, getMockConstants, MAX_ADD_TIME, MAX_GEN_CODE_TIME, MockConstants, mockInquire } from '../../__testing__';
+import { DbType } from '../../db';
+import { InquirerUtilities } from '../../encapsulation';
+import { AddNestCommand } from '../add/add-nest';
+import { AddConfiguration, AddType } from '../add/models';
+
+const mockConstants: MockConstants = getMockConstants('run-command');
+
+describe('RunCommand', () => {
+ beforeEach(async () => {
+ await FileMockUtilities.setup(mockConstants);
+ InquirerUtilities['inquire'] = jest.fn(mockInquire({
+ 'sub domain': 'api',
+ port: 3000,
+ 'Email of the default user': 'test@test.com',
+ 'Password of the default user': 'stringstring',
+ 'Name of the frontend where the reset password ui is implemented': 'admin',
+ 'Database compose service': 'NEW',
+ 'Compose service name': 'db',
+ 'Database name': 'sandbox',
+ 'database type': DbType.POSTGRES
+ }));
+ });
+
+ test('should run', async () => {
+ const baseConfig: AddConfiguration = { name: 'api', type: AddType.NEST };
+ const addNestCommand: AddNestCommand = new AddNestCommand(baseConfig);
+ await addNestCommand.run();
+
+ const command: RunCommand = new RunCommand();
+ await command.start(['api', 'build']);
+ expect(true).toEqual(true);
+ }, MAX_ADD_TIME + MAX_GEN_CODE_TIME);
+
+ afterEach(() => {
+ jest.restoreAllMocks();
+ });
+});
\ No newline at end of file
diff --git a/src/commands/run/run.command.ts b/src/commands/run/run.command.ts
index 6e5a7bb..21baae7 100644
--- a/src/commands/run/run.command.ts
+++ b/src/commands/run/run.command.ts
@@ -1,6 +1,6 @@
import { Dirent } from 'fs';
-import { CPUtilities, FsUtilities } from '../../encapsulation';
+import { FsUtilities } from '../../encapsulation';
import { NativeNpmCommands, NpmUtilities, PackageJson } from '../../npm';
import { exitWithError, getPath } from '../../utilities';
import { WorkspaceProject, WorkspaceUtilities } from '../../workspace';
@@ -16,12 +16,7 @@ export class RunCommand extends BaseCommand {
protected override maxLength: undefined = undefined;
protected override async run(config: RunConfiguration): Promise {
- if (!config.isNativeCommand) {
- await NpmUtilities.run(config.projectName, config.commands);
- return;
- }
- const project: WorkspaceProject = await WorkspaceUtilities.findProjectOrFail(config.projectName, getPath('.'));
- CPUtilities.execSync(`npm ${config.commands} --workspace=${project.npmWorkspaceString}`);
+ await NpmUtilities.run(config.projectName, config.commands, config.isNativeCommand);
}
protected override resolveInput(args: string[]): RunConfiguration {
diff --git a/src/commands/up/up-command.test.ts b/src/commands/up/up-command.test.ts
new file mode 100644
index 0000000..8f8d07a
--- /dev/null
+++ b/src/commands/up/up-command.test.ts
@@ -0,0 +1,49 @@
+import { describe, beforeEach, jest, test, expect, afterEach } from '@jest/globals';
+
+import { FileMockUtilities, getMockConstants, MAX_FAST_TIME, MockConstants, mockInquire } from '../../__testing__';
+import { FullyParsedDockerService, getDockerServices } from '../../docker';
+import { InquirerUtilities } from '../../encapsulation';
+import { DownCommand } from '../down';
+import { UpCommand } from './up.command';
+
+const mockConstants: MockConstants = getMockConstants('up-command');
+
+describe('UpCommand', () => {
+ beforeEach(async () => {
+ await FileMockUtilities.setup(mockConstants, undefined, {
+ DEV_DOCKER_COMPOSE_YAML: [
+ 'services:',
+ '',
+ ' adminer:',
+ ' image: adminer',
+ ' restart: unless-stopped',
+ ' ports:',
+ ' - 8080:8080'
+ ]
+ });
+ InquirerUtilities['inquire'] = jest.fn(mockInquire({
+ env: 'dev.docker-compose.yaml'
+ }));
+ });
+
+ test('should run', async () => {
+ const runningDockerServicesBeforeUp: FullyParsedDockerService[] = await getDockerServices(false);
+
+ const upCommand: UpCommand = new UpCommand();
+ await upCommand.start(['u']);
+
+ const runningDockerServicesAfterUp: FullyParsedDockerService[] = await getDockerServices(false);
+ expect(runningDockerServicesBeforeUp.length + 1).toEqual(runningDockerServicesAfterUp.length);
+
+ const command: DownCommand = new DownCommand();
+ await command.start(['d']);
+
+ const runningDockerServicesAfterDown: FullyParsedDockerService[] = await getDockerServices(false);
+
+ expect(runningDockerServicesAfterDown.length).toEqual(runningDockerServicesBeforeUp.length);
+ }, MAX_FAST_TIME * 2 /** We call up and down. */);
+
+ afterEach(() => {
+ jest.restoreAllMocks();
+ });
+});
\ No newline at end of file
diff --git a/src/commands/version/version-command.test.ts b/src/commands/version/version-command.test.ts
new file mode 100644
index 0000000..7e916ba
--- /dev/null
+++ b/src/commands/version/version-command.test.ts
@@ -0,0 +1,18 @@
+import { beforeEach, describe, expect, test } from '@jest/globals';
+
+import { VersionCommand } from './version.command';
+import { FileMockUtilities, getMockConstants, MAX_INSTANT_TIME, MockConstants } from '../../__testing__';
+
+const mockConstants: MockConstants = getMockConstants('version-command');
+
+describe('VersionCommand', () => {
+ beforeEach(async () => {
+ await FileMockUtilities.setup(mockConstants);
+ });
+
+ test('should run', async () => {
+ const command: VersionCommand = new VersionCommand();
+ await command.start(['v']);
+ expect(true).toBe(true);
+ }, MAX_INSTANT_TIME);
+});
\ No newline at end of file
diff --git a/src/constants.ts b/src/constants.ts
index cfbc12a..317f884 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -86,6 +86,11 @@ export const TAILWIND_CONFIG_FILE_NAME: string = 'tailwind.config.js';
*/
export const TS_CONFIG_FILE_NAME: string = 'tsconfig.json';
+/**
+ * The name of the base ts config file.
+ */
+export const BASE_TS_CONFIG_FILE_NAME: string = 'tsconfig.base.json';
+
/**
* The name of the angular json file.
*/
diff --git a/src/db/db-utilities.test.ts b/src/db/db-utilities.test.ts
index 9e74266..6558e46 100644
--- a/src/db/db-utilities.test.ts
+++ b/src/db/db-utilities.test.ts
@@ -12,10 +12,7 @@ const mockConstants: MockConstants = getMockConstants('db-utilities');
describe('DbUtilities', () => {
beforeEach(async () => {
- await FileMockUtilities.setup(
- mockConstants,
- ['DOCKER_COMPOSE_YAML', 'DEV_DOCKER_COMPOSE_YAML', 'LOCAL_DOCKER_COMPOSE_YAML', 'ENV', 'GLOBAL_ENV_MODEL']
- );
+ await FileMockUtilities.setup(mockConstants);
});
test('createPostgresDatabase', async () => {
diff --git a/src/docker/docker-utilities.test.ts b/src/docker/docker-utilities.test.ts
index 3994a4b..28fd8b0 100644
--- a/src/docker/docker-utilities.test.ts
+++ b/src/docker/docker-utilities.test.ts
@@ -11,7 +11,7 @@ const mockConstants: MockConstants = getMockConstants('docker-utilities');
describe('DockerUtilities', () => {
beforeEach(async () => {
- await FileMockUtilities.setup(mockConstants);
+ await FileMockUtilities.setup(mockConstants, []);
const fakeEmail: string = faker.internet.email();
await EnvUtilities.init('test.com');
diff --git a/src/encapsulation/cp.utilities.ts b/src/encapsulation/cp.utilities.ts
index 22d478c..5403432 100644
--- a/src/encapsulation/cp.utilities.ts
+++ b/src/encapsulation/cp.utilities.ts
@@ -8,6 +8,9 @@ import { exitWithInterrupt, isErrorWithSignal, isExitPromptError } from '../util
*/
export abstract class CPUtilities {
+ /**
+ * Used only for testing/mocking.
+ */
// eslint-disable-next-line typescript/prefer-readonly
private static cwd?: string;
diff --git a/src/env/env-utilities.test.ts b/src/env/env-utilities.test.ts
index 9eab12a..603b54c 100644
--- a/src/env/env-utilities.test.ts
+++ b/src/env/env-utilities.test.ts
@@ -1,4 +1,3 @@
-
import { beforeEach, describe, expect, test } from '@jest/globals';
import { fakeEnvVariable, FileMockUtilities, getMockConstants, MockConstants } from '../__testing__';
@@ -13,13 +12,13 @@ const mockConstants: MockConstants = getMockConstants('env-utilities');
describe('EnvUtilities', () => {
beforeEach(async () => {
- await FileMockUtilities.setup(mockConstants);
+ await FileMockUtilities.setup(mockConstants, []);
await EnvUtilities.init('test.com');
});
test('addStaticVariable', async () => {
for (let i: number = 0; i < 50; i++) {
- await FileMockUtilities.setup(mockConstants);
+ await FileMockUtilities.setup(mockConstants, []);
await EnvUtilities.init('test.com');
const variable: EnvVariable = fakeEnvVariable();
diff --git a/src/loopback/loopback.utilities.test.ts b/src/loopback/loopback.utilities.test.ts
index e155ac8..0ffae3e 100644
--- a/src/loopback/loopback.utilities.test.ts
+++ b/src/loopback/loopback.utilities.test.ts
@@ -31,5 +31,5 @@ describe('LoopbackUtilities', () => {
const dirExists: boolean = await FsUtilities.exists(getPath(mockConstants.APPS_DIR, 'api'));
expect(dirExists).toBe(true);
- }, 80000);
+ }, 50000);
});
\ No newline at end of file
diff --git a/src/nest/nest-utilities.test.ts b/src/nest/nest-utilities.test.ts
new file mode 100644
index 0000000..4d6d00d
--- /dev/null
+++ b/src/nest/nest-utilities.test.ts
@@ -0,0 +1,26 @@
+import { beforeEach, describe, expect, test } from '@jest/globals';
+
+import { FileMockUtilities, getMockConstants, MockConstants } from '../__testing__';
+import { FsUtilities } from '../encapsulation';
+import { getPath } from '../utilities';
+import { NestUtilities } from './nest.utilities';
+
+const mockConstants: MockConstants = getMockConstants('nest-utilities');
+
+describe('NestUtilities', () => {
+ beforeEach(async () => {
+ await FileMockUtilities.setup(mockConstants);
+ });
+
+ test('run new command', async () => {
+ NestUtilities.runCommand(mockConstants.APPS_DIR, 'new api', {
+ '--language': 'TS',
+ '--package-manager': 'npm',
+ '--skip-git': true,
+ '--skip-install': true
+ });
+
+ const dirExists: boolean = await FsUtilities.exists(getPath(mockConstants.APPS_DIR, 'api'));
+ expect(dirExists).toBe(true);
+ }, 50000);
+});
\ No newline at end of file
diff --git a/src/npm/npm-utilities.test.ts b/src/npm/npm-utilities.test.ts
index afb7fce..56ce27d 100644
--- a/src/npm/npm-utilities.test.ts
+++ b/src/npm/npm-utilities.test.ts
@@ -1,6 +1,6 @@
import { beforeEach, describe, expect, test } from '@jest/globals';
-import { fakeUpdatePackageJsonData, FileMockUtilities, getMockConstants, MockConstants } from '../__testing__';
+import { fakeUpdatePackageJsonData, FileMockUtilities, getMockConstants, MAX_ADD_TIME, MockConstants } from '../__testing__';
import { NpmUtilities } from './npm.utilities';
import { FsUtilities } from '../encapsulation';
import { PackageJson } from './package-json.model';
@@ -9,7 +9,7 @@ const mockConstants: MockConstants = getMockConstants('npm-utilities');
describe('NpmUtilities', () => {
beforeEach(async () => {
- await FileMockUtilities.setup(mockConstants, ['ROOT_PACKAGE_JSON']);
+ await FileMockUtilities.setup(mockConstants);
});
test('init', async () => {
@@ -29,7 +29,7 @@ describe('NpmUtilities', () => {
' "description": ""',
'}'
]);
- });
+ }, MAX_ADD_TIME);
test('updatePackageJsonFile', async () => {
const updateData: Partial = fakeUpdatePackageJsonData();
diff --git a/src/npm/npm.utilities.ts b/src/npm/npm.utilities.ts
index 79b8c9b..7134cfd 100644
--- a/src/npm/npm.utilities.ts
+++ b/src/npm/npm.utilities.ts
@@ -58,13 +58,18 @@ export abstract class NpmUtilities {
}
/**
- * Runs the given npm script in the project with the provided name.
- * @param projectName - The project to run the npm script in.
- * @param commands - The npm script to run.
+ * Runs the given npm command in the project with the provided name.
+ * @param projectName - The project to run the npm command in.
+ * @param commands - The npm command to run.
+ * @param isNativeCommand - Whether or not the npm command is native (like "install") or a custom script defined in the package.json.
*/
- static async run(projectName: string, commands: string): Promise {
+ static async run(projectName: string, commands: string, isNativeCommand: boolean): Promise {
const project: WorkspaceProject = await WorkspaceUtilities.findProjectOrFail(projectName, getPath('.'));
- CPUtilities.execSync(`npm run ${commands} --workspace=${project.npmWorkspaceString}`);
+ if (!isNativeCommand) {
+ CPUtilities.execSync(`npm run ${commands} --workspace=${project.npmWorkspaceString}`);
+ return;
+ }
+ CPUtilities.execSync(`npm ${commands} --workspace=${project.npmWorkspaceString}`);
}
/**
@@ -82,10 +87,8 @@ export abstract class NpmUtilities {
* @param development - Whether or not the packages will be installed with -D or not.
*/
static async install(projectName: string, npmPackages: NpmPackage[], development: boolean = false): Promise {
- const project: WorkspaceProject = await WorkspaceUtilities.findProjectOrFail(projectName, getPath('.'));
-
- const installCommand: string = development ? 'npm i -D' : 'npm i';
- CPUtilities.execSync(`cd ${project.path} && ${installCommand} ${npmPackages.join(' ')}`);
+ const installCommand: string = development ? 'i -D' : 'i';
+ await this.run(projectName, `${installCommand} ${npmPackages.join(' ')}`, true);
}
/**
diff --git a/src/storybook/storybook-utilities.test.ts b/src/storybook/storybook-utilities.test.ts
new file mode 100644
index 0000000..6f71e79
--- /dev/null
+++ b/src/storybook/storybook-utilities.test.ts
@@ -0,0 +1,17 @@
+
+import { beforeEach, describe, expect, test } from '@jest/globals';
+
+import { FileMockUtilities, getMockConstants, MockConstants } from '../__testing__';
+
+const mockConstants: MockConstants = getMockConstants('storybook-utilities');
+
+describe('StorybookUtilities', () => {
+
+ beforeEach(async () => {
+ await FileMockUtilities.setup(mockConstants);
+ });
+
+ test('TODO', () => {
+ expect(true).toBe(true);
+ });
+});
\ No newline at end of file
diff --git a/src/tsconfig/tsconfig-utilities.test.ts b/src/tsconfig/tsconfig-utilities.test.ts
index 1319217..4948d79 100644
--- a/src/tsconfig/tsconfig-utilities.test.ts
+++ b/src/tsconfig/tsconfig-utilities.test.ts
@@ -1,9 +1,8 @@
-
import { beforeEach, describe, expect, test } from '@jest/globals';
-import { FileMockUtilities, getMockConstants, MockConstants } from '../__testing__';
+import { defaultFoldersToMock, FileMockUtilities, getMockConstants, MockConstants } from '../__testing__';
import { TsConfigUtilities } from './tsconfig.utilities';
-import { TS_CONFIG_FILE_NAME } from '../constants';
+import { BASE_TS_CONFIG_FILE_NAME, TS_CONFIG_FILE_NAME } from '../constants';
import { FsUtilities } from '../encapsulation';
import { TsConfig } from './tsconfig.model';
import { getPath, Path } from '../utilities';
@@ -12,7 +11,12 @@ const mockConstants: MockConstants = getMockConstants('tsconfig-utilities');
describe('TsConfigUtilities', () => {
beforeEach(async () => {
- await FileMockUtilities.setup(mockConstants);
+ await FileMockUtilities.setup(
+ mockConstants,
+ undefined,
+ undefined,
+ [...defaultFoldersToMock, 'TS_LIBRARY_DIR']
+ );
});
test('init', async () => {
@@ -34,7 +38,7 @@ describe('TsConfigUtilities', () => {
TsConfigUtilities.init(mockConstants.TS_LIBRARY_DIR);
const tsconfigPath: Path = getPath(mockConstants.TS_LIBRARY_DIR, TS_CONFIG_FILE_NAME);
await TsConfigUtilities['update'](tsconfigPath, {
- extends: '../../tsconfig.base.json',
+ extends: `../../${BASE_TS_CONFIG_FILE_NAME}`,
compilerOptions: {
composite: true,
declaration: true,
@@ -45,7 +49,7 @@ describe('TsConfigUtilities', () => {
});
const content: TsConfig = await FsUtilities.parseFileAs(tsconfigPath);
expect(content).toEqual({
- extends: '../../tsconfig.base.json',
+ extends: `../../${BASE_TS_CONFIG_FILE_NAME}`,
compilerOptions: {
composite: true,
declaration: true,
diff --git a/src/tsconfig/tsconfig.utilities.ts b/src/tsconfig/tsconfig.utilities.ts
index ef64390..15fa8d0 100644
--- a/src/tsconfig/tsconfig.utilities.ts
+++ b/src/tsconfig/tsconfig.utilities.ts
@@ -3,7 +3,7 @@ import { ModuleKind, ModuleResolutionKind, ScriptTarget } from 'typescript';
import { CPUtilities, FsUtilities, JsonUtilities } from '../encapsulation';
import { WorkspaceProject, WorkspaceUtilities } from '../workspace';
import { TsConfig } from './tsconfig.model';
-import { TS_CONFIG_FILE_NAME } from '../constants';
+import { BASE_TS_CONFIG_FILE_NAME, TS_CONFIG_FILE_NAME } from '../constants';
import { getPath, mergeDeep, Path } from '../utilities';
/**
@@ -50,7 +50,7 @@ export abstract class TsConfigUtilities {
},
exclude: ['node_modules', 'tmp', 'dist']
};
- await FsUtilities.createFile(getPath('tsconfig.base.json'), JsonUtilities.stringify(tsconfig));
+ await FsUtilities.createFile(getPath(BASE_TS_CONFIG_FILE_NAME), JsonUtilities.stringify(tsconfig));
}
/**
@@ -69,7 +69,7 @@ export abstract class TsConfigUtilities {
* @param data - The data to update the tsconfig with.
*/
static async updateBaseTsConfig(data: Partial): Promise {
- await this.update(getPath('tsconfig.base.json'), data);
+ await this.update(getPath(BASE_TS_CONFIG_FILE_NAME), data);
}
private static async update(path: Path, data: Partial): Promise {
diff --git a/src/workspace/workspace-utilities.test.ts b/src/workspace/workspace-utilities.test.ts
new file mode 100644
index 0000000..228e72f
--- /dev/null
+++ b/src/workspace/workspace-utilities.test.ts
@@ -0,0 +1,40 @@
+import { beforeEach, describe, expect, test } from '@jest/globals';
+
+import { FileMockUtilities, getMockConstants, MAX_INSTANT_TIME, MockConstants } from '../__testing__';
+import { WorkspaceConfig } from './workspace-config.model';
+import { WorkspaceProject, WorkspaceUtilities } from './workspace.utilities';
+import { FsUtilities } from '../encapsulation';
+import { getPath } from '../utilities';
+
+const mockConstants: MockConstants = getMockConstants('workspace-utilities');
+
+describe('WorkspaceUtilities', () => {
+ beforeEach(async () => {
+ await FileMockUtilities.setup(mockConstants, []);
+ });
+
+ test('create config', async () => {
+ const initialConfig: WorkspaceConfig | undefined = await WorkspaceUtilities.getConfig();
+ expect(initialConfig).toEqual(undefined);
+
+ await WorkspaceUtilities.createConfig();
+ const config: WorkspaceConfig = await WorkspaceUtilities.getConfigOrFail();
+ expect(config.name).toEqual('workspace-utilities');
+ }, MAX_INSTANT_TIME);
+
+ test('get projects', async () => {
+ const projectsBefore: WorkspaceProject[] = await WorkspaceUtilities.getProjects('all', getPath('.'));
+ expect(projectsBefore.length).toEqual(0);
+
+ await FsUtilities.mkdir(mockConstants.ANGULAR_APP_DIR);
+
+ const allProjects: WorkspaceProject[] = await WorkspaceUtilities.getProjects('all', getPath('.'));
+ expect(allProjects.length).toEqual(1);
+
+ const appProjects: WorkspaceProject[] = await WorkspaceUtilities.getProjects('apps', getPath('.'));
+ expect(appProjects.length).toEqual(1);
+
+ const libProjects: WorkspaceProject[] = await WorkspaceUtilities.getProjects('libs', getPath('.'));
+ expect(libProjects.length).toEqual(0);
+ }, MAX_INSTANT_TIME);
+});
\ No newline at end of file