Skip to content

Commit 1350920

Browse files
authored
Standalone schematics (#3451)
* Make ng-add work with standalone mode * Add simple AppCheck feature addition * Cleanup
1 parent 78407bc commit 1350920

File tree

4 files changed

+171
-249
lines changed

4 files changed

+171
-249
lines changed

src/schematics/interfaces.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export const enum FEATURES {
44
Hosting,
55
Authentication,
66
Analytics,
7+
AppCheck,
78
Database,
89
Functions,
910
Messaging,
@@ -16,9 +17,10 @@ export const enum FEATURES {
1617
export const featureOptions = [
1718
{ name: 'ng deploy -- hosting', value: FEATURES.Hosting },
1819
{ name: 'Authentication', value: FEATURES.Authentication },
20+
{ name: 'Google Analytics', value: FEATURES.Analytics },
21+
{ name: 'App Check', value: FEATURES.AppCheck },
1922
{ name: 'Firestore', value: FEATURES.Firestore },
2023
{ name: 'Realtime Database', value: FEATURES.Database },
21-
{ name: 'Analytics', value: FEATURES.Analytics },
2224
{ name: 'Cloud Functions (callable)', value: FEATURES.Functions },
2325
{ name: 'Cloud Messaging', value: FEATURES.Messaging },
2426
{ name: 'Performance Monitoring', value: FEATURES.Performance },
@@ -47,7 +49,7 @@ export interface NgAddNormalizedOptions {
4749
}
4850

4951
export interface DeployOptions {
50-
project: string;
52+
project?: string;
5153
}
5254

5355
export interface FirebaseProject {

src/schematics/ng-add.jasmine.ts

+53-52
Original file line numberDiff line numberDiff line change
@@ -299,114 +299,113 @@ describe('ng-add', () => {
299299
tree.create('package.json', JSON.stringify(generatePackageJson()));
300300
});
301301

302-
it('generates new files if starting from scratch', async () => {
303-
const result = await setupProject(tree, {} as any, [FEATURES.Hosting], {
302+
it('generates new files if starting from scratch', () => {
303+
setupProject(tree, {} as any, [FEATURES.Hosting], {
304304
firebaseProject: { projectId: FIREBASE_PROJECT } as any,
305305
projectType: PROJECT_TYPE.Static,
306306
project: PROJECT_NAME,
307307
prerender: false,
308-
}) as Tree;
309-
expect(result.read('firebase.json').toString()).toEqual(initialFirebaseJson);
310-
expect(result.read('.firebaserc').toString()).toEqual(initialFirebaserc);
311-
expect(result.read('angular.json').toString()).toEqual(initialAngularJson);
308+
});
309+
expect(tree.read('firebase.json')?.toString()).toEqual(initialFirebaseJson);
310+
expect(tree.read('.firebaserc')?.toString()).toEqual(initialFirebaserc);
311+
expect(tree.read('angular.json')?.toString()).toEqual(initialAngularJson);
312312
});
313313

314-
it('uses default project', async () => {
315-
const result = await setupProject(tree, {} as any, [FEATURES.Hosting], {
314+
it('uses default project', () => {
315+
setupProject(tree, {} as any, [FEATURES.Hosting], {
316316
firebaseProject: { projectId: FIREBASE_PROJECT } as any,
317317
projectType: PROJECT_TYPE.Static,
318318
project: undefined,
319319
prerender: false,
320-
}) as Tree;
321-
expect(result.read('firebase.json').toString()).toEqual(overwriteFirebaseJson);
322-
expect(result.read('.firebaserc').toString()).toEqual(overwriteFirebaserc);
323-
expect(result.read('angular.json').toString()).toEqual(overwriteAngularJson);
320+
});
321+
expect(tree.read('firebase.json')?.toString()).toEqual(overwriteFirebaseJson);
322+
expect(tree.read('.firebaserc')?.toString()).toEqual(overwriteFirebaserc);
323+
expect(tree.read('angular.json')?.toString()).toEqual(overwriteAngularJson);
324324
});
325325

326-
it('runs if source root is relative to workspace root', async () => {
326+
it('runs if source root is relative to workspace root', () => {
327327
const angularJson = generateAngularJson();
328328
const project: {root: string, sourceRoot?: string} = angularJson.projects[PROJECT_NAME];
329329
project.sourceRoot = `${project.root}/src`;
330330
tree.overwrite('angular.json', JSON.stringify(angularJson));
331-
const promise = setupProject(tree, {} as any, [FEATURES.Hosting], {
331+
setupProject(tree, {} as any, [FEATURES.Hosting], {
332332
firebaseProject: { projectId: FIREBASE_PROJECT } as any,
333333
projectType: PROJECT_TYPE.Static,
334334
project: undefined,
335335
prerender: false,
336336
});
337-
await expectAsync(promise).toBeResolved();
338337
});
339338

340-
it('overrides existing files', async () => {
341-
await setupProject(tree, {} as any, [FEATURES.Hosting], {
339+
it('overrides existing files', () => {
340+
setupProject(tree, {} as any, [FEATURES.Hosting], {
342341
firebaseProject: { projectId: FIREBASE_PROJECT } as any,
343342
projectType: PROJECT_TYPE.Static,
344343
project: PROJECT_NAME,
345344
prerender: false,
346345
});
347-
const result = await setupProject(tree, {} as any, [FEATURES.Hosting], {
346+
setupProject(tree, {} as any, [FEATURES.Hosting], {
348347
firebaseProject: { projectId: OTHER_FIREBASE_PROJECT_NAME } as any,
349348
projectType: PROJECT_TYPE.Static,
350349
project: OTHER_PROJECT_NAME,
351350
prerender: false,
352-
}) as Tree;
353-
expect(result.read('firebase.json').toString()).toEqual(projectFirebaseJson);
354-
expect(result.read('.firebaserc').toString()).toEqual(projectFirebaserc);
355-
expect(result.read('angular.json').toString()).toEqual(projectAngularJson);
351+
});
352+
expect(tree.read('firebase.json')?.toString()).toEqual(projectFirebaseJson);
353+
expect(tree.read('.firebaserc')?.toString()).toEqual(projectFirebaserc);
354+
expect(tree.read('angular.json')?.toString()).toEqual(projectAngularJson);
356355
});
357356
});
358357

359358
describe('error handling', () => {
360-
it('fails if project not defined', async () => {
359+
it('fails if project not defined', () => {
361360
const tree = Tree.empty();
362361
const angularJSON = generateAngularJson();
363362
delete angularJSON.defaultProject;
364363
tree.create('angular.json', JSON.stringify(angularJSON));
365364
tree.create('package.json', JSON.stringify(generatePackageJson()));
366-
await expectAsync(setupProject(tree, {} as any, [FEATURES.Hosting], {
365+
expect(() => setupProject(tree, {} as any, [FEATURES.Hosting], {
367366
firebaseProject: { projectId: FIREBASE_PROJECT } as any,
368367
projectType: PROJECT_TYPE.Static,
369368
project: undefined,
370369
prerender: false,
371-
})).toBeRejectedWith(
370+
})).toThrow(
372371
new SchematicsException('No Angular project selected and no default project in the workspace')
373372
);
374373
});
375374

376-
it('Should throw if angular.json not found', async () => {
377-
await expectAsync(setupProject(Tree.empty(), {} as any, [FEATURES.Hosting], {
375+
it('Should throw if angular.json not found', () => {
376+
expect(() => setupProject(Tree.empty(), {} as any, [FEATURES.Hosting], {
378377
firebaseProject: { projectId: FIREBASE_PROJECT } as any,
379378
projectType: PROJECT_TYPE.Static,
380379
project: PROJECT_NAME,
381380
prerender: false,
382-
})).toBeRejectedWith(new SchematicsException('Could not find angular.json'));
381+
})).toThrow(new SchematicsException('Could not find angular.json'));
383382
});
384383

385-
it('Should throw if angular.json can not be parsed', async () => {
384+
it('Should throw if angular.json can not be parsed', () => {
386385
const tree = Tree.empty();
387386
tree.create('angular.json', 'hi');
388387
tree.create('package.json', JSON.stringify(generatePackageJson()));
389-
await expectAsync(setupProject(tree, {} as any, [FEATURES.Hosting], {
388+
expect(() => setupProject(tree, {} as any, [FEATURES.Hosting], {
390389
firebaseProject: { projectId: FIREBASE_PROJECT } as any,
391390
projectType: PROJECT_TYPE.Static,
392391
project: PROJECT_NAME,
393392
prerender: false,
394-
})).toBeRejectedWith(new SchematicsException('Could not parse angular.json'));
393+
})).toThrow(new SchematicsException('Could not parse angular.json'));
395394
});
396395

397-
it('Should throw if specified project does not exist ', async () => {
396+
it('Should throw if specified project does not exist ', () => {
398397
const tree = Tree.empty();
399398
tree.create('angular.json', JSON.stringify({ projects: {} }));
400399
tree.create('package.json', JSON.stringify(generatePackageJson()));
401-
await expectAsync(setupProject(tree, {} as any, [FEATURES.Hosting], {
400+
expect(() => setupProject(tree, {} as any, [FEATURES.Hosting], {
402401
firebaseProject: { projectId: FIREBASE_PROJECT } as any,
403402
projectType: PROJECT_TYPE.Static,
404403
project: PROJECT_NAME,
405404
prerender: false,
406-
})).toBeRejectedWith(new SchematicsException('The specified Angular project is not defined in this workspace'));
405+
})).toThrow(new SchematicsException('The specified Angular project is not defined in this workspace'));
407406
});
408407

409-
it('Should throw if specified project is not application', async () => {
408+
it('Should throw if specified project is not application', () => {
410409
const tree = Tree.empty();
411410
tree.create(
412411
'angular.json',
@@ -415,15 +414,15 @@ describe('ng-add', () => {
415414
})
416415
);
417416
tree.create('package.json', JSON.stringify(generatePackageJson()));
418-
await expectAsync(setupProject(tree, {} as any, [FEATURES.Hosting], {
417+
expect(() => setupProject(tree, {} as any, [FEATURES.Hosting], {
419418
firebaseProject: { projectId: FIREBASE_PROJECT } as any,
420419
projectType: PROJECT_TYPE.Static,
421420
project: PROJECT_NAME,
422421
prerender: false,
423-
})).toBeRejectedWith(new SchematicsException('Deploy requires an Angular project type of "application" in angular.json'));
422+
})).toThrow(new SchematicsException('Deploy requires an Angular project type of "application" in angular.json'));
424423
});
425424

426-
it('Should throw if app does not have architect configured', async () => {
425+
it('Should throw if app does not have architect configured', () => {
427426
const tree = Tree.empty();
428427
tree.create(
429428
'angular.json',
@@ -432,12 +431,12 @@ describe('ng-add', () => {
432431
})
433432
);
434433
tree.create('package.json', JSON.stringify(generatePackageJson()));
435-
await expectAsync(setupProject(tree, {} as any, [FEATURES.Hosting], {
434+
expect(() => setupProject(tree, {} as any, [FEATURES.Hosting], {
436435
firebaseProject: { projectId: FIREBASE_PROJECT } as any,
437436
projectType: PROJECT_TYPE.Static,
438437
project: PROJECT_NAME,
439438
prerender: false,
440-
})).toBeRejectedWith(
439+
})).toThrow(
441440
new SchematicsException('Angular project "pie-ka-chu" has a malformed angular.json')
442441
);
443442
});
@@ -474,17 +473,17 @@ describe('ng-add', () => {
474473
).toThrowError(/firebase.json: Unexpected token/);
475474
});*/
476475

477-
it('Should throw if .firebaserc is broken', async () => {
476+
it('Should throw if .firebaserc is broken', () => {
478477
const tree = Tree.empty();
479478
tree.create('angular.json', JSON.stringify(generateAngularJson()));
480479
tree.create('package.json', JSON.stringify(generatePackageJson()));
481480
tree.create('.firebaserc', `I'm broken 😔`);
482-
await expectAsync(setupProject(tree, {} as any, [FEATURES.Hosting], {
481+
expect(() => setupProject(tree, {} as any, [FEATURES.Hosting], {
483482
firebaseProject: { projectId: FIREBASE_PROJECT } as any,
484483
projectType: PROJECT_TYPE.Static,
485484
project: PROJECT_NAME,
486485
prerender: false,
487-
})).toBeRejectedWith(
486+
})).toThrow(
488487
parseInt(process.versions.node, 10) >= 20 ?
489488
new SchematicsException(`Error when parsing .firebaserc: Unexpected token 'I', "I'm broken 😔" is not valid JSON`) :
490489
new SchematicsException('Error when parsing .firebaserc: Unexpected token I in JSON at position 0')
@@ -532,37 +531,39 @@ describe('ng-add', () => {
532531

533532
describe('universal app', () => {
534533

535-
it('should add a @angular/fire builder', async () => {
534+
it('should add a @angular/fire builder', () => {
536535
const tree = Tree.empty();
537536
tree.create('angular.json', JSON.stringify(generateAngularJsonWithServer()));
538537
tree.create('package.json', JSON.stringify(generatePackageJson()));
539538

540539
// TODO mock addTask
541-
const result = await setupProject(tree, {addTask: () => undefined} as any, [FEATURES.Hosting], {
540+
setupProject(tree, {addTask: () => undefined} as any, [FEATURES.Hosting], {
542541
firebaseProject: { projectId: FIREBASE_PROJECT } as any,
543542
projectType: PROJECT_TYPE.CloudFunctions,
544543
project: PROJECT_NAME,
545544
prerender: false,
546-
}) as Tree;
545+
});
547546

548-
const workspace = JSON.parse((result.read('angular.json')).toString());
549-
expect(workspace.projects['pie-ka-chu'].architect.deploy).toBeTruthy();
547+
const angularJSON = tree.read('angular.json')?.toString();
548+
const workspace = angularJSON && JSON.parse(angularJSON);
549+
expect(workspace?.projects['pie-ka-chu']?.architect?.deploy).toBeTruthy();
550550
});
551551

552-
it('should configure firebase.json', async () => {
552+
it('should configure firebase.json', () => {
553553
const tree = Tree.empty();
554554
tree.create('angular.json', JSON.stringify(generateAngularJsonWithServer()));
555555
tree.create('package.json', JSON.stringify(generatePackageJson()));
556556

557557
// TODO mock addTask
558-
const result = await setupProject(tree, {addTask: () => undefined} as any, [FEATURES.Hosting], {
558+
setupProject(tree, {addTask: () => undefined} as any, [FEATURES.Hosting], {
559559
firebaseProject: { projectId: FIREBASE_PROJECT } as any,
560560
projectType: PROJECT_TYPE.CloudFunctions,
561561
project: PROJECT_NAME,
562562
prerender: false,
563-
}) as Tree;
563+
});
564564

565-
const firebaseJson = JSON.parse((result.read('firebase.json')).toString());
565+
const firebaseJsonData= tree.read('firebase.json')?.toString();
566+
const firebaseJson = firebaseJsonData && JSON.parse(firebaseJsonData);
566567
expect(firebaseJson).toEqual(universalFirebaseJson);
567568
});
568569
});

0 commit comments

Comments
 (0)