Skip to content

Commit

Permalink
add tests and improve lint
Browse files Browse the repository at this point in the history
  • Loading branch information
BioPhoton committed Sep 10, 2024
1 parent 5f26987 commit bfa7888
Show file tree
Hide file tree
Showing 28 changed files with 461 additions and 14 deletions.
47 changes: 44 additions & 3 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,52 @@
"error",
{
"enforceBuildableLibDependency": true,
"allow": [],
"allow": ["tools"],
"depConstraints": [
{
"sourceTag": "*",
"onlyDependOnLibsWithTags": ["*"]
"sourceTag": "scope:shared",
"onlyDependOnLibsWithTags": ["scope:shared"]
},
{
"sourceTag": "scope:core",
"onlyDependOnLibsWithTags": ["scope:core", "scope:shared"]
},
{
"sourceTag": "type:e2e",
"onlyDependOnLibsWithTags": [
"type:app",
"type:feature",
"type:util",
"type:testing"
]
},
{
"sourceTag": "type:app",
"onlyDependOnLibsWithTags": [
"type:feature",
"type:util",
"type:testing"
]
},
{
"sourceTag": "type:feature",
"onlyDependOnLibsWithTags": [
"type:feature",
"type:util",
"type:testing"
]
},
{
"sourceTag": "type:util",
"onlyDependOnLibsWithTags": ["type:util", "type:testing"]
},
{
"sourceTag": "type:testing",
"onlyDependOnLibsWithTags": ["type:util", "type:testing"]
},
{
"sourceTag": "type:tooling",
"onlyDependOnLibsWithTags": ["type:testing"]
}
]
}
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/ci-examples.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ jobs:
- name: Install dependencies
run: npm i
- name: pretarget E2E test project
run: npx nx run cli-e2e-pretarget:pretarget-e2e
run: npx nx run cli-e2e-pretarget:pretarget-e2e --parallel 1
- name: graph E2E test project
run: npx nx run cli-e2e-graph:graph-e2e
run: npx nx run cli-e2e-graph:graph-e2e --parallel 1
- name: env E2E test project
run: npx nx run cli-e2e-env:env-e2e
run: npx nx run cli-e2e-env:env-e2e --parallel 1
- name: Original E2E test project
run: npx nx run cli-e2e-original:original-e2e
run: npx nx run cli-e2e-original:original-e2e --parallel 1
3 changes: 2 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,5 @@ jobs:
- name: Install dependencies
run: npm i
- name: E2E test all projects with buildable environmnets
run: npx nx run-many -t e2e --parallel 10
# run-many is only used to trigger the e2e tasks on every PR. affected would be a real life implementation
run: npx nx run-many -t e2e --parallel 1
12 changes: 12 additions & 0 deletions testing/test-setup/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"parserOptions": {
"project": ["testing/test-setup/tsconfig.*?.json"]
}
}
]
}
16 changes: 16 additions & 0 deletions testing/test-setup/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# test-setup

This library contains test setup.

## Mock setup

In this library you can find all files that can be used in `setupFiles` property of `vitest.config.(unit|integration|e2e).ts` files. Currently include:

- [console](./src/lib/console.mock.ts) mocking
- [file system](./src/lib/fs.mock.ts) mocking
- [reset](./src/lib/reset.mock.ts) mocking

Additionally, you may find helper functions for:

- setting up and tearing down a [testing folder](./src/lib/test-folder.setup.ts)
- [resetting](./src/lib/reset.mocks.ts) mocks
16 changes: 16 additions & 0 deletions testing/test-setup/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "test-setup",
"$schema": "../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "testing/test-setup/src",
"projectType": "library",
"targets": {
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["testing/test-setup/**/*.ts"]
}
}
},
"tags": ["scope:shared", "type:testing"]
}
29 changes: 29 additions & 0 deletions testing/test-setup/src/lib/console.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { type MockInstance, afterEach, beforeEach, vi } from 'vitest';

let consoleInfoSpy: MockInstance<unknown[], void> | undefined;
let consoleWarnSpy: MockInstance<unknown[], void> | undefined;
let consoleErrorSpy: MockInstance<unknown[], void> | undefined;

beforeEach(() => {
// In multi-progress-bars, console methods are overriden
if (console.info != null) {
// eslint-disable-next-line @typescript-eslint/no-empty-function
consoleInfoSpy = vi.spyOn(console, 'info').mockImplementation(() => {});
}

if (console.warn != null) {
// eslint-disable-next-line @typescript-eslint/no-empty-function
consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
}

if (console.error != null) {
// eslint-disable-next-line @typescript-eslint/no-empty-function
consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
}
});

afterEach(() => {
consoleInfoSpy?.mockRestore();
consoleWarnSpy?.mockRestore();
consoleErrorSpy?.mockRestore();
});
21 changes: 21 additions & 0 deletions testing/test-setup/src/lib/fs.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { type MockInstance, afterEach, beforeEach, vi } from 'vitest';
import { MEMFS_VOLUME } from '@org/test-utils';

vi.mock('fs', async () => {
const memfs: typeof import('memfs') = await vi.importActual('memfs');
return memfs.fs;
});
vi.mock('fs/promises', async () => {
const memfs: typeof import('memfs') = await vi.importActual('memfs');
return memfs.fs.promises;
});

let cwdSpy: MockInstance<[], string>;

beforeEach(() => {
cwdSpy = vi.spyOn(process, 'cwd').mockReturnValue(MEMFS_VOLUME);
});

afterEach(() => {
cwdSpy.mockRestore();
});
7 changes: 7 additions & 0 deletions testing/test-setup/src/lib/reset.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { vol } from 'memfs';
import { beforeEach, vi } from 'vitest';

beforeEach(() => {
vi.clearAllMocks();
vol.reset();
});
19 changes: 19 additions & 0 deletions testing/test-setup/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"module": "ESNext",
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
}
]
}
10 changes: 10 additions & 0 deletions testing/test-setup/tsconfig.lib.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../dist/out-tsc",
"declaration": true,
"types": ["node"]
},
"include": ["src/**/*.ts"],
"exclude": []
}
36 changes: 36 additions & 0 deletions testing/test-utils/mock/execute-process.mock.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const interval = parseInt(process.argv[2] || 100);
let runs = parseInt(process.argv[3] || 4);
let throwError = process.argv[4] === '1';

/**
* Custom runner implementation that simulates asynchronous situations.
* It logs progress to the console with a configurable interval and defaults to 100ms.
* The number of runs is also configurable and defaults to 4.
* We can decide if the process should error or complete. By default, it completes.
*
* @arg interval: number - delay between updates in ms; defaults to 100
* @arg runs: number - number of updates; defaults to 4
* @arg throwError: '1' | '0' - if the process completes or throws; defaults to '0'
**/
(async () => {
console.info(
`process:start with interval: ${interval}, runs: ${runs}, throwError: ${throwError}`
);
await new Promise((resolve) => {
const id = setInterval(() => {
if (runs === 0) {
clearInterval(id);
if (throwError) {
throw new Error('dummy-error');
} else {
resolve('result');
}
} else {
runs--;
console.info('process:update');
}
}, interval);
});

console.info('process:complete');
})();
2 changes: 1 addition & 1 deletion testing/test-utils/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "projects/test-utils/src",
"projectType": "library",
"tags": ["scope:utils", "type:testing-util"],
"tags": ["scope:shared", "type:testing"],
"targets": {
"build": {
"executor": "@nx/esbuild:esbuild",
Expand Down
3 changes: 3 additions & 0 deletions testing/test-utils/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
export * from './lib/execute-process';
export * from './lib/terminal-command';
export * from './lib/setup';
export * from './lib/execute-process-helper.mock';
export * from './lib/test-folder.setup';
export * from './lib/constants';
1 change: 1 addition & 0 deletions testing/test-utils/src/lib/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const MEMFS_VOLUME = '/test';
22 changes: 22 additions & 0 deletions testing/test-utils/src/lib/execute-process-helper.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { join } from 'path';

const asyncProcessPath = join(__dirname, '../../mock/execute-process.mock.mjs');

/**
* Helps to get an async process runner config for testing.
*
* @param cfg can contain up to three properties for the async process runner
*/
export function getAsyncProcessRunnerConfig(cfg?: {
throwError?: boolean;
interval?: number;
runs?: number;
}) {
const args = [
asyncProcessPath,
cfg?.interval ? cfg.interval + '' : '100',
cfg?.runs ? cfg.runs + '' : '4',
cfg?.throwError ? '1' : '0',
];
return { command: 'node', args };
}
14 changes: 14 additions & 0 deletions testing/test-utils/src/lib/test-folder.setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { mkdir, rm } from 'node:fs/promises';

export async function setupTestFolder(dirName: string) {
await mkdir(dirName, { recursive: true });
}

export async function cleanTestFolder(dirName: string) {
await rm(dirName, { recursive: true, force: true });
await mkdir(dirName, { recursive: true });
}

export async function teardownTestFolder(dirName: string) {
await rm(dirName, { recursive: true, force: true });
}
4 changes: 3 additions & 1 deletion tooling/build-env/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
"vite": "~5.0.0",
"@nx/vite": "18.2.4",
"tslib": "^2.3.0",
"nx": "18.2.4"
"nx": "18.2.4",
"vitest": "^1.3.1",
"test-utils": "*"
},
"type": "commonjs",
"main": "./src/index.js",
Expand Down
2 changes: 1 addition & 1 deletion tooling/build-env/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,5 @@
}
}
},
"tags": ["scope:tooling"]
"tags": ["scope:shared", "type:tooling"]
}
Loading

0 comments on commit bfa7888

Please sign in to comment.