0
# Testing Utilities
1
2
Functions for programmatic testing, response injection, and pre-answering questions during automated testing scenarios. These utilities enable deterministic testing of prompt-based applications without user interaction.
3
4
```javascript
5
const prompts = require('prompts');
6
// Or for specific imports:
7
const { inject, override } = require('prompts');
8
```
9
10
## Capabilities
11
12
### Inject Function
13
14
Programmatically inject responses to simulate user input during testing. Injected values are consumed in order and removed from the internal queue as they are used.
15
16
```javascript { .api }
17
/**
18
* Programmatically inject responses for testing
19
* @param answers - Array of values to inject as responses
20
*/
21
function inject(answers: any[]): void;
22
```
23
24
The inject function accepts an array of values that will be used as responses to prompts in the order they are provided. Each value can be:
25
- **Simple value**: Used as a direct response to the next prompt
26
- **Array of values**: Used for prompts that might be asked multiple times
27
- **Error instance**: Simulates user cancellation/abort
28
29
**Usage Examples:**
30
31
```javascript
32
const prompts = require('prompts');
33
34
// Basic injection for testing
35
prompts.inject(['alice', 25, true]);
36
37
const response = await prompts([
38
{ type: 'text', name: 'name', message: 'Your name?' },
39
{ type: 'number', name: 'age', message: 'Your age?' },
40
{ type: 'confirm', name: 'subscribe', message: 'Subscribe?' }
41
]);
42
43
// Result: { name: 'alice', age: 25, subscribe: true }
44
45
// Inject array values for repeated prompts
46
prompts.inject([
47
'user1',
48
['red', 'blue'], // For multiselect prompt
49
'completed'
50
]);
51
52
// Inject error to simulate cancellation
53
prompts.inject([
54
'alice',
55
new Error('User cancelled'),
56
'fallback'
57
]);
58
59
// Test complex scenarios
60
prompts.inject([
61
'setup-wizard',
62
true, // confirm to continue
63
['database', 'auth'], // multiselect features
64
'production' // environment
65
]);
66
67
const config = await prompts([
68
{ type: 'text', name: 'projectName', message: 'Project name?' },
69
{ type: 'confirm', name: 'useDefaults', message: 'Use defaults?' },
70
{ type: 'multiselect', name: 'features', message: 'Select features:', choices: [...] },
71
{ type: 'select', name: 'env', message: 'Environment:', choices: [...] }
72
]);
73
```
74
75
### Override Function
76
77
Pre-answer questions by providing an object with answers mapped to question names. This allows selective answering of specific prompts while letting others proceed normally.
78
79
```javascript { .api }
80
/**
81
* Pre-answer questions by question name
82
* @param answers - Object mapping question names to their answers
83
*/
84
function override(answers: Record<string, any>): void;
85
```
86
87
The override function takes an object where keys are question names and values are the answers to provide for those questions. Questions with overridden answers will be skipped during prompting.
88
89
**Usage Examples:**
90
91
```javascript
92
const prompts = require('prompts');
93
94
// Override specific questions
95
prompts.override({
96
username: 'alice',
97
environment: 'production'
98
});
99
100
const response = await prompts([
101
{ type: 'text', name: 'username', message: 'Username?' }, // Skipped, uses 'alice'
102
{ type: 'number', name: 'port', message: 'Port?' }, // User prompted
103
{ type: 'select', name: 'environment', message: 'Env?', choices: [...] } // Skipped, uses 'production'
104
]);
105
106
// Combine with command-line arguments
107
const prompts = require('prompts');
108
const yargs = require('yargs');
109
110
// Use command-line args as overrides
111
prompts.override(yargs.argv);
112
113
// Now CLI args like --username=alice --port=3000 will pre-answer those questions
114
115
// Override from environment variables
116
prompts.override({
117
apiKey: process.env.API_KEY,
118
database: process.env.DATABASE_URL,
119
environment: process.env.NODE_ENV
120
});
121
122
// Override for testing specific scenarios
123
prompts.override({
124
confirmDeletion: true,
125
backupFirst: false,
126
targetEnvironment: 'staging'
127
});
128
```
129
130
## Testing Patterns
131
132
### Unit Testing with Injection
133
134
```javascript
135
const prompts = require('prompts');
136
137
describe('User Setup', () => {
138
it('should create user with valid inputs', async () => {
139
// Arrange
140
prompts.inject(['John Doe', 'john@example.com', 30, true]);
141
142
// Act
143
const user = await createUserInteractively();
144
145
// Assert
146
expect(user.name).toBe('John Doe');
147
expect(user.email).toBe('john@example.com');
148
expect(user.age).toBe(30);
149
expect(user.newsletter).toBe(true);
150
});
151
152
it('should handle user cancellation', async () => {
153
// Arrange
154
prompts.inject(['John', new Error('Cancelled by user')]);
155
156
// Act & Assert
157
await expect(createUserInteractively()).rejects.toThrow('User cancelled setup');
158
});
159
});
160
```
161
162
### Integration Testing with Override
163
164
```javascript
165
const prompts = require('prompts');
166
167
describe('CLI Application', () => {
168
beforeEach(() => {
169
// Reset any previous overrides
170
prompts.override({});
171
});
172
173
it('should use production config when specified', async () => {
174
// Arrange
175
prompts.override({
176
environment: 'production',
177
confirm: true
178
});
179
180
// Act
181
const config = await loadConfiguration();
182
183
// Assert
184
expect(config.environment).toBe('production');
185
expect(config.debug).toBe(false);
186
});
187
});
188
```
189
190
### Testing Multiselect and Complex Inputs
191
192
```javascript
193
// Test multiselect inputs
194
prompts.inject([
195
['option1', 'option3'], // Array for multiselect
196
true, // Confirmation
197
'custom-value' // Text input
198
]);
199
200
// Test autocomplete inputs
201
prompts.inject([
202
'java', // Will match 'JavaScript' in autocomplete
203
2 // Select index 2 from filtered results
204
]);
205
206
// Test conditional prompts
207
prompts.inject([
208
'pizza', // Triggers additional topping question
209
'pepperoni', // Topping selection
210
true // Final confirmation
211
]);
212
```
213
214
## Testing Best Practices
215
216
### Clean State Management
217
218
```javascript
219
beforeEach(() => {
220
// Clear any previous injections and overrides
221
prompts.inject([]);
222
prompts.override({});
223
});
224
```
225
226
### Error Simulation
227
228
```javascript
229
// Simulate different types of cancellation
230
prompts.inject([
231
'valid-input',
232
new Error('User pressed Ctrl+C'),
233
'recovery-value'
234
]);
235
236
// Test partial completion scenarios
237
prompts.inject([
238
'first-answer',
239
'second-answer',
240
new Error('Connection lost') // Simulate interruption
241
]);
242
```
243
244
### Environment-Specific Testing
245
246
```javascript
247
// Test different environments
248
const testCases = [
249
{ env: 'development', debug: true },
250
{ env: 'staging', debug: false },
251
{ env: 'production', debug: false }
252
];
253
254
testCases.forEach(({ env, debug }) => {
255
it(`should configure correctly for ${env}`, async () => {
256
prompts.override({ environment: env });
257
const config = await setupEnvironment();
258
expect(config.debug).toBe(debug);
259
});
260
});
261
```
262
263
## Injection Behavior
264
265
### Value Consumption
266
- Injected values are consumed in FIFO (first-in, first-out) order
267
- Each prompt consumes exactly one injected value
268
- If no injected value is available, the prompt displays normally to the user
269
- Used values are removed from the injection queue
270
271
### Array Values
272
- Array values are used for prompts that return arrays (multiselect, list)
273
- For single-value prompts, the entire array is used as the value
274
- For multiselect prompts, array items are treated as selected values
275
276
### Error Handling
277
- Error instances in the injection queue simulate user cancellation
278
- The error is thrown when that position in the queue is reached
279
- Subsequent prompts will use remaining injected values after error handling
280
281
## Override Behavior
282
283
### Name Matching
284
- Override keys must exactly match the `name` property of questions
285
- Case-sensitive matching
286
- Questions without matching override names prompt normally
287
288
### Value Types
289
- Override values can be any type appropriate for the question
290
- No type checking is performed; ensure values match expected types
291
- Invalid values may cause prompt errors
292
293
### Persistence
294
- Override values persist until explicitly cleared with `prompts.override({})`
295
- New override calls merge with existing overrides
296
- Set a key to `undefined` to remove a specific override