Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions tests/browser/comment-shortcut.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,57 @@ test("Ctrl+/ and Cmd+/ toggle a comment on the selected lines", async (t) => {
}
});

for (const direction of ["forward", "backward"]) {
test(`comment toggling preserves a ${direction} selection and one-step undo`, async (t) => {
const ctx = await interviewPage(t);
if (!ctx) return;
const { page, errors } = ctx;
try {
for (const { code, end, edited, start, finish } of [
{
code: "alpha\nbeta\ngamma",
end: 10,
edited: "# alpha\n# beta\ngamma",
start: 2,
finish: 14,
},
{
code: "# alpha\n# beta\ngamma",
end: 14,
edited: "alpha\nbeta\ngamma",
start: 0,
finish: 10,
},
]) {
await setBuffer(page, code, direction === "backward" ? end : 0);
for (let i = 0; i < end; i++)
await page.keyboard.press(
direction === "backward" ? "Shift+ArrowLeft" : "Shift+ArrowRight",
);
const selectionDirection = () =>
page
.locator("#editor")
.evaluate((editor) => editor.selectionDirection);
assert.equal(await selectionDirection(), direction);
await page.keyboard.press("Control+/");
assert.equal(await buffer(page), edited);
assert.deepEqual(await selection(page), [start, finish]);
assert.equal(await selectionDirection(), direction);
await page.keyboard.press("Shift+ArrowRight");
assert.deepEqual(await selection(page), [
start + (direction === "backward" ? 1 : 0),
finish + (direction === "forward" ? 1 : 0),
]);
await page.keyboard.press("ControlOrMeta+Z");
assert.equal(await buffer(page), code);
}
assert.deepEqual(errors, []);
} finally {
await page.close();
}
});
}

// The page loads on Python. A toggle that read the language once would go on
// writing `#` into every other tab.
test("the comment marker follows the language tab", async (t) => {
Expand Down
92 changes: 92 additions & 0 deletions tests/browser/editor-pipeline.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,98 @@ test("disabled auto indentation uses native Enter and retains manual indentation
}
});

for (const direction of ["forward", "backward"]) {
for (const { command, code, end, edited, start, finish } of [
{
command: "Tab",
code: "alpha\nbeta\ngamma",
end: 10,
edited: " alpha\n beta\ngamma",
start: 4,
finish: 18,
},
{
command: "Shift+Tab",
code: " alpha\n beta\ngamma",
end: 18,
edited: "alpha\nbeta\ngamma",
start: 0,
finish: 10,
},
{
command: "Shift+Tab",
code: "alpha\nbeta\ngamma",
end: 10,
edited: "alpha\nbeta\ngamma",
start: 0,
finish: 10,
},
]) {
test(`${command} preserves a ${direction} selection${code === edited ? " without changing text" : ""}`, async (t) => {
const ctx = await editorPage(t);
if (!ctx) return;
const { page, errors } = ctx;
try {
await setCode(page, code, direction === "backward" ? end : 0);
for (let i = 0; i < end; i++)
await page.keyboard.press(
direction === "backward" ? "Shift+ArrowLeft" : "Shift+ArrowRight",
);
const selectionDirection = () =>
page
.locator("#editor")
.evaluate((editor) => editor.selectionDirection);
assert.equal(await selectionDirection(), direction);
await page.keyboard.press(command);
assert.deepEqual(await caretState(page), {
value: edited,
start,
end: finish,
});
assert.equal(await selectionDirection(), direction);
await page.keyboard.press("Shift+ArrowRight");
assert.deepEqual(await caretState(page), {
value: edited,
start: start + (direction === "backward" ? 1 : 0),
end: finish + (direction === "forward" ? 1 : 0),
});
if (code !== edited) {
await page.keyboard.press("ControlOrMeta+Z");
assert.equal((await caretState(page)).value, code);
}
assert.deepEqual(errors, []);
} finally {
await page.close();
}
});
}
}

test("replacing a backward selection with Enter leaves a collapsed caret", async (t) => {
const ctx = await editorPage(t);
if (!ctx) return;
const { page, errors } = ctx;
try {
await setCode(page, "alpha\nbeta\ngamma", 10);
for (let i = 0; i < 10; i++) await page.keyboard.press("Shift+ArrowLeft");
await page.keyboard.press("Enter");
assert.deepEqual(await caretState(page), {
value: "\n\ngamma",
start: 1,
end: 1,
});
assert.notEqual(
await page
.locator("#editor")
.evaluate((editor) => editor.selectionDirection),
"backward",
);
assert.deepEqual(errors, []);
} finally {
await page.close();
}
});

test("disabled auto indentation retains parsed bracket highlighting", async (t) => {
const ctx = await editorPage(t, { params: { editorAutoIndent: "0" } });
if (!ctx) return;
Expand Down
7 changes: 5 additions & 2 deletions web/interview.js
Original file line number Diff line number Diff line change
Expand Up @@ -870,8 +870,11 @@ let applyingProgrammaticEdit = false;
function applyEditorEdit(next) {
const editor = nodes.editor;
const previous = editor.value;
// The temporary edit selection must not move the candidate's active end.
const direction =
next.start === next.end ? "none" : editor.selectionDirection;
if (next.value === previous) {
editor.setSelectionRange(next.start, next.end);
editor.setSelectionRange(next.start, next.end, direction);
return;
}
let head = 0;
Expand All @@ -898,7 +901,7 @@ function applyEditorEdit(next) {
editor.value = next.value;
editor.dispatchEvent(new Event("input", { bubbles: true }));
}
editor.setSelectionRange(next.start, next.end);
editor.setSelectionRange(next.start, next.end, direction);
}

function bindEvents() {
Expand Down