Archived
1
0
This repository has been archived on 2024-09-09. You can view files and clone it, but cannot push or open issues or pull requests.
code-server/lib/vscode/extensions/vscode-api-tests/src/singlefolder-tests/editor.test.ts

265 lines
8.5 KiB
TypeScript

/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { workspace, window, Position, Range, commands, TextEditor, TextDocument, TextEditorCursorStyle, TextEditorLineNumbersStyle, SnippetString, Selection, Uri, env } from 'vscode';
import { createRandomFile, deleteFile, closeAllEditors } from '../utils';
suite('vscode API - editors', () => {
teardown(closeAllEditors);
function withRandomFileEditor(initialContents: string, run: (editor: TextEditor, doc: TextDocument) => Thenable<void>): Thenable<boolean> {
return createRandomFile(initialContents).then(file => {
return workspace.openTextDocument(file).then(doc => {
return window.showTextDocument(doc).then((editor) => {
return run(editor, doc).then(_ => {
if (doc.isDirty) {
return doc.save().then(saved => {
assert.ok(saved);
assert.ok(!doc.isDirty);
return deleteFile(file);
});
} else {
return deleteFile(file);
}
});
});
});
});
}
test('insert snippet', () => {
const snippetString = new SnippetString()
.appendText('This is a ')
.appendTabstop()
.appendPlaceholder('placeholder')
.appendText(' snippet');
return withRandomFileEditor('', (editor, doc) => {
return editor.insertSnippet(snippetString).then(inserted => {
assert.ok(inserted);
assert.equal(doc.getText(), 'This is a placeholder snippet');
assert.ok(doc.isDirty);
});
});
});
test('insert snippet with clipboard variables', async function () {
const old = await env.clipboard.readText();
const newValue = 'INTEGRATION-TESTS';
await env.clipboard.writeText(newValue);
const actualValue = await env.clipboard.readText();
if (actualValue !== newValue) {
// clipboard not working?!?
this.skip();
return;
}
const snippetString = new SnippetString('running: $CLIPBOARD');
await withRandomFileEditor('', async (editor, doc) => {
const inserted = await editor.insertSnippet(snippetString);
assert.ok(inserted);
assert.equal(doc.getText(), 'running: INTEGRATION-TESTS');
assert.ok(doc.isDirty);
});
await env.clipboard.writeText(old);
});
test('insert snippet with replacement, editor selection', () => {
const snippetString = new SnippetString()
.appendText('has been');
return withRandomFileEditor('This will be replaced', (editor, doc) => {
editor.selection = new Selection(
new Position(0, 5),
new Position(0, 12)
);
return editor.insertSnippet(snippetString).then(inserted => {
assert.ok(inserted);
assert.equal(doc.getText(), 'This has been replaced');
assert.ok(doc.isDirty);
});
});
});
test('insert snippet with replacement, selection as argument', () => {
const snippetString = new SnippetString()
.appendText('has been');
return withRandomFileEditor('This will be replaced', (editor, doc) => {
const selection = new Selection(
new Position(0, 5),
new Position(0, 12)
);
return editor.insertSnippet(snippetString, selection).then(inserted => {
assert.ok(inserted);
assert.equal(doc.getText(), 'This has been replaced');
assert.ok(doc.isDirty);
});
});
});
test('make edit', () => {
return withRandomFileEditor('', (editor, doc) => {
return editor.edit((builder) => {
builder.insert(new Position(0, 0), 'Hello World');
}).then(applied => {
assert.ok(applied);
assert.equal(doc.getText(), 'Hello World');
assert.ok(doc.isDirty);
});
});
});
test('issue #6281: Edits fail to validate ranges correctly before applying', () => {
return withRandomFileEditor('Hello world!', (editor, doc) => {
return editor.edit((builder) => {
builder.replace(new Range(0, 0, Number.MAX_VALUE, Number.MAX_VALUE), 'new');
}).then(applied => {
assert.ok(applied);
assert.equal(doc.getText(), 'new');
assert.ok(doc.isDirty);
});
});
});
function executeReplace(editor: TextEditor, range: Range, text: string, undoStopBefore: boolean, undoStopAfter: boolean): Thenable<boolean> {
return editor.edit((builder) => {
builder.replace(range, text);
}, { undoStopBefore: undoStopBefore, undoStopAfter: undoStopAfter });
}
test('TextEditor.edit can control undo/redo stack 1', () => {
return withRandomFileEditor('Hello world!', async (editor, doc) => {
const applied1 = await executeReplace(editor, new Range(0, 0, 0, 1), 'h', false, false);
assert.ok(applied1);
assert.equal(doc.getText(), 'hello world!');
assert.ok(doc.isDirty);
const applied2 = await executeReplace(editor, new Range(0, 1, 0, 5), 'ELLO', false, false);
assert.ok(applied2);
assert.equal(doc.getText(), 'hELLO world!');
assert.ok(doc.isDirty);
await commands.executeCommand('undo');
if (doc.getText() === 'hello world!') {
// see https://github.com/microsoft/vscode/issues/109131
// it looks like an undo stop was inserted in between these two edits
// it is unclear why this happens, but it can happen for a multitude of reasons
await commands.executeCommand('undo');
}
assert.equal(doc.getText(), 'Hello world!');
});
});
test('TextEditor.edit can control undo/redo stack 2', () => {
return withRandomFileEditor('Hello world!', (editor, doc) => {
return executeReplace(editor, new Range(0, 0, 0, 1), 'h', false, false).then(applied => {
assert.ok(applied);
assert.equal(doc.getText(), 'hello world!');
assert.ok(doc.isDirty);
return executeReplace(editor, new Range(0, 1, 0, 5), 'ELLO', true, false);
}).then(applied => {
assert.ok(applied);
assert.equal(doc.getText(), 'hELLO world!');
assert.ok(doc.isDirty);
return commands.executeCommand('undo');
}).then(_ => {
assert.equal(doc.getText(), 'hello world!');
});
});
});
test('issue #16573: Extension API: insertSpaces and tabSize are undefined', () => {
return withRandomFileEditor('Hello world!\n\tHello world!', (editor, _doc) => {
assert.equal(editor.options.tabSize, 4);
assert.equal(editor.options.insertSpaces, false);
assert.equal(editor.options.cursorStyle, TextEditorCursorStyle.Line);
assert.equal(editor.options.lineNumbers, TextEditorLineNumbersStyle.On);
editor.options = {
tabSize: 2
};
assert.equal(editor.options.tabSize, 2);
assert.equal(editor.options.insertSpaces, false);
assert.equal(editor.options.cursorStyle, TextEditorCursorStyle.Line);
assert.equal(editor.options.lineNumbers, TextEditorLineNumbersStyle.On);
editor.options.tabSize = 'invalid';
assert.equal(editor.options.tabSize, 2);
assert.equal(editor.options.insertSpaces, false);
assert.equal(editor.options.cursorStyle, TextEditorCursorStyle.Line);
assert.equal(editor.options.lineNumbers, TextEditorLineNumbersStyle.On);
return Promise.resolve();
});
});
test('issue #20757: Overlapping ranges are not allowed!', () => {
return withRandomFileEditor('Hello world!\n\tHello world!', (editor, _doc) => {
return editor.edit((builder) => {
// create two edits that overlap (i.e. are illegal)
builder.replace(new Range(0, 0, 0, 2), 'He');
builder.replace(new Range(0, 1, 0, 3), 'el');
}).then(
(_applied) => {
assert.ok(false, 'edit with overlapping ranges should fail');
},
(_err) => {
assert.ok(true, 'edit with overlapping ranges should fail');
}
);
});
});
test('throw when using invalid edit', async function () {
await withRandomFileEditor('foo', editor => {
return new Promise((resolve, reject) => {
editor.edit(edit => {
edit.insert(new Position(0, 0), 'bar');
setTimeout(() => {
try {
edit.insert(new Position(0, 0), 'bar');
reject(new Error('expected error'));
} catch (err) {
assert.ok(true);
resolve();
}
}, 0);
});
});
});
});
test('editor contents are correctly read (small file)', function () {
return testEditorContents('/far.js');
});
test('editor contents are correctly read (large file)', async function () {
return testEditorContents('/lorem.txt');
});
async function testEditorContents(relativePath: string) {
const root = workspace.workspaceFolders![0]!.uri;
const file = Uri.parse(root.toString() + relativePath);
const document = await workspace.openTextDocument(file);
assert.equal(document.getText(), Buffer.from(await workspace.fs.readFile(file)).toString());
}
});