Skip to content

Commit e65c90b

Browse files
committed
Fix race in executeLine and waitForPrompt
1 parent db25c73 commit e65c90b

File tree

1 file changed

+26
-35
lines changed

1 file changed

+26
-35
lines changed

packages/e2e-tests/test/test-shell.ts

+26-35
Original file line numberDiff line numberDiff line change
@@ -222,39 +222,19 @@ export class TestShell {
222222
return this._process;
223223
}
224224

225-
async waitForPrompt(start = 0): Promise<void> {
226-
await eventually(() => {
227-
const output = this._output.slice(start);
225+
/**
226+
* Wait for the last line of the output to become a prompt and resolve with it
227+
*/
228+
async waitForPrompt(start = 0): Promise<string> {
229+
return this.eventually(() => {
230+
const output = this._output.slice(start).trim();
228231
const lines = output.split('\n');
229-
const found = !!lines
230-
.filter((l) => PROMPT_PATTERN.exec(l)) // a line that is the prompt must at least match the pattern
231-
.find((l) => {
232-
// in some situations the prompt occurs multiple times in the line (but only in tests!)
233-
const prompts = l
234-
.trim()
235-
.replace(/>$/g, '')
236-
.split('>')
237-
.map((m) => m.trim());
238-
// if there are multiple prompt parts they must all equal
239-
if (prompts.length > 1) {
240-
for (const p of prompts) {
241-
if (p !== prompts[0]) {
242-
return false;
243-
}
244-
}
245-
}
246-
return true;
247-
});
248-
if (!found) {
249-
throw new assert.AssertionError({
250-
message: 'expected prompt',
251-
expected: PROMPT_PATTERN.toString(),
252-
actual:
253-
this._output.slice(0, start) +
254-
'[prompt search starts here]' +
255-
output,
256-
});
257-
}
232+
const lastLine = lines[lines.length - 1];
233+
assert(
234+
PROMPT_PATTERN.test(lastLine),
235+
`Expected a prompt (last line was "${lastLine}")`
236+
);
237+
return lastLine;
258238
});
259239
}
260240

@@ -341,10 +321,21 @@ export class TestShell {
341321
}
342322

343323
async executeLine(line: string): Promise<string> {
344-
const previousOutputLength = this._output.length;
324+
// Waiting for a prompt to appear since the last execution
325+
await this.waitForPrompt(this._previousOutputLength);
326+
// Keeping an the length of the output to return only output as result of the input
327+
const outputLengthBefore = this._output.length;
345328
this.writeInputLine(line);
346-
await this.waitForPrompt(previousOutputLength);
347-
return this._output.slice(previousOutputLength);
329+
// Wait for the execution and a new prompt to appear
330+
const prompt = await this.waitForPrompt(outputLengthBefore);
331+
// Store the output (excluding the following prompt)
332+
const output = this._output.slice(
333+
outputLengthBefore,
334+
this._output.length - prompt.length - 1
335+
);
336+
// Storing the output for future executions
337+
this._previousOutputLength = outputLengthBefore + output.length;
338+
return output;
348339
}
349340

350341
async executeLineWithJSONResult(line: string): Promise<any> {

0 commit comments

Comments
 (0)