@@ -2,7 +2,7 @@ import { promises as fs } from 'fs';
2
2
import * as os from 'os' ;
3
3
import * as path from 'path' ;
4
4
import { env } from 'process' ;
5
- import { execWithEnv } from '../../utils/process' ;
5
+ import { execAndCaptureError , execWithEnv } from '../../utils/process' ;
6
6
7
7
const AUTOCOMPLETION_PROMPT = / W o u l d y o u l i k e t o e n a b l e a u t o c o m p l e t i o n \? / ;
8
8
const DEFAULT_ENV = Object . freeze ( {
@@ -83,6 +83,161 @@ export default async function () {
83
83
'CLI printed that it successfully set up autocompletion when it actually' + " didn't." ,
84
84
) ;
85
85
}
86
+
87
+ if ( ! stdout . includes ( "Ok, you won't be prompted again." ) ) {
88
+ throw new Error ( 'CLI did not inform the user they will not be prompted again.' ) ;
89
+ }
90
+ } ) ;
91
+
92
+ // Does *not* prompt if the user already accepted (even if they delete the completion config).
93
+ await mockHome ( async ( home ) => {
94
+ const bashrc = path . join ( home , '.bashrc' ) ;
95
+ await fs . writeFile ( bashrc , '# Other commands...' ) ;
96
+
97
+ const { stdout : stdout1 } = await execWithEnv (
98
+ 'ng' ,
99
+ [ 'version' ] ,
100
+ {
101
+ ...DEFAULT_ENV ,
102
+ SHELL : '/bin/bash' ,
103
+ HOME : home ,
104
+ } ,
105
+ 'y' /* stdin: accept prompt */ ,
106
+ ) ;
107
+
108
+ if ( ! AUTOCOMPLETION_PROMPT . test ( stdout1 ) ) {
109
+ throw new Error ( 'First execution did not prompt for autocompletion setup.' ) ;
110
+ }
111
+
112
+ const bashrcContents1 = await fs . readFile ( bashrc , 'utf-8' ) ;
113
+ if ( ! bashrcContents1 . includes ( 'source <(ng completion script)' ) ) {
114
+ throw new Error (
115
+ '`~/.bashrc` file was not updated after the user accepted the autocompletion' +
116
+ ` prompt. Contents:\n${ bashrcContents1 } ` ,
117
+ ) ;
118
+ }
119
+
120
+ // User modifies their configuration and removes `ng completion`.
121
+ await fs . writeFile ( bashrc , '# Some new commands...' ) ;
122
+
123
+ const { stdout : stdout2 } = await execWithEnv ( 'ng' , [ 'version' ] , {
124
+ ...DEFAULT_ENV ,
125
+ SHELL : '/bin/bash' ,
126
+ HOME : home ,
127
+ } ) ;
128
+
129
+ if ( AUTOCOMPLETION_PROMPT . test ( stdout2 ) ) {
130
+ throw new Error (
131
+ 'Subsequent execution after rejecting autocompletion setup prompted again' +
132
+ ' when it should not have.' ,
133
+ ) ;
134
+ }
135
+
136
+ const bashrcContents2 = await fs . readFile ( bashrc , 'utf-8' ) ;
137
+ if ( bashrcContents2 !== '# Some new commands...' ) {
138
+ throw new Error (
139
+ '`~/.bashrc` file was incorrectly modified when using a modified `~/.bashrc`' +
140
+ ` after previously accepting the autocompletion prompt. Contents:\n${ bashrcContents2 } ` ,
141
+ ) ;
142
+ }
143
+ } ) ;
144
+
145
+ // Does *not* prompt if the user already rejected.
146
+ await mockHome ( async ( home ) => {
147
+ const bashrc = path . join ( home , '.bashrc' ) ;
148
+ await fs . writeFile ( bashrc , '# Other commands...' ) ;
149
+
150
+ const { stdout : stdout1 } = await execWithEnv (
151
+ 'ng' ,
152
+ [ 'version' ] ,
153
+ {
154
+ ...DEFAULT_ENV ,
155
+ SHELL : '/bin/bash' ,
156
+ HOME : home ,
157
+ } ,
158
+ 'n' /* stdin: reject prompt */ ,
159
+ ) ;
160
+
161
+ if ( ! AUTOCOMPLETION_PROMPT . test ( stdout1 ) ) {
162
+ throw new Error ( 'First execution did not prompt for autocompletion setup.' ) ;
163
+ }
164
+
165
+ const { stdout : stdout2 } = await execWithEnv ( 'ng' , [ 'version' ] , {
166
+ ...DEFAULT_ENV ,
167
+ SHELL : '/bin/bash' ,
168
+ HOME : home ,
169
+ } ) ;
170
+
171
+ if ( AUTOCOMPLETION_PROMPT . test ( stdout2 ) ) {
172
+ throw new Error (
173
+ 'Subsequent execution after rejecting autocompletion setup prompted again' +
174
+ ' when it should not have.' ,
175
+ ) ;
176
+ }
177
+
178
+ const bashrcContents = await fs . readFile ( bashrc , 'utf-8' ) ;
179
+ if ( bashrcContents !== '# Other commands...' ) {
180
+ throw new Error (
181
+ '`~/.bashrc` file was incorrectly modified when the user never accepted the' +
182
+ ` autocompletion prompt. Contents:\n${ bashrcContents } ` ,
183
+ ) ;
184
+ }
185
+ } ) ;
186
+
187
+ // Prompts user again on subsequent execution after accepting prompt but failing to setup.
188
+ await mockHome ( async ( home ) => {
189
+ const bashrc = path . join ( home , '.bashrc' ) ;
190
+ await fs . writeFile ( bashrc , '# Other commands...' ) ;
191
+
192
+ // Make `~/.bashrc` readonly. This is enough for the CLI to verify that the file exists and
193
+ // `ng completion` is not in it, but will fail when actually trying to modify the file.
194
+ await fs . chmod ( bashrc , 0o444 ) ;
195
+
196
+ const err = await execAndCaptureError (
197
+ 'ng' ,
198
+ [ 'version' ] ,
199
+ {
200
+ ...DEFAULT_ENV ,
201
+ SHELL : '/bin/bash' ,
202
+ HOME : home ,
203
+ } ,
204
+ 'y' /* stdin: accept prompt */ ,
205
+ ) ;
206
+
207
+ if ( ! err . message . includes ( 'Failed to append autocompletion setup' ) ) {
208
+ throw new Error (
209
+ `Failed first execution did not print the expected error message. Actual:\n${ err . message } ` ,
210
+ ) ;
211
+ }
212
+
213
+ // User corrects file permissions between executions.
214
+ await fs . chmod ( bashrc , 0o777 ) ;
215
+
216
+ const { stdout : stdout2 } = await execWithEnv (
217
+ 'ng' ,
218
+ [ 'version' ] ,
219
+ {
220
+ ...DEFAULT_ENV ,
221
+ SHELL : '/bin/bash' ,
222
+ HOME : home ,
223
+ } ,
224
+ 'y' /* stdin: accept prompt */ ,
225
+ ) ;
226
+
227
+ if ( ! AUTOCOMPLETION_PROMPT . test ( stdout2 ) ) {
228
+ throw new Error (
229
+ 'Subsequent execution after failed autocompletion setup did not prompt again when it should' +
230
+ ' have.' ,
231
+ ) ;
232
+ }
233
+
234
+ const bashrcContents = await fs . readFile ( bashrc , 'utf-8' ) ;
235
+ if ( ! bashrcContents . includes ( 'ng completion script' ) ) {
236
+ throw new Error (
237
+ '`~/.bashrc` file does not include `ng completion` after the user never accepted the' +
238
+ ` autocompletion prompt a second time. Contents:\n${ bashrcContents } ` ,
239
+ ) ;
240
+ }
86
241
} ) ;
87
242
88
243
// Does *not* prompt user for CI executions.
0 commit comments