Skip to content

Commit 512cec8

Browse files
feat: show next steps after ng add (#201)
* feat: show next steps after ng add Display helpful message with documentation link after installation: - Read the docs link - Deploy command hint - Friendly closing message * test: verify console output after ng add
1 parent 678215b commit 512cec8

4 files changed

Lines changed: 75 additions & 20 deletions

File tree

src/ng-add.spec.ts

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,19 @@ const PROJECT_NAME = 'THEPROJECT';
66
const PROJECT_ROOT = 'PROJECTROOT';
77
const OTHER_PROJECT_NAME = 'OTHERPROJECT';
88

9+
// Mock context with logger - only the methods we actually use
10+
const mockLogger = {
11+
info: jest.fn(),
12+
warn: jest.fn(),
13+
error: jest.fn(),
14+
debug: jest.fn(),
15+
fatal: jest.fn(),
16+
log: jest.fn(),
17+
createChild: jest.fn()
18+
};
19+
20+
const mockContext = { logger: mockLogger } as unknown as SchematicContext;
21+
922
describe('ng-add', () => {
1023
describe('generating files', () => {
1124
let tree: Tree;
@@ -18,7 +31,7 @@ describe('ng-add', () => {
1831
it('generates new files if starting from scratch', async () => {
1932
const result = await ngAdd({
2033
project: PROJECT_NAME
21-
})(tree, {} as SchematicContext);
34+
})(tree, mockContext);
2235

2336
const actual = result.read('angular.json')!.toString();
2437
expect(prettifyJSON(actual)).toMatchSnapshot();
@@ -27,11 +40,11 @@ describe('ng-add', () => {
2740
it('overrides existing files', async () => {
2841
const tempTree = await ngAdd({
2942
project: PROJECT_NAME
30-
})(tree, {} as SchematicContext);
43+
})(tree, mockContext);
3144

3245
const result = await ngAdd({
3346
project: OTHER_PROJECT_NAME
34-
})(tempTree, {} as SchematicContext);
47+
})(tempTree, mockContext);
3548

3649
const actual = result.read('angular.json')!.toString();
3750

@@ -49,7 +62,7 @@ describe('ng-add', () => {
4962

5063
const resultTree = await ngAdd({ project: '' })(
5164
tree,
52-
{} as SchematicContext
65+
mockContext
5366
);
5467

5568
const resultConfig = readJSONFromTree(resultTree, 'angular.json');
@@ -65,15 +78,15 @@ describe('ng-add', () => {
6578
tree.create('angular.json', JSON.stringify(angularJSON));
6679

6780
await expect(
68-
ngAdd({ project: '' })(tree, {} as SchematicContext)
81+
ngAdd({ project: '' })(tree, mockContext)
6982
).rejects.toThrowError(
7083
'There is more than one project in your workspace. Please select it manually by using the --project argument.'
7184
);
7285
});
7386

7487
it('should throw if angular.json not found', async () => {
7588
await expect(
76-
ngAdd({ project: PROJECT_NAME })(Tree.empty(), {} as SchematicContext)
89+
ngAdd({ project: PROJECT_NAME })(Tree.empty(), mockContext)
7790
).rejects.toThrowError('Unable to determine format for workspace path.');
7891
});
7992

@@ -82,7 +95,7 @@ describe('ng-add', () => {
8295
tree.create('angular.json', 'hi');
8396

8497
await expect(
85-
ngAdd({ project: PROJECT_NAME })(tree, {} as SchematicContext)
98+
ngAdd({ project: PROJECT_NAME })(tree, mockContext)
8699
).rejects.toThrowError('Invalid workspace file - expected JSON object.');
87100
});
88101

@@ -91,7 +104,7 @@ describe('ng-add', () => {
91104
tree.create('angular.json', JSON.stringify({ version: 1, projects: {} }));
92105

93106
await expect(
94-
ngAdd({ project: PROJECT_NAME })(tree, {} as SchematicContext)
107+
ngAdd({ project: PROJECT_NAME })(tree, mockContext)
95108
).rejects.toThrowError(
96109
'The specified Angular project is not defined in this workspace'
97110
);
@@ -110,7 +123,7 @@ describe('ng-add', () => {
110123
);
111124

112125
await expect(
113-
ngAdd({ project: PROJECT_NAME })(tree, {} as SchematicContext)
126+
ngAdd({ project: PROJECT_NAME })(tree, mockContext)
114127
).rejects.toThrowError(
115128
'Deploy requires an Angular project type of "application" in angular.json'
116129
);
@@ -135,7 +148,7 @@ describe('ng-add', () => {
135148
await expect(
136149
ngAdd({
137150
project: PROJECT_NAME
138-
})(tree, {} as SchematicContext)
151+
})(tree, mockContext)
139152
).rejects.toThrowError(
140153
/Cannot find build target for the Angular project/
141154
);
@@ -168,7 +181,7 @@ describe('ng-add', () => {
168181

169182
const result = await ngAdd({ project: PROJECT_NAME })(
170183
tree,
171-
{} as SchematicContext
184+
mockContext
172185
);
173186

174187
const resultConfig = readJSONFromTree(result, 'angular.json');
@@ -200,7 +213,7 @@ describe('ng-add', () => {
200213

201214
const result = await ngAdd({ project: PROJECT_NAME })(
202215
tree,
203-
{} as SchematicContext
216+
mockContext
204217
);
205218

206219
const resultConfig = readJSONFromTree(result, 'angular.json');
@@ -232,7 +245,7 @@ describe('ng-add', () => {
232245

233246
const result = await ngAdd({ project: PROJECT_NAME })(
234247
tree,
235-
{} as SchematicContext
248+
mockContext
236249
);
237250

238251
const resultConfig = readJSONFromTree(result, 'angular.json');
@@ -263,12 +276,31 @@ describe('ng-add', () => {
263276
);
264277

265278
await expect(
266-
ngAdd({ project: PROJECT_NAME })(tree, {} as SchematicContext)
279+
ngAdd({ project: PROJECT_NAME })(tree, mockContext)
267280
).rejects.toThrowError(
268281
/Invalid outputPath configuration.*Expected undefined.*a string.*an object with a "base" property/
269282
);
270283
});
271284
});
285+
286+
describe('console output', () => {
287+
beforeEach(() => {
288+
jest.clearAllMocks();
289+
});
290+
291+
it('should display next steps after successful installation', async () => {
292+
const tree = Tree.empty();
293+
tree.create('angular.json', JSON.stringify(generateAngularJson()));
294+
295+
await ngAdd({ project: PROJECT_NAME })(tree, mockContext);
296+
297+
expect(mockLogger.info).toHaveBeenCalledWith('🚀 angular-cli-ghpages is ready!');
298+
expect(mockLogger.info).toHaveBeenCalledWith('Next steps:');
299+
expect(mockLogger.info).toHaveBeenCalledWith(' 1. Read the docs: https://github.com/angular-schule/angular-cli-ghpages');
300+
expect(mockLogger.info).toHaveBeenCalledWith(' 2. Deploy via: ng deploy');
301+
expect(mockLogger.info).toHaveBeenCalledWith(' 3. Have a nice day!');
302+
});
303+
});
272304
});
273305

274306
function prettifyJSON(json: string) {

src/ng-add.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ interface NgAddOptions {
1212

1313
export const ngAdd = (options: NgAddOptions) => async (
1414
tree: Tree,
15-
_context: SchematicContext
15+
context: SchematicContext
1616
) => {
1717
const host = createHost(tree);
1818
const { workspace } = await workspaces.readWorkspace('/', host);
@@ -74,5 +74,15 @@ export const ngAdd = (options: NgAddOptions) => async (
7474
});
7575

7676
workspaces.writeWorkspace(workspace, host);
77+
78+
// Show next steps
79+
context.logger.info('');
80+
context.logger.info('🚀 angular-cli-ghpages is ready!');
81+
context.logger.info('');
82+
context.logger.info('Next steps:');
83+
context.logger.info(' 1. Read the docs: https://github.com/angular-schule/angular-cli-ghpages');
84+
context.logger.info(' 2. Deploy via: ng deploy');
85+
context.logger.info(' 3. Have a nice day!');
86+
7787
return tree;
7888
};

src/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "angular-cli-ghpages",
3-
"version": "3.0.0",
3+
"version": "3.0.1",
44
"description": "Deploy your Angular app to GitHub Pages or Cloudflare Pages directly from the Angular CLI (ng deploy)",
55
"main": "index.js",
66
"types": "index.d.ts",

src/test-fixtures/angular-versions.spec.ts

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,19 @@ import fs from 'fs';
1515
import path from 'path';
1616
import { ngAdd } from '../ng-add';
1717

18+
// Mock context with logger - only the methods we actually use
19+
const mockLogger = {
20+
info: jest.fn(),
21+
warn: jest.fn(),
22+
error: jest.fn(),
23+
debug: jest.fn(),
24+
fatal: jest.fn(),
25+
log: jest.fn(),
26+
createChild: jest.fn()
27+
};
28+
29+
const mockContext = { logger: mockLogger } as unknown as SchematicContext;
30+
1831
// Load fixture files - actual angular.json from each Angular CLI version
1932
const fixturesDir = path.join(__dirname);
2033
const angular18Config = JSON.parse(fs.readFileSync(path.join(fixturesDir, 'angular-18.json'), 'utf-8'));
@@ -33,7 +46,7 @@ describe('Angular Version Compatibility', () => {
3346
const tree = Tree.empty();
3447
tree.create('angular.json', JSON.stringify(angular18Config));
3548

36-
const result = await ngAdd({ project: 'ng18' })(tree, {} as SchematicContext);
49+
const result = await ngAdd({ project: 'ng18' })(tree, mockContext);
3750
const resultConfig = JSON.parse(result.read('angular.json')!.toString());
3851

3952
expect(resultConfig.projects.ng18.architect.deploy.builder).toBe('angular-cli-ghpages:deploy');
@@ -50,7 +63,7 @@ describe('Angular Version Compatibility', () => {
5063
const tree = Tree.empty();
5164
tree.create('angular.json', JSON.stringify(angular19Config));
5265

53-
const result = await ngAdd({ project: 'ng19' })(tree, {} as SchematicContext);
66+
const result = await ngAdd({ project: 'ng19' })(tree, mockContext);
5467
const resultConfig = JSON.parse(result.read('angular.json')!.toString());
5568

5669
expect(resultConfig.projects.ng19.architect.deploy.builder).toBe('angular-cli-ghpages:deploy');
@@ -67,7 +80,7 @@ describe('Angular Version Compatibility', () => {
6780
const tree = Tree.empty();
6881
tree.create('angular.json', JSON.stringify(angular20Config));
6982

70-
const result = await ngAdd({ project: 'ng20' })(tree, {} as SchematicContext);
83+
const result = await ngAdd({ project: 'ng20' })(tree, mockContext);
7184
const resultConfig = JSON.parse(result.read('angular.json')!.toString());
7285

7386
expect(resultConfig.projects.ng20.architect.deploy.builder).toBe('angular-cli-ghpages:deploy');
@@ -84,7 +97,7 @@ describe('Angular Version Compatibility', () => {
8497
const tree = Tree.empty();
8598
tree.create('angular.json', JSON.stringify(angular21Config));
8699

87-
const result = await ngAdd({ project: 'ng21' })(tree, {} as SchematicContext);
100+
const result = await ngAdd({ project: 'ng21' })(tree, mockContext);
88101
const resultConfig = JSON.parse(result.read('angular.json')!.toString());
89102

90103
expect(resultConfig.projects.ng21.architect.deploy.builder).toBe('angular-cli-ghpages:deploy');

0 commit comments

Comments
 (0)