Tidy up asserting when command executes, wait for throttle and don't force a sync

This commit is contained in:
Daniel Imms
2024-04-19 05:46:43 -07:00
parent 5b0f10e26e
commit eb43e1910f
2 changed files with 57 additions and 63 deletions
@@ -82,6 +82,9 @@ export class PromptInputModel extends Disposable implements IPromptInputModel {
getCombinedString(): string {
const value = this._value.replaceAll('\n', '\u23CE');
if (this._cursorIndex === -1) {
return value;
}
let result = `${value.substring(0, this.cursorIndex)}|`;
if (this.ghostTextIndex !== -1) {
result += `${value.substring(this.cursorIndex, this.ghostTextIndex)}[`;
@@ -111,6 +114,7 @@ export class PromptInputModel extends Disposable implements IPromptInputModel {
}
this._state = PromptInputState.Execute;
this._cursorIndex = -1;
this._onDidFinishInput.fire();
}
@@ -120,10 +124,6 @@ export class PromptInputModel extends Disposable implements IPromptInputModel {
@throttle(0)
private _sync() {
this._syncNow();
}
protected _syncNow() {
if (this._state !== PromptInputState.Input) {
return;
}
@@ -14,16 +14,10 @@ import { Terminal } from '@xterm/headless';
import { strictEqual } from 'assert';
import { timeout } from 'vs/base/common/async';
class TestPromptInputModel extends PromptInputModel {
forceSync() {
this._syncNow();
}
}
suite('PromptInputModel', () => {
const store = ensureNoDisposablesAreLeakedInTestSuite();
let promptInputModel: TestPromptInputModel;
let promptInputModel: PromptInputModel;
let xterm: Terminal;
let onCommandStart: Emitter<ITerminalCommand>;
let onCommandExecuted: Emitter<ITerminalCommand>;
@@ -40,13 +34,13 @@ suite('PromptInputModel', () => {
onCommandExecuted.fire(null!);
}
function assertPromptInput(valueWithCursor: string) {
if (!valueWithCursor.includes('|')) {
async function assertPromptInput(valueWithCursor: string) {
await timeout(0);
if (promptInputModel.cursorIndex !== -1 && !valueWithCursor.includes('|')) {
throw new Error('assertPromptInput must contain | character');
}
promptInputModel.forceSync();
const actualValueWithCursor = promptInputModel.getCombinedString();
strictEqual(
actualValueWithCursor,
@@ -64,123 +58,123 @@ suite('PromptInputModel', () => {
xterm = store.add(new Terminal({ allowProposedApi: true }));
onCommandStart = store.add(new Emitter());
onCommandExecuted = store.add(new Emitter());
promptInputModel = store.add(new TestPromptInputModel(xterm, onCommandStart.event, onCommandExecuted.event, new NullLogService));
promptInputModel = store.add(new PromptInputModel(xterm, onCommandStart.event, onCommandExecuted.event, new NullLogService));
});
test('basic input and execute', async () => {
await writePromise('$ ');
fireCommandStart();
assertPromptInput('|');
await assertPromptInput('|');
await writePromise('foo bar');
assertPromptInput('foo bar|');
await assertPromptInput('foo bar|');
await writePromise('\r\n');
fireCommandExecuted();
assertPromptInput('foo bar|');
await assertPromptInput('foo bar');
await writePromise('(command output)\r\n$ ');
fireCommandStart();
assertPromptInput('|');
await assertPromptInput('|');
});
test('cursor navigation', async () => {
await writePromise('$ ');
fireCommandStart();
assertPromptInput('|');
await assertPromptInput('|');
await writePromise('foo bar');
assertPromptInput('foo bar|');
await assertPromptInput('foo bar|');
await writePromise('\x1b[3D');
assertPromptInput('foo |bar');
await assertPromptInput('foo |bar');
await writePromise('\x1b[4D');
assertPromptInput('|foo bar');
await assertPromptInput('|foo bar');
await writePromise('\x1b[3C');
assertPromptInput('foo| bar');
await assertPromptInput('foo| bar');
await writePromise('\x1b[4C');
assertPromptInput('foo bar|');
await assertPromptInput('foo bar|');
await writePromise('\x1b[D');
assertPromptInput('foo ba|r');
await assertPromptInput('foo ba|r');
await writePromise('\x1b[C');
assertPromptInput('foo bar|');
await assertPromptInput('foo bar|');
});
test('ghost text', async () => {
await writePromise('$ ');
fireCommandStart();
assertPromptInput('|');
await assertPromptInput('|');
await writePromise('foo\x1b[2m bar\x1b[0m\x1b[4D');
assertPromptInput('foo|[ bar]');
await assertPromptInput('foo|[ bar]');
await writePromise('\x1b[2D');
assertPromptInput('f|oo[ bar]');
await assertPromptInput('f|oo[ bar]');
});
test('wide input (Korean)', async () => {
await writePromise('$ ');
fireCommandStart();
assertPromptInput('|');
await assertPromptInput('|');
await writePromise('안영');
assertPromptInput('안영|');
await assertPromptInput('안영|');
await writePromise('\r\n컴퓨터');
assertPromptInput('안영\n컴퓨터|');
await assertPromptInput('안영\n컴퓨터|');
await writePromise('\r\n사람');
assertPromptInput('안영\n컴퓨터\n사람|');
await assertPromptInput('안영\n컴퓨터\n사람|');
await writePromise('\x1b[G');
assertPromptInput('안영\n컴퓨터\n|사람');
await assertPromptInput('안영\n컴퓨터\n|사람');
await writePromise('\x1b[A');
assertPromptInput('안영\n|컴퓨터\n사람');
await assertPromptInput('안영\n|컴퓨터\n사람');
await writePromise('\x1b[4C');
assertPromptInput('안영\n컴퓨|터\n사람');
await assertPromptInput('안영\n컴퓨|터\n사람');
await writePromise('\x1b[1;4H');
assertPromptInput('안|영\n컴퓨터\n사람');
await assertPromptInput('안|영\n컴퓨터\n사람');
await writePromise('\x1b[D');
assertPromptInput('|안영\n컴퓨터\n사람');
await assertPromptInput('|안영\n컴퓨터\n사람');
});
test('emoji input', async () => {
await writePromise('$ ');
fireCommandStart();
assertPromptInput('|');
await assertPromptInput('|');
await writePromise('✌️👍');
assertPromptInput('✌️👍|');
await assertPromptInput('✌️👍|');
await writePromise('\r\n😎😕😅');
assertPromptInput('✌️👍\n😎😕😅|');
await assertPromptInput('✌️👍\n😎😕😅|');
await writePromise('\r\n🤔🤷😩');
assertPromptInput('✌️👍\n😎😕😅\n🤔🤷😩|');
await assertPromptInput('✌️👍\n😎😕😅\n🤔🤷😩|');
await writePromise('\x1b[G');
assertPromptInput('✌️👍\n😎😕😅\n|🤔🤷😩');
await assertPromptInput('✌️👍\n😎😕😅\n|🤔🤷😩');
await writePromise('\x1b[A');
assertPromptInput('✌️👍\n|😎😕😅\n🤔🤷😩');
await assertPromptInput('✌️👍\n|😎😕😅\n🤔🤷😩');
await writePromise('\x1b[2C');
assertPromptInput('✌️👍\n😎😕|😅\n🤔🤷😩');
await assertPromptInput('✌️👍\n😎😕|😅\n🤔🤷😩');
await writePromise('\x1b[1;4H');
assertPromptInput('✌️|👍\n😎😕😅\n🤔🤷😩');
await assertPromptInput('✌️|👍\n😎😕😅\n🤔🤷😩');
await writePromise('\x1b[D');
assertPromptInput('|✌️👍\n😎😕😅\n🤔🤷😩');
await assertPromptInput('|✌️👍\n😎😕😅\n🤔🤷😩');
});
// To "record a session" for these tests:
@@ -206,7 +200,7 @@ suite('PromptInputModel', () => {
'\r\n03:13:47  vscode   tyriar/prompt_input_model  $⇡  via  v18.18.2 \r\n ',
]);
fireCommandStart();
assertPromptInput('|');
await assertPromptInput('|');
await replayEvents([
'[?25lfakecommand[?25h',
@@ -216,7 +210,7 @@ suite('PromptInputModel', () => {
'[?25lfoo[?25h',
'',
]);
assertPromptInput('foo|');
await assertPromptInput('foo|');
});
test('input with accepted and run ghost text', async () => {
await replayEvents([
@@ -229,62 +223,62 @@ suite('PromptInputModel', () => {
]);
promptInputModel.setContinuationPrompt('∙ ');
fireCommandStart();
assertPromptInput('|');
await assertPromptInput('|');
await replayEvents([
'[?25lecho "hello world"[?25h',
'',
]);
assertPromptInput('e|[cho "hello world"]');
await assertPromptInput('e|[cho "hello world"]');
await replayEvents([
'[?25lecho "hello world"[?25h',
'',
]);
assertPromptInput('ec|[ho "hello world"]');
await assertPromptInput('ec|[ho "hello world"]');
await replayEvents([
'[?25lecho "hello world"[?25h',
'',
]);
assertPromptInput('ech|[o "hello world"]');
await assertPromptInput('ech|[o "hello world"]');
await replayEvents([
'[?25lecho "hello world"[?25h',
'',
]);
assertPromptInput('echo|[ "hello world"]');
await assertPromptInput('echo|[ "hello world"]');
await replayEvents([
'[?25lecho "hello world"[?25h',
'',
]);
assertPromptInput('echo |["hello world"]');
await assertPromptInput('echo |["hello world"]');
await replayEvents([
'[?25lecho "hello world"[?25h',
'',
]);
assertPromptInput('echo "hello world"|');
await assertPromptInput('echo "hello world"|');
await replayEvents([
']633;E;echo "hello world";ff464d39-bc80-4bae-9ead-b1cafc4adf6f]633;C',
]);
fireCommandExecuted();
assertPromptInput('echo "hello world"|');
await assertPromptInput('echo "hello world"');
await replayEvents([
'\r\n',
'hello world\r\n',
]);
assertPromptInput('echo "hello world"|');
await assertPromptInput('echo "hello world"');
await replayEvents([
']633;D;0]633;A]633;P;Cwd=C:\x5cGithub\x5cmicrosoft\x5cvscode]633;B',
'\r\n03:41:42  vscode   tyriar/prompt_input_model  $  via  v18.18.2 \r\n ',
]);
fireCommandStart();
assertPromptInput('|');
await assertPromptInput('|');
});
test('input, go to start (ctrl+home), delete word in front (ctrl+delete)', async () => {
@@ -297,7 +291,7 @@ suite('PromptInputModel', () => {
'\r\n16:07:06  vscode   tyriar/210662  $!  via  v18.18.2 \r\n ',
]);
fireCommandStart();
assertPromptInput('|');
await assertPromptInput('|');
await replayEvents([
'[?25lGit push[?25h',
@@ -306,7 +300,7 @@ suite('PromptInputModel', () => {
'',
'[?25lGet-ChildItem -Path a[?25h',
]);
assertPromptInput('Get|[-ChildItem -Path a]');
await assertPromptInput('Get|[-ChildItem -Path a]');
await replayEvents([
'',