Skip to content

Commit d9a415f

Browse files
authored
Merge pull request #98 from Service-Soft/81-testing-e2e-does-not-finish
Added tests to check if commands actually finish without errors, adde…
2 parents a74ce23 + c898c65 commit d9a415f

48 files changed

Lines changed: 760 additions & 121 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ jobs:
1414
test:
1515
runs-on: ubuntu-latest
1616
steps:
17+
-
18+
name: Set up Docker Compose
19+
uses: docker/setup-compose-action@v1
1720
- uses: actions/checkout@v4
1821
- run: npm ci
1922
- run: npm run build

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ The projects that can be added to a Monux monorepo also provide a lot of functio
6262
- [Angular website](#angular-website)
6363
- [Angular library](#angular-library)
6464
- [LoopBack](#loopback)
65+
- [Nest](#nest)
6566
- [Typescript library](#typescript-library)
6667
- [Wordpress](#wordpress)
6768
- [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
301302
## Angular website
302303
## Angular library
303304
## LoopBack
305+
## Nest
304306
## Typescript library
305307
## Wordpress
306308
## Add projects manually
307309
One of the reasons that Monux was created was the amount of abstraction layers added by tools like Nx.<br>
308310
The magic was really cool as long as everything worked, but made debugging issues much harder.
309311

310-
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).
312+
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).
311313

312314
Because of that it should be fairly simple to add any project/framework/library manually by just taking a look at existing projects.
313315

jest.config.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ const config = {
1212
modulePathIgnorePatterns: ['tmp'],
1313
// coverage
1414
collectCoverage: true,
15+
coverageProvider: 'v8',
1516
coverageDirectory: '<rootDir>/__testing__/coverage',
1617
coveragePathIgnorePatterns: [
1718
'/node_modules/',

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "monux-cli",
3-
"version": "2.2.2",
3+
"version": "2.2.3",
44
"license": "MIT",
55
"main": "index.js",
66
"engines": {
@@ -33,10 +33,10 @@
3333
"start": "npm run build && cd sandbox && node ../dist/index.js",
3434
"build": "tsc",
3535
"clear": "rm -rf sandbox && mkdir sandbox && npm run start i",
36-
"test": "node --max_old_space_size=4096 ./node_modules/jest/bin/jest.js",
36+
"test": "jest --runInBand",
3737
"lint": "eslint . --max-warnings=0",
3838
"lint:fix": "eslint . --max-warnings=0 --fix",
39-
"prepublishOnly": "npm i && npm run lint && npm run build"
39+
"prepublishOnly": "npm i && npm run build"
4040
},
4141
"dependencies": {
4242
"chalk": "^4.1.2",

src/__testing__/mock/constants.ts

Lines changed: 16 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,53 @@
1-
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';
1+
/* eslint-disable jsdoc/require-jsdoc */
2+
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';
23
import { OmitStrict } from '../../types';
34
import { getPath, Path } from '../../utilities';
45

5-
// eslint-disable-next-line jsdoc/require-jsdoc
6+
export const MAX_ADD_TIME: number = 60000;
7+
8+
export const MAX_GEN_CODE_TIME: number = 10000;
9+
10+
export const MAX_FAST_TIME: number = 300;
11+
12+
export const MAX_INSTANT_TIME: number = 100;
13+
614
export type MockConstants = {
7-
// eslint-disable-next-line jsdoc/require-jsdoc
815
readonly PROJECT_DIR: Path,
9-
// eslint-disable-next-line jsdoc/require-jsdoc
1016
readonly APPS_DIR: Path,
11-
// eslint-disable-next-line jsdoc/require-jsdoc
1217
readonly LIBS_DIR: Path,
13-
// eslint-disable-next-line jsdoc/require-jsdoc
1418
readonly DOCKER_COMPOSE_YAML: Path,
15-
// eslint-disable-next-line jsdoc/require-jsdoc
1619
readonly DEV_DOCKER_COMPOSE_YAML: Path,
17-
// eslint-disable-next-line jsdoc/require-jsdoc
1820
readonly LOCAL_DOCKER_COMPOSE_YAML: Path,
19-
// eslint-disable-next-line jsdoc/require-jsdoc
2021
readonly ANGULAR_ESLINT_CONFIG_MJS: Path,
21-
// eslint-disable-next-line jsdoc/require-jsdoc
2222
readonly ANGULAR_PACKAGE_JSON: Path,
23-
// eslint-disable-next-line jsdoc/require-jsdoc
2423
readonly ANGULAR_APP_NAME: string,
25-
// eslint-disable-next-line jsdoc/require-jsdoc
2624
readonly ANGULAR_APP_DIR: Path,
27-
// eslint-disable-next-line jsdoc/require-jsdoc
2825
readonly ANGULAR_APP_COMPONENT_TS: Path,
29-
// eslint-disable-next-line jsdoc/require-jsdoc
3026
readonly ANGULAR_APP_COMPONENT_HTML: Path,
31-
// eslint-disable-next-line jsdoc/require-jsdoc
3227
readonly ANGULAR_APP_ROUTES_TS: Path,
33-
// eslint-disable-next-line jsdoc/require-jsdoc
3428
readonly ANGULAR_ROUTES_TS: Path,
35-
// eslint-disable-next-line jsdoc/require-jsdoc
3629
readonly ANGULAR_APP_CONFIG_TS: Path,
37-
// eslint-disable-next-line jsdoc/require-jsdoc
3830
readonly ANGULAR_JSON: Path,
39-
// eslint-disable-next-line jsdoc/require-jsdoc
4031
readonly ANGULAR_ENVIRONMENT_MODEL: Path,
41-
// eslint-disable-next-line jsdoc/require-jsdoc
4232
readonly ANGULAR_ENVIRONMENT: Path,
43-
// eslint-disable-next-line jsdoc/require-jsdoc
4433
readonly TS_LIBRARY_DIR: Path,
45-
// eslint-disable-next-line jsdoc/require-jsdoc
4634
readonly TS_LIBRARY_SCOPE: string,
47-
// eslint-disable-next-line jsdoc/require-jsdoc
4835
readonly TS_LIBRARY_PACKAGE_JSON: Path,
49-
// eslint-disable-next-line jsdoc/require-jsdoc
5036
readonly ROOT_PACKAGE_JSON: Path,
51-
// eslint-disable-next-line jsdoc/require-jsdoc
5237
readonly TS_LIBRARY_NAME: string,
53-
// eslint-disable-next-line jsdoc/require-jsdoc
5438
readonly ENV: Path,
55-
// eslint-disable-next-line jsdoc/require-jsdoc
5639
readonly GLOBAL_ENV_MODEL: Path,
57-
// eslint-disable-next-line jsdoc/require-jsdoc
58-
readonly GITHUB_WORKFLOW_DIR: Path
40+
readonly GITHUB_WORKFLOW_DIR: Path,
41+
readonly WORKSPACE_JSON: Path,
42+
readonly BASE_TS_CONFIG_JSON: Path
5943
};
6044

61-
// eslint-disable-next-line jsdoc/require-jsdoc
6245
export type FileMockConstants = OmitStrict<
6346
MockConstants,
6447
'ANGULAR_APP_DIR' | 'APPS_DIR' | 'LIBS_DIR' | 'PROJECT_DIR' | 'TS_LIBRARY_DIR' | 'GITHUB_WORKFLOW_DIR'
6548
| 'ANGULAR_APP_NAME' | 'TS_LIBRARY_SCOPE' | 'TS_LIBRARY_NAME'
6649
>;
6750

68-
// eslint-disable-next-line jsdoc/require-jsdoc
6951
export type DirMockConstants = OmitStrict<
7052
MockConstants,
7153
keyof FileMockConstants | 'TS_LIBRARY_NAME' | 'ANGULAR_APP_NAME' | 'TS_LIBRARY_SCOPE'
@@ -114,7 +96,9 @@ export function getMockConstants(projectName: string): MockConstants {
11496
ROOT_PACKAGE_JSON: getPath(PROJECT_DIR, PACKAGE_JSON_FILE_NAME),
11597
ENV: getPath(PROJECT_DIR, ENV_FILE_NAME),
11698
GLOBAL_ENV_MODEL: getPath(PROJECT_DIR, GLOBAL_ENVIRONMENT_MODEL_FILE_NAME),
117-
GITHUB_WORKFLOW_DIR: getPath(PROJECT_DIR, '.github', 'workflows')
99+
GITHUB_WORKFLOW_DIR: getPath(PROJECT_DIR, '.github', 'workflows'),
100+
WORKSPACE_JSON: getPath(PROJECT_DIR, WORKSPACE_FILE_NAME),
101+
BASE_TS_CONFIG_JSON: getPath(PROJECT_DIR, BASE_TS_CONFIG_FILE_NAME)
118102
} as const;
119103
return mockConstants;
120104
}

src/__testing__/mock/file-mock.utilities.ts

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,27 @@ import { MockConstants, FileMockConstants, DirMockConstants } from './constants'
33
import { AngularJson } from '../../angular';
44
import { CPUtilities, FsUtilities, JsonUtilities } from '../../encapsulation';
55
import { EnvUtilities } from '../../env';
6+
import { TsConfigUtilities } from '../../tsconfig';
67
import { getPath } from '../../utilities';
78
import { WorkspaceUtilities } from '../../workspace';
89

10+
export const defaultFilesToMock: (keyof FileMockConstants)[] = [
11+
'WORKSPACE_JSON',
12+
'BASE_TS_CONFIG_JSON',
13+
'ENV',
14+
'GLOBAL_ENV_MODEL',
15+
'ROOT_PACKAGE_JSON',
16+
'DOCKER_COMPOSE_YAML',
17+
'DEV_DOCKER_COMPOSE_YAML',
18+
'LOCAL_DOCKER_COMPOSE_YAML'
19+
] as const;
20+
21+
export const defaultFoldersToMock: (keyof DirMockConstants)[] = [
22+
'LIBS_DIR',
23+
'APPS_DIR',
24+
'PROJECT_DIR'
25+
] as const;
26+
927
export abstract class FileMockUtilities {
1028

1129
private static readonly mockMethodForFile: Record<
@@ -27,33 +45,27 @@ export abstract class FileMockUtilities {
2745
ANGULAR_ENVIRONMENT: this.createEmptyFile,
2846
TS_LIBRARY_PACKAGE_JSON: this.createEmptyFile,
2947
ROOT_PACKAGE_JSON: this.createRootPackageJson,
30-
ENV: this.createEmptyFile,
31-
GLOBAL_ENV_MODEL: this.createGlobalEnvModel
48+
ENV: this.createEnv,
49+
GLOBAL_ENV_MODEL: this.createGlobalEnvModel,
50+
WORKSPACE_JSON: WorkspaceUtilities.createConfig,
51+
BASE_TS_CONFIG_JSON: TsConfigUtilities.createBaseTsConfig
3252
};
3353

3454
static async setup(
3555
mockConstants: MockConstants,
36-
filesToMock: (keyof FileMockConstants)[] = [],
37-
contentOverrides: Partial<Record<keyof FileMockConstants, string | string[]>> = {}
56+
filesToMock: (keyof FileMockConstants)[] = defaultFilesToMock,
57+
contentOverrides: Partial<Record<keyof FileMockConstants, string | string[]>> = {},
58+
foldersToMock: (keyof DirMockConstants)[] = defaultFoldersToMock
3859
): Promise<void> {
39-
await FsUtilities.rm(getPath(mockConstants.PROJECT_DIR));
60+
await FsUtilities.rm(mockConstants.PROJECT_DIR);
4061
CPUtilities['cwd'] = mockConstants.PROJECT_DIR;
41-
await this.mockFolders(mockConstants);
62+
await this.mockFolders(foldersToMock, mockConstants);
4263
await this.mockFiles(filesToMock, contentOverrides, mockConstants);
43-
await WorkspaceUtilities.createConfig();
4464
}
4565

46-
private static async mockFolders(mockConstants: MockConstants): Promise<void> {
47-
const dirMockConstants: DirMockConstants = {
48-
ANGULAR_APP_DIR: mockConstants.ANGULAR_APP_DIR,
49-
APPS_DIR: mockConstants.APPS_DIR,
50-
LIBS_DIR: mockConstants.LIBS_DIR,
51-
PROJECT_DIR: mockConstants.PROJECT_DIR,
52-
TS_LIBRARY_DIR: mockConstants.TS_LIBRARY_DIR,
53-
GITHUB_WORKFLOW_DIR: mockConstants.GITHUB_WORKFLOW_DIR
54-
};
55-
for (const entry of Object.values(dirMockConstants)) {
56-
await FsUtilities.mkdir(getPath(entry), true, false);
66+
private static async mockFolders(foldersToMock: (keyof DirMockConstants)[], mockConstants: MockConstants): Promise<void> {
67+
for (const entry of foldersToMock) {
68+
await FsUtilities.mkdir(mockConstants[entry], true, false);
5769
}
5870
}
5971

@@ -117,7 +129,7 @@ export abstract class FileMockUtilities {
117129
private static async createRootPackageJson(mockConstants: MockConstants): Promise<void> {
118130
await FsUtilities.createFile(mockConstants.ROOT_PACKAGE_JSON, [
119131
'{',
120-
' "name": "@library/library",',
132+
' "name": "sandbox",',
121133
' "version": "1.0.0",',
122134
' "main": "index.js",',
123135
' "scripts": {',
@@ -126,7 +138,18 @@ export abstract class FileMockUtilities {
126138
' "keywords": [],',
127139
' "author": "",',
128140
' "license": "ISC",',
129-
' "description": ""',
141+
' "description": "",',
142+
' "devDependencies": {',
143+
' "autoprefixer": "^10.4.21",',
144+
' "eslint": "^9.25.1",',
145+
' "eslint-config-service-soft": "^2.0.8",',
146+
' "postcss": "^8.5.3",',
147+
' "tailwindcss": "^4.1.4"',
148+
' },',
149+
' "workspaces": [',
150+
' "apps/*",',
151+
' "libs/*"',
152+
' ]',
130153
'}'
131154
], true, false);
132155
}
@@ -176,4 +199,8 @@ export abstract class FileMockUtilities {
176199
private static async createGlobalEnvModel(): Promise<void> {
177200
await EnvUtilities['createGlobalEnvironmentModel']();
178201
}
202+
203+
private static async createEnv(mockConstants: MockConstants): Promise<void> {
204+
await FsUtilities.createFile(mockConstants.ENV, ['prod_root_domain=test.com', 'is_public=false']);
205+
}
179206
}

src/__testing__/mock/helpers/fake-unique-string.function.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { faker } from '@faker-js/faker';
33

44
const usedKeys: string[] = [];
55
export function fakeUniqueString(): string {
6-
const key: string = faker.string.alpha({ length: { min: 1, max: 20 }, exclude: usedKeys });
6+
const key: string = faker.string.alpha({ length: { min: 2, max: 20 }, exclude: usedKeys });
77
usedKeys.push(key);
88
return key;
99
}

src/angular/angular-utilities.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { afterEach, beforeEach, describe, expect, jest, test } from '@jest/globals';
22

33
import { AngularUtilities } from './angular.utilities';
4-
import { fakeAddNavElementConfig, fakeTsImportDefinition, FileMockUtilities, getMockConstants, MockConstants } from '../__testing__';
4+
import { fakeAddNavElementConfig, fakeTsImportDefinition, FileMockUtilities, getMockConstants, MAX_GEN_CODE_TIME, MockConstants } from '../__testing__';
55
import { CPUtilities, FsUtilities } from '../encapsulation';
66
import { NpmUtilities } from '../npm';
77
import { TsImportDefinition } from '../ts';
@@ -255,7 +255,7 @@ describe('AngularUtilities', () => {
255255
'',
256256
'export const routes: NavRoute[] = NavUtilities.getAngularRoutes(navbarRows, footerRows, [notFoundRoute]);'
257257
]);
258-
}, 20000);
258+
}, MAX_GEN_CODE_TIME);
259259

260260
test('generatePage for footer', async () => {
261261
await AngularUtilities.setupNavigation(mockConstants.ANGULAR_APP_DIR, mockConstants.ANGULAR_APP_NAME);
@@ -319,7 +319,7 @@ describe('AngularUtilities', () => {
319319
'',
320320
'export const routes: NavRoute[] = NavUtilities.getAngularRoutes(navbarRows, footerRows, [notFoundRoute]);'
321321
]);
322-
}, 10000);
322+
}, MAX_GEN_CODE_TIME);
323323

324324
test('addPwaSupport', async () => {
325325
await AngularUtilities.setupPwa(mockConstants.ANGULAR_APP_DIR, mockConstants.ANGULAR_APP_NAME);

src/angular/angular.utilities.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -799,7 +799,6 @@ export abstract class AngularUtilities {
799799
{ defaultImport: false, element: 'OfflineService', path: './services/offline.service' }
800800
]
801801
);
802-
// TODO: enable OfflineRequestInterceptor. Need to fix parsing of provideServiceWorker first.
803802
await this.addProvider(
804803
root,
805804
// eslint-disable-next-line typescript/no-unsafe-assignment, typescript/no-explicit-any
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { afterEach, beforeEach, describe, expect, jest, test } from '@jest/globals';
2+
3+
import { FileMockUtilities, getMockConstants, MAX_ADD_TIME, MockConstants, mockInquire } from '../../../__testing__';
4+
import { InquirerUtilities } from '../../../encapsulation';
5+
import { AddConfiguration, AddType } from '../models';
6+
import { AddAngularLibraryCommand } from './add-angular-library.command';
7+
8+
const mockConstants: MockConstants = getMockConstants('add-angular-library-command');
9+
10+
describe('AddAngularLibraryCommand', () => {
11+
beforeEach(async () => {
12+
await FileMockUtilities.setup(mockConstants);
13+
InquirerUtilities['inquire'] = jest.fn(mockInquire({
14+
scope: '@sandbox'
15+
}));
16+
});
17+
18+
test('should run', async () => {
19+
const baseConfig: AddConfiguration = { name: 'ui', type: AddType.ANGULAR_LIBRARY };
20+
const command: AddAngularLibraryCommand = new AddAngularLibraryCommand(baseConfig);
21+
await command.run();
22+
expect(true).toBe(true);
23+
}, MAX_ADD_TIME);
24+
25+
afterEach(() => {
26+
jest.restoreAllMocks();
27+
});
28+
});

0 commit comments

Comments
 (0)