open-nomad/ui/tests/integration/util/exec-command-editor-xterm-adapter-test.js

138 lines
3.7 KiB
JavaScript
Raw Normal View History

import ExecCommandEditorXtermAdapter from 'nomad-ui/utils/classes/exec-command-editor-xterm-adapter';
import { setupRenderingTest } from 'ember-qunit';
import { module, test } from 'qunit';
import { render, settled } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
import { Terminal } from 'xterm';
UI: add handling for exec command-editing keys (#7601) This is a minimal implementation that closes #7463. It doesn’t include true support for moving around within the command to edit using arrow keys because it gets too complex when managing wrapping at the edge of the terminal. Instead, arrow keys are ignored. It also ignores ^A and ^E, which are cursor manipulations that pose similar problems to arrow keys. It does support ^U, which deletes the entire command. It also allows a command to be pasted, which was previously unsupported. This is accomplished by migrating from Xterm.js’s onKey handler to onData, which is recommended here: https://github.com/xtermjs/xterm.js/issues/2673#issuecomment-574897733 onData is a higher-level handler that issues events with the final interpreted data instead of the individual key events. That means the processing in this PR has changed from inspecting DOM key events to inspecting their ASCII equivalents, which I’ve extracted into a utility dictionary for use in tests and implementation. One consequence of ignoring most control characters is that if you paste a string that includes a control character, that character will be stripped. It’s somewhat strange for compound sequences like arrow keys; if you run copy('/bin/b' + '\x1b[D' + 'ash') in a Javascript console and paste what’s on the clipboard, you get "/bin/b[Dash". That’s because the left arrow key, as in that centre portion of the string, is represented by the escape character and a coded sequence. Stripping the control character leaves the coded sequence as part of the paste. That seems like an acceptable compromise vs either ignoring any pasted string with control characters (confusing UX) or trying to interpret and strip all such compound control sequences (difficult to be exhaustive).
2020-04-03 17:14:47 +00:00
import KEYS from 'nomad-ui/utils/keys';
module('Integration | Utility | exec-command-editor-xterm-adapter', function(hooks) {
setupRenderingTest(hooks);
test('it can wrap to a previous line while backspacing', async function(assert) {
let done = assert.async();
await render(hbs`
<div id='terminal'></div>
`);
let terminal = new Terminal({ cols: 10 });
terminal.open(document.getElementById('terminal'));
terminal.write('/bin/long-command');
new ExecCommandEditorXtermAdapter(
terminal,
command => {
assert.equal(command, '/bin/long');
done();
},
'/bin/long-command'
);
UI: add handling for exec command-editing keys (#7601) This is a minimal implementation that closes #7463. It doesn’t include true support for moving around within the command to edit using arrow keys because it gets too complex when managing wrapping at the edge of the terminal. Instead, arrow keys are ignored. It also ignores ^A and ^E, which are cursor manipulations that pose similar problems to arrow keys. It does support ^U, which deletes the entire command. It also allows a command to be pasted, which was previously unsupported. This is accomplished by migrating from Xterm.js’s onKey handler to onData, which is recommended here: https://github.com/xtermjs/xterm.js/issues/2673#issuecomment-574897733 onData is a higher-level handler that issues events with the final interpreted data instead of the individual key events. That means the processing in this PR has changed from inspecting DOM key events to inspecting their ASCII equivalents, which I’ve extracted into a utility dictionary for use in tests and implementation. One consequence of ignoring most control characters is that if you paste a string that includes a control character, that character will be stripped. It’s somewhat strange for compound sequences like arrow keys; if you run copy('/bin/b' + '\x1b[D' + 'ash') in a Javascript console and paste what’s on the clipboard, you get "/bin/b[Dash". That’s because the left arrow key, as in that centre portion of the string, is represented by the escape character and a coded sequence. Stripping the control character leaves the coded sequence as part of the paste. That seems like an acceptable compromise vs either ignoring any pasted string with control characters (confusing UX) or trying to interpret and strip all such compound control sequences (difficult to be exhaustive).
2020-04-03 17:14:47 +00:00
await terminal.simulateCommandDataEvent(KEYS.DELETE);
await terminal.simulateCommandDataEvent(KEYS.DELETE);
await terminal.simulateCommandDataEvent(KEYS.DELETE);
await terminal.simulateCommandDataEvent(KEYS.DELETE);
await terminal.simulateCommandDataEvent(KEYS.DELETE);
await terminal.simulateCommandDataEvent(KEYS.DELETE);
await terminal.simulateCommandDataEvent(KEYS.DELETE);
await terminal.simulateCommandDataEvent(KEYS.DELETE);
await settled();
assert.equal(
terminal.buffer.active
.getLine(0)
.translateToString()
.trim(),
'/bin/long'
);
UI: add handling for exec command-editing keys (#7601) This is a minimal implementation that closes #7463. It doesn’t include true support for moving around within the command to edit using arrow keys because it gets too complex when managing wrapping at the edge of the terminal. Instead, arrow keys are ignored. It also ignores ^A and ^E, which are cursor manipulations that pose similar problems to arrow keys. It does support ^U, which deletes the entire command. It also allows a command to be pasted, which was previously unsupported. This is accomplished by migrating from Xterm.js’s onKey handler to onData, which is recommended here: https://github.com/xtermjs/xterm.js/issues/2673#issuecomment-574897733 onData is a higher-level handler that issues events with the final interpreted data instead of the individual key events. That means the processing in this PR has changed from inspecting DOM key events to inspecting their ASCII equivalents, which I’ve extracted into a utility dictionary for use in tests and implementation. One consequence of ignoring most control characters is that if you paste a string that includes a control character, that character will be stripped. It’s somewhat strange for compound sequences like arrow keys; if you run copy('/bin/b' + '\x1b[D' + 'ash') in a Javascript console and paste what’s on the clipboard, you get "/bin/b[Dash". That’s because the left arrow key, as in that centre portion of the string, is represented by the escape character and a coded sequence. Stripping the control character leaves the coded sequence as part of the paste. That seems like an acceptable compromise vs either ignoring any pasted string with control characters (confusing UX) or trying to interpret and strip all such compound control sequences (difficult to be exhaustive).
2020-04-03 17:14:47 +00:00
await terminal.simulateCommandDataEvent(KEYS.ENTER);
});
test('it ignores arrow keys and unprintable characters other than ^U', async function(assert) {
let done = assert.async();
await render(hbs`
<div id='terminal'></div>
`);
let terminal = new Terminal({ cols: 72 });
terminal.open(document.getElementById('terminal'));
terminal.write('/bin/bash');
new ExecCommandEditorXtermAdapter(
terminal,
command => {
assert.equal(command, '/bin/bash!');
done();
},
'/bin/bash'
);
await terminal.simulateCommandDataEvent(KEYS.RIGHT_ARROW);
await terminal.simulateCommandDataEvent(KEYS.RIGHT_ARROW);
await terminal.simulateCommandDataEvent(KEYS.LEFT_ARROW);
await terminal.simulateCommandDataEvent(KEYS.UP_ARROW);
await terminal.simulateCommandDataEvent(KEYS.UP_ARROW);
await terminal.simulateCommandDataEvent(KEYS.DOWN_ARROW);
await terminal.simulateCommandDataEvent(KEYS.CONTROL_A);
await terminal.simulateCommandDataEvent('!');
await settled();
assert.equal(terminal.buffer.active.cursorY, 0);
assert.equal(terminal.buffer.active.cursorX, 10);
UI: add handling for exec command-editing keys (#7601) This is a minimal implementation that closes #7463. It doesn’t include true support for moving around within the command to edit using arrow keys because it gets too complex when managing wrapping at the edge of the terminal. Instead, arrow keys are ignored. It also ignores ^A and ^E, which are cursor manipulations that pose similar problems to arrow keys. It does support ^U, which deletes the entire command. It also allows a command to be pasted, which was previously unsupported. This is accomplished by migrating from Xterm.js’s onKey handler to onData, which is recommended here: https://github.com/xtermjs/xterm.js/issues/2673#issuecomment-574897733 onData is a higher-level handler that issues events with the final interpreted data instead of the individual key events. That means the processing in this PR has changed from inspecting DOM key events to inspecting their ASCII equivalents, which I’ve extracted into a utility dictionary for use in tests and implementation. One consequence of ignoring most control characters is that if you paste a string that includes a control character, that character will be stripped. It’s somewhat strange for compound sequences like arrow keys; if you run copy('/bin/b' + '\x1b[D' + 'ash') in a Javascript console and paste what’s on the clipboard, you get "/bin/b[Dash". That’s because the left arrow key, as in that centre portion of the string, is represented by the escape character and a coded sequence. Stripping the control character leaves the coded sequence as part of the paste. That seems like an acceptable compromise vs either ignoring any pasted string with control characters (confusing UX) or trying to interpret and strip all such compound control sequences (difficult to be exhaustive).
2020-04-03 17:14:47 +00:00
assert.equal(
terminal.buffer.active
UI: add handling for exec command-editing keys (#7601) This is a minimal implementation that closes #7463. It doesn’t include true support for moving around within the command to edit using arrow keys because it gets too complex when managing wrapping at the edge of the terminal. Instead, arrow keys are ignored. It also ignores ^A and ^E, which are cursor manipulations that pose similar problems to arrow keys. It does support ^U, which deletes the entire command. It also allows a command to be pasted, which was previously unsupported. This is accomplished by migrating from Xterm.js’s onKey handler to onData, which is recommended here: https://github.com/xtermjs/xterm.js/issues/2673#issuecomment-574897733 onData is a higher-level handler that issues events with the final interpreted data instead of the individual key events. That means the processing in this PR has changed from inspecting DOM key events to inspecting their ASCII equivalents, which I’ve extracted into a utility dictionary for use in tests and implementation. One consequence of ignoring most control characters is that if you paste a string that includes a control character, that character will be stripped. It’s somewhat strange for compound sequences like arrow keys; if you run copy('/bin/b' + '\x1b[D' + 'ash') in a Javascript console and paste what’s on the clipboard, you get "/bin/b[Dash". That’s because the left arrow key, as in that centre portion of the string, is represented by the escape character and a coded sequence. Stripping the control character leaves the coded sequence as part of the paste. That seems like an acceptable compromise vs either ignoring any pasted string with control characters (confusing UX) or trying to interpret and strip all such compound control sequences (difficult to be exhaustive).
2020-04-03 17:14:47 +00:00
.getLine(0)
.translateToString()
.trim(),
'/bin/bash!'
);
await terminal.simulateCommandDataEvent(KEYS.ENTER);
});
test('it supports typing ^U to delete the entire command', async function(assert) {
let done = assert.async();
await render(hbs`
<div id='terminal'></div>
`);
let terminal = new Terminal({ cols: 10 });
terminal.open(document.getElementById('terminal'));
terminal.write('to-delete');
new ExecCommandEditorXtermAdapter(
terminal,
command => {
assert.equal(command, '!');
done();
},
'to-delete'
);
await terminal.simulateCommandDataEvent(KEYS.CONTROL_U);
await settled();
assert.equal(
terminal.buffer.active
UI: add handling for exec command-editing keys (#7601) This is a minimal implementation that closes #7463. It doesn’t include true support for moving around within the command to edit using arrow keys because it gets too complex when managing wrapping at the edge of the terminal. Instead, arrow keys are ignored. It also ignores ^A and ^E, which are cursor manipulations that pose similar problems to arrow keys. It does support ^U, which deletes the entire command. It also allows a command to be pasted, which was previously unsupported. This is accomplished by migrating from Xterm.js’s onKey handler to onData, which is recommended here: https://github.com/xtermjs/xterm.js/issues/2673#issuecomment-574897733 onData is a higher-level handler that issues events with the final interpreted data instead of the individual key events. That means the processing in this PR has changed from inspecting DOM key events to inspecting their ASCII equivalents, which I’ve extracted into a utility dictionary for use in tests and implementation. One consequence of ignoring most control characters is that if you paste a string that includes a control character, that character will be stripped. It’s somewhat strange for compound sequences like arrow keys; if you run copy('/bin/b' + '\x1b[D' + 'ash') in a Javascript console and paste what’s on the clipboard, you get "/bin/b[Dash". That’s because the left arrow key, as in that centre portion of the string, is represented by the escape character and a coded sequence. Stripping the control character leaves the coded sequence as part of the paste. That seems like an acceptable compromise vs either ignoring any pasted string with control characters (confusing UX) or trying to interpret and strip all such compound control sequences (difficult to be exhaustive).
2020-04-03 17:14:47 +00:00
.getLine(0)
.translateToString()
.trim(),
''
);
await terminal.simulateCommandDataEvent('!');
await terminal.simulateCommandDataEvent(KEYS.ENTER);
});
});