Skip to content

Commit 2f7e64c

Browse files
laurentgrangierlucas-koehler
authored andcommitted
feat: support Angular 18
Updates code base to Angular 18. This removes support for Angular 16. Also includes the following changes: - removal of the angular test package - Typescript update - migration guide entry Co-authored-by: Lucas Köhler <lkoehler@eclipsesource.com>
1 parent 5c5a470 commit 2f7e64c

Some content is hidden

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

44 files changed

+8262
-15338
lines changed

MIGRATION.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Migration guide
22

3+
## Migrating to JSON Forms 3.3
4+
5+
### Angular support now targets Angular 17 and Angular 18
6+
7+
When using JSON Forms 3.3, your Angular application now needs to target Angular 17 or 18.
8+
9+
Use JSON Forms 3.2 if you need to stay on Angular 16.
10+
311
## Migrating to JSON Forms 3.2
412

513
### React Material Renderers using Outlined Inputs

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"build:examples-app": "lerna run build:examples-app && node packages/examples-app/prepare-examples-app.js"
2121
},
2222
"devDependencies": {
23-
"@angular/core": "^16.0.0",
23+
"@angular/core": "^17.0.0",
2424
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.5",
2525
"@babel/plugin-proposal-optional-chaining": "^7.16.5",
2626
"@istanbuljs/nyc-config-typescript": "^1.0.2",
@@ -44,7 +44,7 @@
4444
"ts-loader": "^9.5.1",
4545
"ts-node": "^10.4.0",
4646
"tslib": "^2.5.0",
47-
"typescript": "~4.9.5",
47+
"typescript": "~5.2.2",
4848
"webpack": "^5.78.0",
4949
"webpack-merge": "^5.10.0"
5050
}

packages/angular-material/package.json

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,14 @@
6060
]
6161
},
6262
"peerDependencies": {
63-
"@angular/animations": "^16.0.0 || ^17.0.0",
64-
"@angular/cdk": "^16.0.0 || ^17.0.0",
65-
"@angular/common": "^16.0.0 || ^17.0.0",
66-
"@angular/core": "^16.0.0 || ^17.0.0",
67-
"@angular/forms": "^16.0.0 || ^17.0.0",
68-
"@angular/material": "^16.0.0 || ^17.0.0",
69-
"@angular/platform-browser": "^16.0.0 || ^17.0.0",
70-
"@angular/router": "^16.0.0 || ^17.0.0",
63+
"@angular/animations": "^17.0.0 || ^18.0.0",
64+
"@angular/cdk": "^17.0.0 || ^18.0.0",
65+
"@angular/common": "^17.0.0 || ^18.0.0",
66+
"@angular/core": "^17.0.0 || ^18.0.0",
67+
"@angular/forms": "^17.0.0 || ^18.0.0",
68+
"@angular/material": "^17.0.0 || ^18.0.0",
69+
"@angular/platform-browser": "^17.0.0 || ^18.0.0",
70+
"@angular/router": "^17.0.0 || ^18.0.0",
7171
"@jsonforms/angular": "3.3.0-beta.0",
7272
"@jsonforms/core": "3.3.0-beta.0",
7373
"dayjs": "^1.11.7",
@@ -78,30 +78,29 @@
7878
"lodash": "^4.17.21"
7979
},
8080
"devDependencies": {
81-
"@angular-devkit/build-angular": "^16.0.0",
82-
"@angular-devkit/core": "^16.0.0",
83-
"@angular-eslint/eslint-plugin": "^16.0.0",
84-
"@angular-eslint/eslint-plugin-template": "^16.0.0",
85-
"@angular-eslint/schematics": "^16.0.0",
86-
"@angular-eslint/template-parser": "^16.0.0",
87-
"@angular/animations": "^16.0.0",
88-
"@angular/cdk": "^16.0.0",
89-
"@angular/common": "^16.0.0",
90-
"@angular/compiler": "^16.0.0",
91-
"@angular/compiler-cli": "^16.0.0",
92-
"@angular/core": "^16.0.0",
93-
"@angular/forms": "^16.0.0",
94-
"@angular/material": "^16.0.0",
95-
"@angular/platform-browser": "^16.0.0",
96-
"@angular/platform-browser-dynamic": "^16.0.0",
97-
"@angular/router": "^16.0.0",
81+
"@angular-devkit/build-angular": "^17.0.0",
82+
"@angular-devkit/core": "^17.0.0",
83+
"@angular-eslint/eslint-plugin": "^17.0.0",
84+
"@angular-eslint/eslint-plugin-template": "^17.0.0",
85+
"@angular-eslint/schematics": "^17.0.0",
86+
"@angular-eslint/template-parser": "^17.0.0",
87+
"@angular/animations": "^17.0.0",
88+
"@angular/cdk": "^17.0.0",
89+
"@angular/common": "^17.0.0",
90+
"@angular/compiler": "^17.0.0",
91+
"@angular/compiler-cli": "^17.0.0",
92+
"@angular/core": "^17.0.0",
93+
"@angular/forms": "^17.0.0",
94+
"@angular/material": "^17.0.0",
95+
"@angular/platform-browser": "^17.0.0",
96+
"@angular/platform-browser-dynamic": "^17.0.0",
97+
"@angular/router": "^17.0.0",
9898
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.5",
9999
"@babel/plugin-proposal-optional-chaining": "^7.16.5",
100100
"@jsonforms/angular": "workspace:*",
101-
"@jsonforms/angular-test": "workspace:*",
102101
"@jsonforms/core": "workspace:*",
103102
"@jsonforms/examples": "workspace:*",
104-
"@ngtools/webpack": "^16.0.0",
103+
"@ngtools/webpack": "^17.0.0",
105104
"@types/jasmine": "~3.8.0",
106105
"@types/lodash": "4.14.149",
107106
"@types/node": "^18.19.4",
@@ -118,14 +117,14 @@
118117
"http-server": "^14.1.1",
119118
"jasmine": "^3.99.0",
120119
"jasmine-spec-reporter": "^4.2.1",
121-
"karma": "^6.4.1",
120+
"karma": "^6.4.3",
122121
"karma-chrome-launcher": "^3.2.0",
123122
"karma-coverage": "~2.0.3",
124123
"karma-jasmine": "^2.0.1",
125124
"karma-jasmine-html-reporter": "^1.7.0",
126125
"karma-sourcemap-loader": "^0.3.8",
127126
"karma-webpack": "^5.0.0",
128-
"ng-packagr": "^16.0.0",
127+
"ng-packagr": "^17.0.0",
129128
"null-loader": "^0.1.1",
130129
"nyc": "^15.1.0",
131130
"prettier": "^2.8.4",
@@ -135,9 +134,9 @@
135134
"ts-loader": "^9.5.1",
136135
"tslib": "^2.5.0",
137136
"typedoc": "~0.25.3",
138-
"typescript": "~4.9.5",
137+
"typescript": "~5.2.2",
139138
"webpack": "^5.78.0",
140139
"yargs": "^17.7.2",
141-
"zone.js": "~0.13.0"
140+
"zone.js": "~0.14.0"
142141
}
143142
}

packages/angular-material/test/autocomplete-control.spec.ts

Lines changed: 37 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,13 @@ import {
2828
} from '@angular/material/autocomplete';
2929
import { MatError, MatFormFieldModule } from '@angular/material/form-field';
3030
import { MatInputModule } from '@angular/material/input';
31-
import { OverlayContainer } from '@angular/cdk/overlay';
32-
import { DebugElement, NgZone } from '@angular/core';
31+
import { DebugElement } from '@angular/core';
3332
import {
3433
ComponentFixture,
3534
fakeAsync,
36-
inject,
3735
TestBed,
3836
tick,
37+
waitForAsync,
3938
} from '@angular/core/testing';
4039
import { ReactiveFormsModule } from '@angular/forms';
4140
import { By } from '@angular/platform-browser';
@@ -44,11 +43,15 @@ import {
4443
ErrorTestExpectation,
4544
setupMockStore,
4645
getJsonFormsService,
47-
} from '@jsonforms/angular-test';
46+
} from './common';
4847
import { ControlElement, JsonSchema, Actions } from '@jsonforms/core';
4948
import { AutocompleteControlRenderer } from '../src';
5049
import { JsonFormsAngularService } from '@jsonforms/angular';
5150
import { ErrorObject } from 'ajv';
51+
import { initTestEnvironment } from './test';
52+
import { HarnessLoader } from '@angular/cdk/testing';
53+
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
54+
import { MatAutocompleteHarness } from '@angular/material/autocomplete/testing';
5255

5356
const data = { foo: 'A' };
5457
const schema: JsonSchema = {
@@ -80,17 +83,19 @@ const errorTest: ErrorTestExpectation = {
8083
indexOfElement: 0,
8184
};
8285

86+
initTestEnvironment();
87+
8388
describe('Autocomplete control Base Tests', () => {
8489
let fixture: ComponentFixture<AutocompleteControlRenderer>;
8590
let component: AutocompleteControlRenderer;
8691
let inputElement: HTMLInputElement;
87-
beforeEach(() => {
92+
beforeEach(waitForAsync(() => {
8893
TestBed.configureTestingModule({
8994
declarations: [componentUT],
9095
imports: imports,
9196
providers: providers,
9297
}).compileComponents();
93-
});
98+
}));
9499
beforeEach(() => {
95100
fixture = TestBed.createComponent(componentUT);
96101
component = fixture.componentInstance;
@@ -211,40 +216,21 @@ describe('Autocomplete control Base Tests', () => {
211216
describe('AutoComplete control Input Event Tests', () => {
212217
let fixture: ComponentFixture<AutocompleteControlRenderer>;
213218
let component: AutocompleteControlRenderer;
214-
let inputElement: HTMLInputElement;
215-
let overlayContainer: OverlayContainer;
216-
let overlayContainerElement: HTMLElement;
217-
let zone: NgZone;
218-
beforeEach(() => {
219+
let loader: HarnessLoader;
220+
beforeEach(waitForAsync(() => {
219221
TestBed.configureTestingModule({
220222
declarations: [componentUT],
221223
imports: imports,
222224
providers: [...providers],
223225
}).compileComponents();
224-
225-
inject([OverlayContainer], (oc: OverlayContainer) => {
226-
overlayContainer = oc;
227-
overlayContainerElement = oc.getContainerElement();
228-
})();
229-
});
230-
beforeEach(() => {
226+
}));
227+
beforeEach(waitForAsync(() => {
231228
fixture = TestBed.createComponent(componentUT);
232229
component = fixture.componentInstance;
233-
zone = TestBed.inject(NgZone);
234-
spyOn(zone, 'runOutsideAngular').and.callFake((fn: () => any) => fn());
235-
inputElement = fixture.debugElement.query(By.css('input')).nativeElement;
236-
});
230+
loader = TestbedHarnessEnvironment.loader(fixture);
231+
}));
237232

238-
afterEach(inject(
239-
[OverlayContainer],
240-
(currentOverlayContainer: OverlayContainer) => {
241-
// Since we're resetting the testing module in some of the tests,
242-
// we can potentially have multiple overlay containers.
243-
currentOverlayContainer.ngOnDestroy();
244-
overlayContainer.ngOnDestroy();
245-
}
246-
));
247-
it('should update via input event', fakeAsync(() => {
233+
it('should update via input event', fakeAsync(async () => {
248234
setupMockStore(fixture, { uischema, schema, data });
249235
getJsonFormsService(component).updateCore(
250236
Actions.init(data, schema, uischema)
@@ -255,14 +241,12 @@ describe('AutoComplete control Input Event Tests', () => {
255241

256242
const spy = spyOn(component, 'onSelect');
257243

258-
inputElement.focus();
259-
zone.runOutsideAngular(() => zone.onStable.emit(null));
244+
await (await loader.getHarness(MatAutocompleteHarness)).focus();
260245
fixture.detectChanges();
261246

262-
const options = overlayContainerElement.querySelectorAll(
263-
'mat-option'
264-
) as NodeListOf<HTMLElement>;
265-
options.item(1).click();
247+
await (
248+
await loader.getHarness(MatAutocompleteHarness)
249+
).selectOption({ text: 'B' });
266250
tick();
267251
fixture.detectChanges();
268252

@@ -272,7 +256,7 @@ describe('AutoComplete control Input Event Tests', () => {
272256

273257
expect(event.option.value).toBe('B');
274258
}));
275-
it('options should prefer own props', fakeAsync(() => {
259+
it('options should prefer own props', fakeAsync(async () => {
276260
setupMockStore(fixture, { uischema, schema, data });
277261
getJsonFormsService(component).updateCore(
278262
Actions.init(data, schema, uischema)
@@ -283,33 +267,30 @@ describe('AutoComplete control Input Event Tests', () => {
283267
fixture.detectChanges();
284268
const spy = spyOn(component, 'onSelect');
285269

286-
inputElement.focus();
287-
zone.runOutsideAngular(() => zone.onStable.emit(null));
270+
await (await loader.getHarness(MatAutocompleteHarness)).focus();
288271
fixture.detectChanges();
289272

290-
fixture.whenStable().then(() => {
291-
const options = overlayContainerElement?.querySelectorAll(
292-
'mat-option'
293-
) as NodeListOf<HTMLElement>;
294-
(options[1] as HTMLElement).click();
295-
fixture.detectChanges();
296-
tick();
297-
const event = spy.calls.mostRecent()
298-
.args[0] as MatAutocompleteSelectedEvent;
299-
expect(event.option.value).toBe('Y');
300-
});
273+
await (
274+
await loader.getHarness(MatAutocompleteHarness)
275+
).selectOption({ text: 'Y' });
276+
fixture.detectChanges();
277+
tick();
278+
279+
const event = spy.calls.mostRecent()
280+
.args[0] as MatAutocompleteSelectedEvent;
281+
expect(event.option.value).toBe('Y');
301282
}));
302283
});
303284
describe('AutoComplete control Error Tests', () => {
304285
let fixture: ComponentFixture<AutocompleteControlRenderer>;
305286
let component: AutocompleteControlRenderer;
306-
beforeEach(() => {
287+
beforeEach(waitForAsync(() => {
307288
TestBed.configureTestingModule({
308289
declarations: [componentUT],
309290
imports: imports,
310291
providers: providers,
311292
}).compileComponents();
312-
});
293+
}));
313294
beforeEach(() => {
314295
fixture = TestBed.createComponent(componentUT);
315296
component = fixture.componentInstance;
@@ -349,13 +330,13 @@ describe('AutoComplete control updateFilter function', () => {
349330
let fixture: ComponentFixture<AutocompleteControlRenderer>;
350331
let component: AutocompleteControlRenderer;
351332

352-
beforeEach(() => {
333+
beforeEach(waitForAsync(() => {
353334
TestBed.configureTestingModule({
354335
declarations: [componentUT],
355336
imports: imports,
356337
providers: providers,
357338
}).compileComponents();
358-
});
339+
}));
359340

360341
beforeEach(() => {
361342
fixture = TestBed.createComponent(componentUT);

packages/angular-material/test/boolean-control.spec.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,12 @@ import {
2929
booleanErrorTest,
3030
booleanInputEventTest,
3131
ErrorTestExpectation,
32-
} from '@jsonforms/angular-test';
32+
} from './common';
3333
import { BooleanControlRenderer, booleanControlTester } from '../src';
3434
import { JsonFormsAngularService } from '@jsonforms/angular';
35+
import { initTestEnvironment } from './test';
36+
37+
initTestEnvironment();
3538

3639
describe('Material boolean field tester', () => {
3740
const uischema = {

0 commit comments

Comments
 (0)