Skip to content

Commit 460f5be

Browse files
authored
feat: 🎸 upgrade to Angular v20 (#711)
* feat: 🎸 upgrade to Angular v20 npx ng update @angular/core @angular/cli @angular/cdk angular-eslint @angular-builders/jest @analogjs/vitest-angular @analogjs/vite-plugin-angular jest-preset-angular prettier BREAKING CHANGE: 🧨 removed TestBed.get support * chore: 🤖 fix karma tests * chore: 🤖 bump @angular-builders/jest to v20 * chore: 🤖 fix karma bug `NODE_ENV=build yarn test` throws an error: TypeError [ERR_INVALID_STATE]: Invalid state: Controller is already closed bug: angular/angular-cli#30653 Update Angular to latest version with Karma fix: npx ng update @angular/core@latest @angular/cli@latest @angular/cdk@latest * chore: 🤖 bump @angular peerDependencies to >= 20.0.0 BREAKING CHANGE: 🧨 peerDependencies @angular/*: >= 20.0.0 * chore: 🤖 fix hanging Karma "ERROR Some of your tests did a full page reload!" karma-runner/karma#3887 (comment) * chore: 🤖 align karma.conf.js with latest @angular/cli reference * chore: 🤖 bump ng-packagr to v20.1.0 * chore: 🤖 bump vite dependencies * chore: 🤖 revert karma.conf.js clearContext setting
1 parent 694e97c commit 460f5be

File tree

13 files changed

+3545
-3564
lines changed

13 files changed

+3545
-3564
lines changed

angular.json

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"prefix": "lib",
1111
"architect": {
1212
"build": {
13-
"builder": "@angular-devkit/build-angular:ng-packagr",
13+
"builder": "@angular/build:ng-packagr",
1414
"options": {
1515
"tsConfig": "projects/spectator/tsconfig.lib.json",
1616
"project": "projects/spectator/ng-package.json"
@@ -22,7 +22,7 @@
2222
}
2323
},
2424
"test": {
25-
"builder": "@angular-devkit/build-angular:karma",
25+
"builder": "@angular/build:karma",
2626
"options": {
2727
"tsConfig": "projects/spectator/tsconfig.spec.json",
2828
"karmaConfig": "projects/spectator/karma.conf.js",
@@ -34,7 +34,8 @@
3434
"include": [
3535
"../test/test.ts",
3636
"../test/**/*.spec.ts"
37-
]
37+
],
38+
"watch": false
3839
}
3940
},
4041
"test-jest": {
@@ -68,6 +69,30 @@
6869
},
6970
"@angular-eslint/schematics:library": {
7071
"setParserOptionsProject": true
72+
},
73+
"@schematics/angular:component": {
74+
"type": "component"
75+
},
76+
"@schematics/angular:directive": {
77+
"type": "directive"
78+
},
79+
"@schematics/angular:service": {
80+
"type": "service"
81+
},
82+
"@schematics/angular:guard": {
83+
"typeSeparator": "."
84+
},
85+
"@schematics/angular:interceptor": {
86+
"typeSeparator": "."
87+
},
88+
"@schematics/angular:module": {
89+
"typeSeparator": "."
90+
},
91+
"@schematics/angular:pipe": {
92+
"typeSeparator": "."
93+
},
94+
"@schematics/angular:resolver": {
95+
"typeSeparator": "."
7196
}
7297
}
7398
}

package.json

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -31,24 +31,24 @@
3131
"release:dry": "cd projects/spectator && standard-version --infile ../../CHANGELOG.md --dry-run"
3232
},
3333
"devDependencies": {
34-
"@analogjs/vite-plugin-angular": "^1.10.1",
35-
"@analogjs/vitest-angular": "^1.10.1",
36-
"@angular-builders/jest": "^18.0.0",
37-
"@angular-devkit/build-angular": "^19.0.1",
38-
"@angular-devkit/schematics": "^19.0.1",
39-
"@angular/animations": "^19.0.0",
40-
"@angular/build": "^19.0.0",
41-
"@angular/cdk": "^19.0.0",
42-
"@angular/cli": "^19.0.1",
43-
"@angular/common": "^19.0.0",
44-
"@angular/compiler": "^19.0.0",
45-
"@angular/compiler-cli": "^19.0.0",
46-
"@angular/core": "^19.0.0",
47-
"@angular/forms": "^19.0.0",
48-
"@angular/language-service": "^19.0.0",
49-
"@angular/platform-browser": "^19.0.0",
50-
"@angular/platform-browser-dynamic": "^19.0.0",
51-
"@angular/router": "19.0.0",
34+
"@analogjs/vite-plugin-angular": "^1.19.1",
35+
"@analogjs/vitest-angular": "^1.19.1",
36+
"@angular-builders/jest": "^20.0.0",
37+
"@angular-devkit/build-angular": "^20.1.0",
38+
"@angular-devkit/schematics": "^20.1.0",
39+
"@angular/animations": "^20.1.0",
40+
"@angular/build": "^20.1.0",
41+
"@angular/cdk": "^20.1.0",
42+
"@angular/cli": "^20.1.0",
43+
"@angular/common": "^20.1.0",
44+
"@angular/compiler": "^20.1.0",
45+
"@angular/compiler-cli": "^20.1.0",
46+
"@angular/core": "^20.1.0",
47+
"@angular/forms": "^20.1.0",
48+
"@angular/language-service": "^20.1.0",
49+
"@angular/platform-browser": "^20.1.0",
50+
"@angular/platform-browser-dynamic": "^20.1.0",
51+
"@angular/router": "20.1.0",
5252
"@commitlint/cli": "17.3.0",
5353
"@commitlint/config-angular": "17.3.0",
5454
"@commitlint/config-conventional": "17.3.0",
@@ -58,7 +58,7 @@
5858
"@typescript-eslint/eslint-plugin": "^8.33.1",
5959
"@typescript-eslint/parser": "^8.33.1",
6060
"all-contributors-cli": "^6.19.0",
61-
"angular-eslint": "^19.8.0",
61+
"angular-eslint": "^20.1.1",
6262
"core-js": "^3.9.1",
6363
"cross-env": "^5.1.4",
6464
"cz-conventional-changelog": "^3.3.0",
@@ -69,24 +69,24 @@
6969
"jasmine-core": "5.1.1",
7070
"jasmine-spec-reporter": "7.0.0",
7171
"jest": "29.7.0",
72-
"jest-preset-angular": "14.1.0",
72+
"jest-preset-angular": "14.6.0",
7373
"jsdom": "^25.0.1",
74-
"karma": "6.4.2",
74+
"karma": "6.4.4",
7575
"karma-chrome-launcher": "3.2.0",
76-
"karma-coverage-istanbul-reporter": "3.0.3",
76+
"karma-coverage": "2.2.1",
7777
"karma-jasmine": "5.1.0",
7878
"karma-jasmine-html-reporter": "2.1.0",
7979
"lint-staged": "^13.1.0",
80-
"ng-packagr": "19.0.1",
81-
"prettier": "3.2.5",
80+
"ng-packagr": "20.1.0",
81+
"prettier": "3.5.3",
8282
"rxjs": "7.8.1",
8383
"standard-version": "^9.1.0",
8484
"ts-node": "10.1.0",
8585
"tslib": "^2.6.2",
86-
"typescript": "5.6.3",
86+
"typescript": "5.8.3",
8787
"typescript-eslint": "^8.33.1",
88-
"vite-tsconfig-paths": "^5.0.1",
89-
"vitest": "2.1.8",
88+
"vite-tsconfig-paths": "^5.1.4",
89+
"vitest": "3.2.4",
9090
"zone.js": "0.15.0"
9191
},
9292
"config": {

projects/spectator/karma.conf.js

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,41 @@
1-
// tslint:disable
2-
31
// Karma configuration file, see link for more information
42
// https://karma-runner.github.io/1.0/config/configuration-file.html
53

64
const build = process.env.NODE_ENV === 'build';
75

8-
module.exports = function(config) {
6+
module.exports = function (config) {
97
config.set({
10-
basePath: "",
11-
frameworks: ["jasmine", "@angular-devkit/build-angular"],
8+
basePath: '',
9+
frameworks: ['jasmine', '@angular-devkit/build-angular'],
1210
plugins: [
13-
require("karma-jasmine"),
14-
require("karma-chrome-launcher"),
15-
require("karma-jasmine-html-reporter"),
16-
require("karma-coverage-istanbul-reporter"),
17-
require("@angular-devkit/build-angular/plugins/karma"),
11+
require('karma-jasmine'),
12+
require('karma-chrome-launcher'),
13+
require('karma-jasmine-html-reporter'),
14+
require('karma-coverage'),
15+
require('@angular-devkit/build-angular/plugins/karma')
1816
],
1917
client: {
2018
clearContext: false, // leave Jasmine Spec Runner output visible in browser
19+
jasmine: {
20+
// you can add configuration options for Jasmine here
21+
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
22+
// for example, you can disable the random execution with `random: false`
23+
// or set a specific seed with `seed: 4321`
24+
},
25+
},
26+
jasmineHtmlReporter: {
27+
suppressAll: true // removes the duplicated traces
2128
},
22-
coverageIstanbulReporter: {
23-
dir: require("path").join(__dirname, "../../coverage/spectator"),
24-
reports: ["html", "lcovonly"],
25-
fixWebpackSourcePaths: true,
29+
coverageReporter: {
30+
dir: require('path').join(__dirname, '../../coverage/spectator'),
31+
subdir: '.',
32+
reporters: [
33+
{ type: 'html' },
34+
{ type: 'lcov' },
35+
{ type: 'text-summary' }
36+
],
2637
},
27-
reporters: ["progress", "kjhtml"],
38+
reporters: ['progress', 'kjhtml'],
2839
port: 9876,
2940
colors: true,
3041
logLevel: config.LOG_INFO,

projects/spectator/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@
2929
"tslib": "^2.6.2"
3030
},
3131
"peerDependencies": {
32-
"@angular/common": ">= 18.0.0",
33-
"@angular/router": ">= 18.0.0",
34-
"@angular/animations": ">= 18.0.0"
32+
"@angular/common": ">= 20.0.0",
33+
"@angular/router": ">= 20.0.0",
34+
"@angular/animations": ">= 20.0.0"
3535
},
3636
"schematics": "./schematics/collection.json"
3737
}

projects/spectator/src/lib/base/base-spectator.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { Token } from '../token';
88
*/
99
export abstract class BaseSpectator {
1010
public inject<T>(token: Token<T>): SpyObject<T> {
11-
return TestBed.inject ? TestBed.inject(token) : TestBed.get(token);
11+
return TestBed.inject(token) as SpyObject<T>;
1212
}
1313

1414
/**

projects/spectator/src/lib/internals/query.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { By } from '@angular/platform-browser';
33

44
import { DOMSelector } from '../dom-selectors';
55
import { isString, QueryOptions, QueryType } from '../types';
6+
import { type Token } from '../token';
67

78
export function getChildren<R>(debugElementRoot: DebugElement): (directiveOrSelector: QueryType, options?: QueryOptions<R>) => R[] {
89
return (directiveOrSelector: QueryType, options: QueryOptions<R> = { root: false, read: undefined }): R[] => {
@@ -15,7 +16,7 @@ export function getChildren<R>(debugElementRoot: DebugElement): (directiveOrSele
1516
);
1617

1718
if (options.read) {
18-
return debugElements.map((debug) => debug.injector.get(options.read));
19+
return debugElements.map((debug) => debug.injector.get(options.read as Token<R>));
1920
}
2021

2122
if (isString(directiveOrSelector)) {

projects/spectator/src/lib/spectator-http/create-factory.ts

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,7 @@ export function createHttpFactory<S>(typeOrOptions: Type<S> | SpectatorHttpOptio
3535
});
3636

3737
afterEach(() => {
38-
if (TestBed.inject) {
39-
TestBed.inject(HttpTestingController).verify();
40-
} else {
41-
TestBed.get(HttpTestingController).verify();
42-
}
38+
TestBed.inject(HttpTestingController).verify();
4339
});
4440

4541
return (overrides?: CreateHttpOverrides<S>) => {
@@ -52,13 +48,6 @@ export function createHttpFactory<S>(typeOrOptions: Type<S> | SpectatorHttpOptio
5248
});
5349
}
5450

55-
/**
56-
* Back compatibility, angular under 9 version doesnt have a inject function
57-
*/
58-
if (!TestBed.inject) {
59-
return new SpectatorHttp<S>(TestBed.get(service), TestBed.get(HttpClient), TestBed.get(HttpTestingController));
60-
}
61-
6251
return new SpectatorHttp<S>(TestBed.inject(service), TestBed.inject(HttpClient), TestBed.inject(HttpTestingController));
6352
};
6453
}

projects/spectator/src/lib/spectator-routing/create-factory.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ export function createRoutingFactory<C>(typeOrOptions: Type<C> | SpectatorRoutin
7474
TestBed.overrideProvider(ActivatedRoute, {
7575
useValue: new ActivatedRouteStub({ params, queryParams, data, fragment, url, root, parent, children, firstChild }),
7676
});
77-
const ngZone = (<any>TestBed).inject ? TestBed.inject(NgZone) : TestBed.get(NgZone);
77+
78+
const ngZone = TestBed.inject(NgZone);
7879

7980
return ngZone.run(() => {
8081
const spectator = createSpectatorRouting(options, props);
@@ -96,13 +97,6 @@ function createSpectatorRouting<C>(options: Required<SpectatorRoutingOptions<C>>
9697

9798
const component = setProps(fixture.componentRef, props);
9899

99-
/**
100-
* Back compatibility, angular under 9 version doesnt have a inject function
101-
*/
102-
if (!TestBed.inject) {
103-
return new SpectatorRouting(fixture, debugElement, component, TestBed.get(Router), TestBed.get(ActivatedRoute));
104-
}
105-
106100
return new SpectatorRouting(
107101
fixture,
108102
debugElement,

projects/spectator/src/lib/spectator-service/create-factory.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,9 @@ export function createServiceFactory<S>(typeOrOptions: Type<S> | SpectatorServic
3434
});
3535

3636
afterEach(() => {
37-
const testedService = (<any>TestBed).inject
38-
? (<{ inject<T>(token: Type<T>, notFoundValue?: T): T } & TestBedStatic>TestBed).inject<S>(service)
39-
: TestBed.get(service);
37+
const testedService = (<{ inject<T>(token: Type<T>, notFoundValue?: T): T } & TestBedStatic>TestBed).inject<S>(service) as object;
4038

4139
if (doesServiceImplementsOnDestroy(testedService)) {
42-
// eslint-disable-next-line
4340
testedService.ngOnDestroy();
4441
}
4542
});
@@ -54,6 +51,6 @@ export function createServiceFactory<S>(typeOrOptions: Type<S> | SpectatorServic
5451
});
5552
}
5653

57-
return new SpectatorService<S>(TestBed.inject ? TestBed.inject(service) : TestBed.get(service));
54+
return new SpectatorService<S>(TestBed.inject(service));
5855
};
5956
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { InjectionToken, AbstractType, Type } from '@angular/core';
1+
import { InjectionToken, AbstractType, Type, ProviderToken } from '@angular/core';
22

33
/** Type representing valid typesafe token types for provider binding. */
4-
export type Token<T> = Type<T> | InjectionToken<T> | AbstractType<T>;
4+
export type Token<T> = Type<T> | InjectionToken<T> | AbstractType<T> | ProviderToken<T>;

0 commit comments

Comments
 (0)