Skip to content

Commit 02e8d60

Browse files
committed
feat(custom-esbuild): add unit-test builder
1 parent ae2a34f commit 02e8d60

File tree

17 files changed

+2204
-335
lines changed

17 files changed

+2204
-335
lines changed

merge-schemes.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,9 @@ for (const {
2929
(extendedSchema: any, currentExtension: any) => merge(extendedSchema, currentExtension),
3030
originalSchema
3131
);
32-
writeFileSync(newSchemaPath, JSON.stringify(newSchema, null, 2), 'utf-8');
32+
writeFileSync(newSchemaPath, JSON.stringify(newSchema, schemaValueReplacer, 2), 'utf-8');
33+
}
34+
35+
function schemaValueReplacer(key: unknown, value: unknown) {
36+
return value === '__DELETE__' ? undefined : value;
3337
}

packages/bazel/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@
3434
"ci": "node ./scripts/ci.js"
3535
},
3636
"dependencies": {
37-
"@angular-devkit/architect": ">=0.2000.0 < 0.2100.0",
37+
"@angular-devkit/architect": ">=0.2001.0 < 0.2100.0",
3838
"@bazel/bazelisk": "^1.26.0",
3939
"@bazel/ibazel": "^0.25.0"
4040
},
4141
"devDependencies": {
42-
"@angular-devkit/core": "^20.0.0",
42+
"@angular-devkit/core": "^20.1.0",
4343
"cpy-cli": "^5.0.0",
4444
"quicktype": "^15.0.260",
4545
"rimraf": "^5.0.0",

packages/common/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"clean": "rimraf dist"
2121
},
2222
"dependencies": {
23-
"@angular-devkit/core": "^20.0.0",
23+
"@angular-devkit/core": "^20.1.0",
2424
"ts-node": "^10.0.0",
2525
"tsconfig-paths": "^4.2.0"
2626
},

packages/custom-esbuild/README.md

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ Allow customizing ESBuild configuration
1313
- [Example](#example)
1414
- [Custom ESBuild `dev-server`](#custom-esbuild-dev-server)
1515
- [Example](#example)
16+
- [Custom ESBuild `unit-test`](#custom-esbuild-unit-test)
17+
- [Example](#example-1)
1618
- [Index Transform](#index-transform)
1719
- [Example](#example-2)
1820
- [ES Modules (ESM) Support](#es-modules-esm-support)
@@ -46,15 +48,15 @@ Allow customizing ESBuild configuration
4648
"architect": {
4749
...
4850
"[architect-target]": {
49-
"builder": "@angular-builders/custom-esbuild:[application|dev-server]",
51+
"builder": "@angular-builders/custom-esbuild:[application|dev-server|unit-test]",
5052
"options": {
5153
...
5254
}
5355
```
5456
Where:
5557
- [project] is the name of the project to which you want to add the builder
5658
- [architect-target] is the name of build target you want to run (build, serve, test etc. or any custom target)
57-
- [application|dev-server] one of the supported builders - [application](#Custom-webpack-browser) or [dev-server](#Custom-webpack-extract-i18n)
59+
- [application|dev-server|unit-test] one of the supported builders - [application](#Custom-esbuild-application), [dev-server](#Custom-esbuild-dev-server), or [unit-test](#Custom-esbuild-unit-test)
5860
3. If `[architect-target]` is not one of the predefined targets (like build, serve, test etc.) then run it like this:
5961
`ng run [project]:[architect-target]`
6062
If it is one of the predefined targets, you can run it with `ng [architect-target]`
@@ -81,6 +83,7 @@ Allow customizing ESBuild configuration
8183
8284
- [@angular-builders/custom-esbuild:application](#Custom-esbuild-application)
8385
- [@angular-builders/custom-esbuild:dev-server](#Custom-esbuild-dev-server)
86+
- [@angular-builders/custom-esbuild:unit-test](#Custom-esbuild-unit-test)
8487
8588
## Custom ESBuild `application`
8689
@@ -228,6 +231,35 @@ The `@angular-builders/custom-esbuild:dev-server` is an enhanced version of the
228231
}
229232
```
230233
234+
## Custom ESBuild `unit-test`
235+
236+
The `@angular-builders/custom-esbuild:unit-test` builder is an enhanced version of the `@angular/build:unit-test` builder that reuses your application ESBuild plugins during test execution. It reads the `plugins` from the referenced `:application` build target and runs the official unit test builder with those plugins applied.
237+
There is no need to specify a `runner` option as the only supported test runner is Vitest.
238+
239+
### Example-1
240+
241+
`angular.json`:
242+
243+
```js
244+
"architect": {
245+
...
246+
"build": {
247+
"builder": "@angular-builders/custom-esbuild:application",
248+
"options": {
249+
"plugins": ["./esbuild/plugin-1.js"]
250+
...
251+
}
252+
},
253+
"test": {
254+
"builder": "@angular-builders/custom-esbuild:unit-test",
255+
"options": {
256+
"buildTarget": "my-project:build",
257+
"tsConfig": "src/tsconfig.spec.json"
258+
}
259+
}
260+
}
261+
```
262+
231263
# Index Transform
232264
233265
Since Angular 8, `index.html` is not generated as part of the build. If you want to modify your `index.html`, you should use the `indexHtmlTransformer` option. `indexHtmlTransformer` is a path (relative to the workspace root) to a `.js` or `.ts` file that exports a transformation function for `index.html`. If `indexHtmlTransformer` is written in TypeScript, the application's `tsConfig` file will be used by `tsnode` for its execution:

packages/custom-esbuild/builders.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@
1010
"implementation": "./dist/dev-server",
1111
"schema": "./dist/dev-server/schema.json",
1212
"description": "Build browser app extended with custom esbuild config"
13+
},
14+
"unit-test": {
15+
"implementation": "./dist/unit-test",
16+
"schema": "./dist/unit-test/schema.json",
17+
"description": "Run unit test extended with custom esbuild config"
1318
}
1419
}
1520
}

packages/custom-esbuild/e2e/custom-esbuild-schema.spec.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ import { resolvePackagePath } from '@angular-builders/common';
33
describe('Custom ESBuild schema tests', () => {
44
let customEsbuildApplicationSchema: any;
55
let customEsbuildDevServerSchema: any;
6+
let customEsbuildUnitTestSchema: any;
67

78
beforeEach(() => {
89
jest.resetModules();
910
customEsbuildApplicationSchema = require('../dist/application/schema.json');
1011
customEsbuildDevServerSchema = require('../dist/dev-server/schema.json');
12+
customEsbuildUnitTestSchema = require('../dist/unit-test/schema.json');
1113
});
1214

1315
it('should fit the schema of the `@angular/build:application`', () => {
@@ -24,4 +26,12 @@ describe('Custom ESBuild schema tests', () => {
2426
customEsbuildDevServerSchema.properties['middlewares'] = undefined;
2527
expect(originalDevServerSchema.properties).toEqual(customEsbuildDevServerSchema.properties);
2628
});
29+
30+
it('should fit the schema of the `@angular/build:unit-test` without `runner` property', () => {
31+
const path = resolvePackagePath('@angular/build', 'src/builders/unit-test/schema.json');
32+
const originalUnitTestSchema = require(path);
33+
originalUnitTestSchema.properties['runner'] = undefined;
34+
customEsbuildUnitTestSchema.properties['plugins'] = undefined;
35+
expect(originalUnitTestSchema.properties).toEqual(customEsbuildUnitTestSchema.properties);
36+
});
2737
});

packages/custom-esbuild/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,15 @@
4141
"builders": "builders.json",
4242
"dependencies": {
4343
"@angular-builders/common": "workspace:*",
44-
"@angular-devkit/architect": ">=0.2000.0 < 0.2100.0",
45-
"@angular-devkit/core": "^20.0.0",
46-
"@angular/build": "^20.0.0"
44+
"@angular-devkit/architect": ">=0.2001.0 < 0.2100.0",
45+
"@angular-devkit/core": "^20.1.0",
46+
"@angular/build": "^20.1.0"
4747
},
4848
"peerDependencies": {
4949
"@angular/compiler-cli": "^20.0.0"
5050
},
5151
"devDependencies": {
52-
"esbuild": "0.25.1",
52+
"esbuild": "0.25.9",
5353
"jest": "29.7.0",
5454
"rimraf": "^5.0.0",
5555
"ts-node": "^10.0.0",
Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,21 @@
1-
import { ApplicationBuilderOptions, DevServerBuilderOptions } from '@angular/build';
1+
import {
2+
ApplicationBuilderOptions,
3+
DevServerBuilderOptions,
4+
UnitTestBuilderOptions,
5+
} from '@angular/build';
26

37
export type PluginConfig = string | { path: string; options?: Record<string, unknown> };
48

59
export type CustomEsbuildApplicationSchema = ApplicationBuilderOptions & {
6-
plugins?: string[];
10+
plugins?: PluginConfig[];
711
indexHtmlTransformer?: string;
812
};
913

1014
export type CustomEsbuildDevServerSchema = DevServerBuilderOptions & {
1115
middlewares?: string[];
1216
};
17+
18+
// Omitting `runner` here as we only support `vitest` runner (`karma` runner doesn't support ESBuild plugins)
19+
export type CustomEsbuildUnitTestSchema = Omit<UnitTestBuilderOptions, 'runner'> & {
20+
plugins?: PluginConfig[];
21+
};
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export * from './application';
22
export * from './dev-server';
3+
export * from './unit-test';

packages/custom-esbuild/src/load-plugins.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { loadModule } from '@angular-builders/common';
55
import {
66
CustomEsbuildApplicationSchema,
77
CustomEsbuildDevServerSchema,
8+
CustomEsbuildUnitTestSchema,
89
PluginConfig,
910
} from './custom-esbuild-schema';
1011
import { Target } from '@angular-devkit/architect';
@@ -14,7 +15,7 @@ export async function loadPlugins(
1415
workspaceRoot: string,
1516
tsConfig: string,
1617
logger: logging.LoggerApi,
17-
builderOptions: CustomEsbuildApplicationSchema | CustomEsbuildDevServerSchema,
18+
builderOptions: CustomEsbuildApplicationSchema | CustomEsbuildDevServerSchema | CustomEsbuildUnitTestSchema,
1819
target: Target
1920
): Promise<Plugin[]> {
2021
const plugins = await Promise.all(

0 commit comments

Comments
 (0)