Skip to content

Commit 5f6c17e

Browse files
committed
test: add TabstopManager editor-session tests
Real-editor (createMockEditor) tests for insertSnippet: single-stop caret placement, placeholder selection, the import-completion snippet, multi-stop Tab/Shift-Tab navigation ending at $0, Esc, markers following edits above the snippet, and range replacement.
1 parent 69b6401 commit 5f6c17e

1 file changed

Lines changed: 125 additions & 2 deletions

File tree

test/spec/TabstopManager-test.js

Lines changed: 125 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,11 @@
1818
*
1919
*/
2020

21-
/*global describe, it, expect*/
21+
/*global describe, it, expect, afterEach*/
2222

2323
define(function (require, exports, module) {
24-
const TabstopManager = require("editor/TabstopManager");
24+
const TabstopManager = require("editor/TabstopManager"),
25+
SpecRunnerUtils = require("spec/SpecRunnerUtils");
2526

2627
describe("unit:TabstopManager", function () {
2728

@@ -155,5 +156,127 @@ define(function (require, exports, module) {
155156
]);
156157
});
157158
});
159+
160+
// insertSnippet drives the real editor: text replacement, caret/selection placement and the
161+
// marker-backed Tab/Shift-Tab session. Uses a mock editor (a real Editor + CodeMirror), which
162+
// runs in the unit category like Editor-test.
163+
describe("insertSnippet - editor session", function () {
164+
let myDocument, myEditor;
165+
166+
function createTestEditor(content) {
167+
const mocks = SpecRunnerUtils.createMockEditor(content || "", "javascript");
168+
myDocument = mocks.doc;
169+
myEditor = mocks.editor;
170+
}
171+
172+
// Reach the live Tab-session keymap CodeMirror is using, so we exercise the exact
173+
// bindings insertSnippet installed rather than re-implementing navigation here.
174+
function sessionKeymap() {
175+
return (myEditor._codeMirror.state.keyMaps || []).filter(function (m) {
176+
return m.name === "tabstop-session";
177+
})[0];
178+
}
179+
function pressTab() {
180+
sessionKeymap().Tab(myEditor._codeMirror);
181+
}
182+
function pressShiftTab() {
183+
sessionKeymap()["Shift-Tab"](myEditor._codeMirror);
184+
}
185+
186+
const ORIGIN = { line: 0, ch: 0 };
187+
188+
afterEach(function () {
189+
TabstopManager.endSession(); // before destroy so no marker ops run on a dead editor
190+
if (myEditor) {
191+
SpecRunnerUtils.destroyMockEditor(myDocument);
192+
myEditor = null;
193+
myDocument = null;
194+
}
195+
});
196+
197+
it("should insert plain text and place the caret at the single stop (no session)", function () {
198+
createTestEditor("");
199+
TabstopManager.insertSnippet(myEditor, "log($1)", ORIGIN, ORIGIN);
200+
expect(myDocument.getText()).toBe("log()");
201+
const cursor = myEditor.getCursorPos();
202+
expect([cursor.line, cursor.ch]).toEqual([0, 4]);
203+
expect(myEditor.getSelectedText()).toBe("");
204+
expect(TabstopManager.hasActiveSession()).toBe(false);
205+
});
206+
207+
it("should select a single placeholder's default text for type-over", function () {
208+
createTestEditor("");
209+
TabstopManager.insertSnippet(myEditor, "foo(${1:bar})", ORIGIN, ORIGIN);
210+
expect(myDocument.getText()).toBe("foo(bar)");
211+
expect(myEditor.getSelectedText()).toBe("bar");
212+
expect(TabstopManager.hasActiveSession()).toBe(false);
213+
});
214+
215+
it("should expand the import-completion snippet without a literal $1", function () {
216+
createTestEditor("import getfromi");
217+
TabstopManager.insertSnippet(myEditor, 'import { getFromIndex$1 } from "./db";',
218+
ORIGIN, { line: 0, ch: 15 });
219+
expect(myDocument.getText()).toBe('import { getFromIndex } from "./db";');
220+
const cursor = myEditor.getCursorPos();
221+
expect([cursor.line, cursor.ch]).toEqual([0, 21]); // right after getFromIndex
222+
expect(TabstopManager.hasActiveSession()).toBe(false);
223+
});
224+
225+
it("should start a session and navigate stops with Tab, ending at $0", function () {
226+
createTestEditor("");
227+
TabstopManager.insertSnippet(myEditor, "connect(${1:host}, ${2:port})$0", ORIGIN, ORIGIN);
228+
expect(myDocument.getText()).toBe("connect(host, port)");
229+
expect(myEditor.getSelectedText()).toBe("host");
230+
expect(TabstopManager.hasActiveSession()).toBe(true);
231+
232+
pressTab();
233+
expect(myEditor.getSelectedText()).toBe("port");
234+
expect(TabstopManager.hasActiveSession()).toBe(true);
235+
236+
pressTab();
237+
// landed on $0 (end of text) - caret only, session ends
238+
const cursor = myEditor.getCursorPos();
239+
expect([cursor.line, cursor.ch]).toEqual([0, 19]);
240+
expect(myEditor.getSelectedText()).toBe("");
241+
expect(TabstopManager.hasActiveSession()).toBe(false);
242+
});
243+
244+
it("should navigate backwards with Shift-Tab", function () {
245+
createTestEditor("");
246+
TabstopManager.insertSnippet(myEditor, "${1:a} ${2:b} $0", ORIGIN, ORIGIN);
247+
expect(myEditor.getSelectedText()).toBe("a");
248+
pressTab();
249+
expect(myEditor.getSelectedText()).toBe("b");
250+
pressShiftTab();
251+
expect(myEditor.getSelectedText()).toBe("a");
252+
expect(TabstopManager.hasActiveSession()).toBe(true);
253+
});
254+
255+
it("should end the session on Esc", function () {
256+
createTestEditor("");
257+
TabstopManager.insertSnippet(myEditor, "${1:a} ${2:b}", ORIGIN, ORIGIN);
258+
expect(TabstopManager.hasActiveSession()).toBe(true);
259+
sessionKeymap().Esc(myEditor._codeMirror);
260+
expect(TabstopManager.hasActiveSession()).toBe(false);
261+
});
262+
263+
it("should keep stops correct when text is inserted above (markers follow edits)", function () {
264+
createTestEditor("");
265+
TabstopManager.insertSnippet(myEditor, "fn(${1:a}, ${2:b})", ORIGIN, ORIGIN);
266+
expect(myEditor.getSelectedText()).toBe("a");
267+
// Simulate an auto-import line being added above the snippet after insertion.
268+
myEditor.document.replaceRange("import x;\n", ORIGIN);
269+
pressTab();
270+
const sel = myEditor.getSelection();
271+
expect(myEditor.getSelectedText()).toBe("b");
272+
expect(sel.start.line).toBe(1); // snippet now lives on line 1
273+
});
274+
275+
it("should replace the given range, not just insert at the cursor", function () {
276+
createTestEditor("foo.barbaz");
277+
TabstopManager.insertSnippet(myEditor, "log($1)", { line: 0, ch: 4 }, { line: 0, ch: 7 });
278+
expect(myDocument.getText()).toBe("foo.log()baz");
279+
});
280+
});
158281
});
159282
});

0 commit comments

Comments
 (0)