Skip to content

Commit edb8587

Browse files
committed
feat(ng-add): add logic for project selection
Since defaultProject is deprecated, the project must be determined differently. Variants: - Use the defaultProject if given (for compatibility) - Use the first project if only one is available - Use the project defined by the --project arg. - Throw an error.
1 parent 0a28c48 commit edb8587

File tree

3 files changed

+139
-7
lines changed

3 files changed

+139
-7
lines changed

src/__snapshots__/ng-add.spec.ts.snap

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
exports[`ng-add generating files generates new files if starting from scratch 1`] = `
44
"{
55
\\"version\\": 1,
6-
\\"defaultProject\\": \\"THEPROJECT\\",
76
\\"projects\\": {
87
\\"THEPROJECT\\": {
98
\\"projectType\\": \\"application\\",
@@ -37,7 +36,6 @@ exports[`ng-add generating files generates new files if starting from scratch 1`
3736
exports[`ng-add generating files overrides existing files 1`] = `
3837
"{
3938
\\"version\\": 1,
40-
\\"defaultProject\\": \\"THEPROJECT\\",
4139
\\"projects\\": {
4240
\\"THEPROJECT\\": {
4341
\\"projectType\\": \\"application\\",
@@ -70,3 +68,92 @@ exports[`ng-add generating files overrides existing files 1`] = `
7068
}
7169
}"
7270
`;
71+
72+
exports[`ng-add project selection should select the default project when not explicitly given (for compatibility!) 1`] = `
73+
"{
74+
\\"version\\": 1,
75+
\\"projects\\": {
76+
\\"THEPROJECT\\": {
77+
\\"projectType\\": \\"application\\",
78+
\\"root\\": \\"PROJECTROOT\\",
79+
\\"architect\\": {
80+
\\"build\\": {
81+
\\"options\\": {
82+
\\"outputPath\\": \\"dist/THEPROJECT\\"
83+
}
84+
},
85+
\\"deploy\\": {
86+
\\"builder\\": \\"angular-cli-ghpages:deploy\\"
87+
}
88+
}
89+
},
90+
\\"OTHERPROJECT\\": {
91+
\\"projectType\\": \\"application\\",
92+
\\"root\\": \\"PROJECTROOT\\",
93+
\\"architect\\": {
94+
\\"build\\": {
95+
\\"options\\": {
96+
\\"outputPath\\": \\"dist/OTHERPROJECT\\"
97+
}
98+
}
99+
}
100+
}
101+
},
102+
\\"defaultProject\\": \\"THEPROJECT\\"
103+
}"
104+
`;
105+
106+
exports[`ng-add project selection should select the explicitly defined project 1`] = `
107+
"{
108+
\\"version\\": 1,
109+
\\"projects\\": {
110+
\\"THEPROJECT\\": {
111+
\\"projectType\\": \\"application\\",
112+
\\"root\\": \\"PROJECTROOT\\",
113+
\\"architect\\": {
114+
\\"build\\": {
115+
\\"options\\": {
116+
\\"outputPath\\": \\"dist/THEPROJECT\\"
117+
}
118+
}
119+
}
120+
},
121+
\\"OTHERPROJECT\\": {
122+
\\"projectType\\": \\"application\\",
123+
\\"root\\": \\"PROJECTROOT\\",
124+
\\"architect\\": {
125+
\\"build\\": {
126+
\\"options\\": {
127+
\\"outputPath\\": \\"dist/OTHERPROJECT\\"
128+
}
129+
},
130+
\\"deploy\\": {
131+
\\"builder\\": \\"angular-cli-ghpages:deploy\\"
132+
}
133+
}
134+
}
135+
}
136+
}"
137+
`;
138+
139+
exports[`ng-add project selection should select the first project if there is only one 1`] = `
140+
"{
141+
\\"version\\": 1,
142+
\\"projects\\": {
143+
\\"OTHERPROJECT\\": {
144+
\\"projectType\\": \\"application\\",
145+
\\"root\\": \\"PROJECTROOT\\",
146+
\\"architect\\": {
147+
\\"build\\": {
148+
\\"options\\": {
149+
\\"outputPath\\": \\"dist/OTHERPROJECT\\"
150+
}
151+
},
152+
\\"deploy\\": {
153+
\\"builder\\": \\"angular-cli-ghpages:deploy\\"
154+
}
155+
}
156+
}
157+
}
158+
}"
159+
`;

src/ng-add.spec.ts

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,61 @@ describe('ng-add', () => {
3939
});
4040
});
4141

42+
describe('project selection', () => {
43+
it('should select the default project when not explicitly given (for compatibility!)', async () => {
44+
const tree = Tree.empty();
45+
const angularJSON = generateAngularJson();
46+
(angularJSON as any).defaultProject = PROJECT_NAME;
47+
tree.create('angular.json', JSON.stringify(angularJSON));
48+
49+
const resultTree = await ngAdd({
50+
project: ''
51+
})(tree, {} as SchematicContext);
52+
53+
const actual = resultTree.read('angular.json')!.toString();
54+
expect(prettifyJSON(actual)).toMatchSnapshot();
55+
});
56+
57+
it('should select the explicitly defined project', async () => {
58+
const tree = Tree.empty();
59+
const angularJSON = generateAngularJson();
60+
tree.create('angular.json', JSON.stringify(angularJSON));
61+
62+
const resultTree = await ngAdd({
63+
project: OTHER_PROJECT_NAME
64+
})(tree, {} as SchematicContext);
65+
66+
const actual = resultTree.read('angular.json')!.toString();
67+
expect(prettifyJSON(actual)).toMatchSnapshot();
68+
});
69+
70+
it('should select the first project if there is only one', async () => {
71+
const tree = Tree.empty();
72+
const angularJSON = generateAngularJson();
73+
delete (angularJSON as any).projects[PROJECT_NAME]; // delete one project so that one is left
74+
tree.create('angular.json', JSON.stringify(angularJSON));
75+
76+
const resultTree = await ngAdd({
77+
project: ''
78+
})(tree, {} as SchematicContext);
79+
80+
const actual = resultTree.read('angular.json')!.toString();
81+
expect(prettifyJSON(actual)).toMatchSnapshot();
82+
});
83+
});
84+
4285
describe('error handling', () => {
43-
it('should fail if project not defined', async () => {
86+
it('should fail if there are multiple projects in workspace and project is not explicitly defined', async () => {
4487
const tree = Tree.empty();
4588
const angularJSON = generateAngularJson();
46-
delete angularJSON.defaultProject;
4789
tree.create('angular.json', JSON.stringify(angularJSON));
4890

4991
await expect(
5092
ngAdd({
5193
project: ''
5294
})(tree, {} as SchematicContext)
5395
).rejects.toThrowError(
54-
'No Angular project selected and no default project in the workspace'
96+
'There is more than one project in your workspace. Please select it manually by using the --project argument.'
5597
);
5698
});
5799

@@ -134,7 +176,6 @@ function prettifyJSON(json: string) {
134176
function generateAngularJson() {
135177
return {
136178
version: 1,
137-
defaultProject: PROJECT_NAME as string | undefined,
138179
projects: {
139180
[PROJECT_NAME]: {
140181
projectType: 'application',

src/ng-add.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@ export const ngAdd = (options: NgAddOptions) => async (
1818
const { workspace } = await workspaces.readWorkspace('/', host);
1919

2020
if (!options.project) {
21+
// TODO: defaultProject is deprecated as for Angular 14. Remove support here when officially removed from Angular.
2122
if (workspace.extensions.defaultProject) {
2223
options.project = workspace.extensions.defaultProject as string;
24+
} else if (workspace.projects.size === 1) {
25+
// If there is only one project, return that one.
26+
options.project = Array.from(workspace.projects.keys())[0];
2327
} else {
2428
throw new SchematicsException(
25-
'No Angular project selected and no default project in the workspace'
29+
'There is more than one project in your workspace. Please select it manually by using the --project argument.'
2630
);
2731
}
2832
}

0 commit comments

Comments
 (0)