mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-21 17:19:01 +01:00
add API tests that run on a workspace
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import 'mocha';
|
||||
import * as assert from 'assert';
|
||||
import { join } from 'path';
|
||||
import { commands, workspace, window, Uri, ViewColumn, Range, Position } from 'vscode';
|
||||
|
||||
suite('commands namespace tests', () => {
|
||||
|
||||
test('getCommands', function (done) {
|
||||
|
||||
let p1 = commands.getCommands().then(commands => {
|
||||
let hasOneWithUnderscore = false;
|
||||
for (let command of commands) {
|
||||
if (command[0] === '_') {
|
||||
hasOneWithUnderscore = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert.ok(hasOneWithUnderscore);
|
||||
}, done);
|
||||
|
||||
let p2 = commands.getCommands(true).then(commands => {
|
||||
let hasOneWithUnderscore = false;
|
||||
for (let command of commands) {
|
||||
if (command[0] === '_') {
|
||||
hasOneWithUnderscore = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert.ok(!hasOneWithUnderscore);
|
||||
}, done);
|
||||
|
||||
Promise.all([p1, p2]).then(() => {
|
||||
done();
|
||||
}, done);
|
||||
});
|
||||
|
||||
test('command with args', function () {
|
||||
|
||||
let args: IArguments;
|
||||
let registration = commands.registerCommand('t1', function () {
|
||||
args = arguments;
|
||||
});
|
||||
|
||||
return commands.executeCommand('t1', 'start').then(() => {
|
||||
registration.dispose();
|
||||
|
||||
assert.ok(args);
|
||||
assert.equal(args.length, 1);
|
||||
assert.equal(args[0], 'start');
|
||||
});
|
||||
});
|
||||
|
||||
test('editorCommand with extra args', function () {
|
||||
|
||||
let args: IArguments;
|
||||
let registration = commands.registerTextEditorCommand('t1', function () {
|
||||
args = arguments;
|
||||
});
|
||||
|
||||
return workspace.openTextDocument(join(workspace.rootPath || '', './far.js')).then(doc => {
|
||||
return window.showTextDocument(doc).then(editor => {
|
||||
return commands.executeCommand('t1', 12345, commands);
|
||||
}).then(() => {
|
||||
assert.ok(args);
|
||||
assert.equal(args.length, 4);
|
||||
assert.ok(args[2] === 12345);
|
||||
assert.ok(args[3] === commands);
|
||||
registration.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
test('api-command: vscode.previewHtm', function () {
|
||||
|
||||
let registration = workspace.registerTextDocumentContentProvider('speciale', {
|
||||
provideTextDocumentContent(uri) {
|
||||
return `content of URI <b>${uri.toString()}</b>`;
|
||||
}
|
||||
});
|
||||
|
||||
let virtualDocumentUri = Uri.parse('speciale://authority/path');
|
||||
let title = 'A title';
|
||||
|
||||
return commands.executeCommand('vscode.previewHtml', virtualDocumentUri, ViewColumn.Three, title).then(success => {
|
||||
assert.ok(success);
|
||||
registration.dispose();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
test('api-command: vscode.diff', function () {
|
||||
|
||||
let registration = workspace.registerTextDocumentContentProvider('sc', {
|
||||
provideTextDocumentContent(uri) {
|
||||
return `content of URI <b>${uri.toString()}</b>#${Math.random()}`;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
let a = commands.executeCommand('vscode.diff', Uri.parse('sc:a'), Uri.parse('sc:b'), 'DIFF').then(value => {
|
||||
assert.ok(value === void 0);
|
||||
registration.dispose();
|
||||
});
|
||||
|
||||
let b = commands.executeCommand('vscode.diff', Uri.parse('sc:a'), Uri.parse('sc:b')).then(value => {
|
||||
assert.ok(value === void 0);
|
||||
registration.dispose();
|
||||
});
|
||||
|
||||
let c = commands.executeCommand('vscode.diff', Uri.parse('sc:a'), Uri.parse('sc:b'), 'Title', { selection: new Range(new Position(1, 1), new Position(1, 2)) }).then(value => {
|
||||
assert.ok(value === void 0);
|
||||
registration.dispose();
|
||||
});
|
||||
|
||||
let d = commands.executeCommand('vscode.diff').then(() => assert.ok(false), () => assert.ok(true));
|
||||
let e = commands.executeCommand('vscode.diff', 1, 2, 3).then(() => assert.ok(false), () => assert.ok(true));
|
||||
|
||||
return Promise.all([a, b, c, d, e]);
|
||||
});
|
||||
|
||||
test('api-command: vscode.open', function () {
|
||||
let uri = Uri.file(join(workspace.rootPath || '', './image.png'));
|
||||
let a = commands.executeCommand('vscode.open', uri).then(() => assert.ok(true), () => assert.ok(false));
|
||||
let b = commands.executeCommand('vscode.open', uri, ViewColumn.Two).then(() => assert.ok(true), () => assert.ok(false));
|
||||
let c = commands.executeCommand('vscode.open').then(() => assert.ok(false), () => assert.ok(true));
|
||||
let d = commands.executeCommand('vscode.open', uri, true).then(() => assert.ok(false), () => assert.ok(true));
|
||||
|
||||
return Promise.all([a, b, c, d]);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,46 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'mocha';
|
||||
import * as assert from 'assert';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
suite('Configuration tests', () => {
|
||||
|
||||
test('configurations, language defaults', function () {
|
||||
const defaultLanguageSettings = vscode.workspace.getConfiguration().get('[abcLang]');
|
||||
|
||||
assert.deepEqual(defaultLanguageSettings, {
|
||||
'editor.lineNumbers': 'off',
|
||||
'editor.tabSize': 2
|
||||
});
|
||||
});
|
||||
|
||||
test('configuration, defaults', () => {
|
||||
const config = vscode.workspace.getConfiguration('farboo');
|
||||
|
||||
assert.ok(config.has('config0'));
|
||||
assert.equal(config.get('config0'), true);
|
||||
assert.equal(config.get('config4'), '');
|
||||
assert.equal(config['config0'], true);
|
||||
assert.equal(config['config4'], '');
|
||||
|
||||
assert.throws(() => (<any>config)['config4'] = 'valuevalue');
|
||||
|
||||
assert.ok(config.has('nested.config1'));
|
||||
assert.equal(config.get('nested.config1'), 42);
|
||||
assert.ok(config.has('nested.config2'));
|
||||
assert.equal(config.get('nested.config2'), 'Das Pferd frisst kein Reis.');
|
||||
});
|
||||
|
||||
test('configuration, name vs property', () => {
|
||||
const config = vscode.workspace.getConfiguration('farboo');
|
||||
|
||||
assert.ok(config.has('get'));
|
||||
assert.equal(config.get('get'), 'get-prop');
|
||||
assert.deepEqual(config['get'], config.get);
|
||||
assert.throws(() => config['get'] = <any>'get-prop');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,200 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { workspace, window, Position, Range, commands, TextEditor, TextDocument, TextEditorCursorStyle, TextEditorLineNumbersStyle, SnippetString, Selection } from 'vscode';
|
||||
import { createRandomFile, deleteFile, closeAllEditors } from '../utils';
|
||||
|
||||
suite('editor tests', () => {
|
||||
|
||||
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 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!', (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', false, 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('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');
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { env } from 'vscode';
|
||||
|
||||
suite('env-namespace', () => {
|
||||
|
||||
test('env is set', function () {
|
||||
assert.equal(typeof env.language, 'string');
|
||||
assert.equal(typeof env.appRoot, 'string');
|
||||
assert.equal(typeof env.appName, 'string');
|
||||
assert.equal(typeof env.machineId, 'string');
|
||||
assert.equal(typeof env.sessionId, 'string');
|
||||
});
|
||||
|
||||
test('env is readonly', function () {
|
||||
assert.throws(() => env.language = '234');
|
||||
assert.throws(() => env.appRoot = '234');
|
||||
assert.throws(() => env.appName = '234');
|
||||
assert.throws(() => env.machineId = '234');
|
||||
assert.throws(() => env.sessionId = '234');
|
||||
});
|
||||
|
||||
});
|
||||
28
extensions/vscode-api-tests/src/singlefolder-tests/index.ts
Normal file
28
extensions/vscode-api-tests/src/singlefolder-tests/index.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
//
|
||||
// PLEASE DO NOT MODIFY / DELETE UNLESS YOU KNOW WHAT YOU ARE DOING
|
||||
//
|
||||
// This file is providing the test runner to use when running extension tests.
|
||||
// By default the test runner in use is Mocha based.
|
||||
//
|
||||
// You can provide your own test runner if you want to override it by exporting
|
||||
// a function run(testRoot: string, clb: (error:Error) => void) that the extension
|
||||
// host can call to run the tests. The test runner is expected to use console.log
|
||||
// to report the results back to the caller. When the tests are finished, return
|
||||
// a possible error to the callback or null if none.
|
||||
|
||||
const testRunner = require('vscode/lib/testrunner');
|
||||
|
||||
// You can directly control Mocha options by uncommenting the following lines
|
||||
// See https://github.com/mochajs/mocha/wiki/Using-mocha-programmatically#set-options for more info
|
||||
testRunner.configure({
|
||||
ui: 'tdd', // the TDD UI is being used in extension.test.ts (suite, test, etc.)
|
||||
useColors: process.platform !== 'win32', // colored output from test results (only windows cannot handle)
|
||||
timeout: 60000
|
||||
});
|
||||
|
||||
export = testRunner;
|
||||
@@ -0,0 +1,89 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { join } from 'path';
|
||||
import {
|
||||
languages, workspace, commands, Uri, Diagnostic, Range, Command, Disposable, CancellationToken,
|
||||
CompletionList, CompletionItem, CompletionItemKind, TextDocument, Position
|
||||
} from 'vscode';
|
||||
|
||||
suite('languages namespace tests', () => {
|
||||
|
||||
test('diagnostics & CodeActionProvider', function () {
|
||||
|
||||
class D2 extends Diagnostic {
|
||||
customProp = { complex() { } };
|
||||
constructor() {
|
||||
super(new Range(0, 2, 0, 7), 'sonntag');
|
||||
}
|
||||
}
|
||||
|
||||
let diag1 = new Diagnostic(new Range(0, 0, 0, 5), 'montag');
|
||||
let diag2 = new D2();
|
||||
|
||||
let ran = false;
|
||||
let uri = Uri.parse('ttt:path.far');
|
||||
|
||||
let r1 = languages.registerCodeActionsProvider({ pattern: '*.far', scheme: 'ttt' }, {
|
||||
provideCodeActions(document, range, ctx): Command[] {
|
||||
|
||||
assert.equal(ctx.diagnostics.length, 2);
|
||||
let [first, second] = ctx.diagnostics;
|
||||
assert.ok(first === diag1);
|
||||
assert.ok(second === diag2);
|
||||
assert.ok(diag2 instanceof D2);
|
||||
ran = true;
|
||||
return [];
|
||||
}
|
||||
});
|
||||
|
||||
let r2 = workspace.registerTextDocumentContentProvider('ttt', {
|
||||
provideTextDocumentContent() {
|
||||
return 'this is some text';
|
||||
}
|
||||
});
|
||||
|
||||
let r3 = languages.createDiagnosticCollection();
|
||||
r3.set(uri, [diag1]);
|
||||
|
||||
let r4 = languages.createDiagnosticCollection();
|
||||
r4.set(uri, [diag2]);
|
||||
|
||||
return workspace.openTextDocument(uri).then(doc => {
|
||||
return commands.executeCommand('vscode.executeCodeActionProvider', uri, new Range(0, 0, 0, 10));
|
||||
}).then(commands => {
|
||||
assert.ok(ran);
|
||||
Disposable.from(r1, r2, r3, r4).dispose();
|
||||
});
|
||||
});
|
||||
|
||||
test('completions with document filters', function () {
|
||||
let ran = false;
|
||||
let uri = Uri.file(join(workspace.rootPath || '', './bower.json'));
|
||||
|
||||
let jsonDocumentFilter = [{ language: 'json', pattern: '**/package.json' }, { language: 'json', pattern: '**/bower.json' }, { language: 'json', pattern: '**/.bower.json' }];
|
||||
|
||||
let r1 = languages.registerCompletionItemProvider(jsonDocumentFilter, {
|
||||
provideCompletionItems: (document: TextDocument, position: Position, token: CancellationToken): CompletionItem[] => {
|
||||
let proposal = new CompletionItem('foo');
|
||||
proposal.kind = CompletionItemKind.Property;
|
||||
ran = true;
|
||||
return [proposal];
|
||||
}
|
||||
});
|
||||
|
||||
return workspace.openTextDocument(uri).then(doc => {
|
||||
return commands.executeCommand<CompletionList>('vscode.executeCompletionItemProvider', uri, new Position(1, 0));
|
||||
}).then((result: CompletionList | undefined) => {
|
||||
r1.dispose();
|
||||
assert.ok(ran);
|
||||
console.log(result!.items);
|
||||
assert.equal(result!.items[0].label, 'foo');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,434 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { workspace, window, commands, ViewColumn, TextEditorViewColumnChangeEvent, Uri, Selection, Position, CancellationTokenSource, TextEditorSelectionChangeKind } from 'vscode';
|
||||
import { join } from 'path';
|
||||
import { closeAllEditors, pathEquals, createRandomFile } from '../utils';
|
||||
|
||||
suite('window namespace tests', () => {
|
||||
|
||||
teardown(closeAllEditors);
|
||||
|
||||
test('editor, active text editor', () => {
|
||||
return workspace.openTextDocument(join(workspace.rootPath || '', './far.js')).then(doc => {
|
||||
return window.showTextDocument(doc).then((editor) => {
|
||||
const active = window.activeTextEditor;
|
||||
assert.ok(active);
|
||||
assert.ok(pathEquals(active!.document.uri.fsPath, doc.uri.fsPath));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('editor, opened via resource', () => {
|
||||
const uri = Uri.file(join(workspace.rootPath || '', './far.js'));
|
||||
return window.showTextDocument(uri).then((editor) => {
|
||||
const active = window.activeTextEditor;
|
||||
assert.ok(active);
|
||||
assert.ok(pathEquals(active!.document.uri.fsPath, uri.fsPath));
|
||||
});
|
||||
});
|
||||
|
||||
// test('editor, UN-active text editor', () => {
|
||||
// assert.equal(window.visibleTextEditors.length, 0);
|
||||
// assert.ok(window.activeTextEditor === undefined);
|
||||
// });
|
||||
|
||||
test('editor, assign and check view columns', () => {
|
||||
|
||||
return workspace.openTextDocument(join(workspace.rootPath || '', './far.js')).then(doc => {
|
||||
let p1 = window.showTextDocument(doc, ViewColumn.One).then(editor => {
|
||||
assert.equal(editor.viewColumn, ViewColumn.One);
|
||||
});
|
||||
let p2 = window.showTextDocument(doc, ViewColumn.Two).then(editor => {
|
||||
assert.equal(editor.viewColumn, ViewColumn.Two);
|
||||
});
|
||||
let p3 = window.showTextDocument(doc, ViewColumn.Three).then(editor => {
|
||||
assert.equal(editor.viewColumn, ViewColumn.Three);
|
||||
});
|
||||
return Promise.all([p1, p2, p3]);
|
||||
});
|
||||
});
|
||||
|
||||
test('editor, onDidChangeVisibleTextEditors', () => {
|
||||
|
||||
let eventCounter = 0;
|
||||
let reg = window.onDidChangeVisibleTextEditors(editor => {
|
||||
eventCounter += 1;
|
||||
});
|
||||
|
||||
return workspace.openTextDocument(join(workspace.rootPath || '', './far.js')).then(doc => {
|
||||
return window.showTextDocument(doc, ViewColumn.One).then(editor => {
|
||||
assert.equal(eventCounter, 1);
|
||||
return doc;
|
||||
});
|
||||
}).then(doc => {
|
||||
return window.showTextDocument(doc, ViewColumn.Two).then(editor => {
|
||||
assert.equal(eventCounter, 2);
|
||||
return doc;
|
||||
});
|
||||
}).then(doc => {
|
||||
return window.showTextDocument(doc, ViewColumn.Three).then(editor => {
|
||||
assert.equal(eventCounter, 3);
|
||||
return doc;
|
||||
});
|
||||
}).then(doc => {
|
||||
reg.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
test('editor, onDidChangeTextEditorViewColumn', () => {
|
||||
|
||||
let actualEvent: TextEditorViewColumnChangeEvent;
|
||||
|
||||
let registration1 = workspace.registerTextDocumentContentProvider('bikes', {
|
||||
provideTextDocumentContent() {
|
||||
return 'mountainbiking,roadcycling';
|
||||
}
|
||||
});
|
||||
|
||||
return Promise.all([
|
||||
workspace.openTextDocument(Uri.parse('bikes://testing/one')).then(doc => window.showTextDocument(doc, ViewColumn.One)),
|
||||
workspace.openTextDocument(Uri.parse('bikes://testing/two')).then(doc => window.showTextDocument(doc, ViewColumn.Two))
|
||||
]).then(editors => {
|
||||
|
||||
let [one, two] = editors;
|
||||
|
||||
return new Promise(resolve => {
|
||||
|
||||
let registration2 = window.onDidChangeTextEditorViewColumn(event => {
|
||||
actualEvent = event;
|
||||
registration2.dispose();
|
||||
resolve();
|
||||
});
|
||||
|
||||
// close editor 1, wait a little for the event to bubble
|
||||
one.hide();
|
||||
|
||||
}).then(() => {
|
||||
assert.ok(actualEvent);
|
||||
assert.ok(actualEvent.textEditor === two);
|
||||
assert.ok(actualEvent.viewColumn === two.viewColumn);
|
||||
|
||||
registration1.dispose();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('issue #25801 - default column when opening a file', async () => {
|
||||
const [docA, docB, docC] = await Promise.all([
|
||||
workspace.openTextDocument(await createRandomFile()),
|
||||
workspace.openTextDocument(await createRandomFile()),
|
||||
workspace.openTextDocument(await createRandomFile())
|
||||
]);
|
||||
|
||||
await window.showTextDocument(docA, ViewColumn.One);
|
||||
await window.showTextDocument(docB, ViewColumn.Two);
|
||||
|
||||
assert.ok(window.activeTextEditor);
|
||||
assert.ok(window.activeTextEditor!.document === docB);
|
||||
assert.equal(window.activeTextEditor!.viewColumn, ViewColumn.Two);
|
||||
|
||||
await window.showTextDocument(docC);
|
||||
assert.ok(window.activeTextEditor!.document === docC);
|
||||
assert.equal(window.activeTextEditor!.viewColumn, ViewColumn.One);
|
||||
});
|
||||
|
||||
test('issue #27408 - showTextDocument & vscode.diff always default to ViewColumn.One', async () => {
|
||||
const [docA, docB, docC] = await Promise.all([
|
||||
workspace.openTextDocument(await createRandomFile()),
|
||||
workspace.openTextDocument(await createRandomFile()),
|
||||
workspace.openTextDocument(await createRandomFile())
|
||||
]);
|
||||
|
||||
await window.showTextDocument(docA, ViewColumn.One);
|
||||
await window.showTextDocument(docB, ViewColumn.Two);
|
||||
|
||||
assert.ok(window.activeTextEditor);
|
||||
assert.ok(window.activeTextEditor!.document === docB);
|
||||
assert.equal(window.activeTextEditor!.viewColumn, ViewColumn.Two);
|
||||
|
||||
await window.showTextDocument(docC, ViewColumn.Active);
|
||||
|
||||
assert.ok(window.activeTextEditor!.document === docC);
|
||||
assert.equal(window.activeTextEditor!.viewColumn, ViewColumn.Two);
|
||||
});
|
||||
|
||||
test('issue #5362 - Incorrect TextEditor passed by onDidChangeTextEditorSelection', (done) => {
|
||||
const file10Path = join(workspace.rootPath || '', './10linefile.ts');
|
||||
const file30Path = join(workspace.rootPath || '', './30linefile.ts');
|
||||
|
||||
let finished = false;
|
||||
let failOncePlease = (err: Error) => {
|
||||
if (finished) {
|
||||
return;
|
||||
}
|
||||
finished = true;
|
||||
done(err);
|
||||
};
|
||||
|
||||
let passOncePlease = () => {
|
||||
if (finished) {
|
||||
return;
|
||||
}
|
||||
finished = true;
|
||||
done(null);
|
||||
};
|
||||
|
||||
let subscription = window.onDidChangeTextEditorSelection((e) => {
|
||||
let lineCount = e.textEditor.document.lineCount;
|
||||
let pos1 = e.textEditor.selections[0].active.line;
|
||||
let pos2 = e.selections[0].active.line;
|
||||
|
||||
if (pos1 !== pos2) {
|
||||
failOncePlease(new Error('received invalid selection changed event!'));
|
||||
return;
|
||||
}
|
||||
|
||||
if (pos1 >= lineCount) {
|
||||
failOncePlease(new Error(`Cursor position (${pos1}) is not valid in the document ${e.textEditor.document.fileName} that has ${lineCount} lines.`));
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
// Open 10 line file, show it in slot 1, set cursor to line 10
|
||||
// Open 30 line file, show it in slot 1, set cursor to line 30
|
||||
// Open 10 line file, show it in slot 1
|
||||
// Open 30 line file, show it in slot 1
|
||||
workspace.openTextDocument(file10Path).then((doc) => {
|
||||
return window.showTextDocument(doc, ViewColumn.One);
|
||||
}).then((editor10line) => {
|
||||
editor10line.selection = new Selection(new Position(9, 0), new Position(9, 0));
|
||||
}).then(() => {
|
||||
return workspace.openTextDocument(file30Path);
|
||||
}).then((doc) => {
|
||||
return window.showTextDocument(doc, ViewColumn.One);
|
||||
}).then((editor30line) => {
|
||||
editor30line.selection = new Selection(new Position(29, 0), new Position(29, 0));
|
||||
}).then(() => {
|
||||
return workspace.openTextDocument(file10Path);
|
||||
}).then((doc) => {
|
||||
return window.showTextDocument(doc, ViewColumn.One);
|
||||
}).then(() => {
|
||||
return workspace.openTextDocument(file30Path);
|
||||
}).then((doc) => {
|
||||
return window.showTextDocument(doc, ViewColumn.One);
|
||||
}).then(() => {
|
||||
subscription.dispose();
|
||||
}).then(passOncePlease, failOncePlease);
|
||||
});
|
||||
|
||||
test('#7013 - input without options', function () {
|
||||
const source = new CancellationTokenSource();
|
||||
let p = window.showInputBox(undefined, source.token);
|
||||
assert.ok(typeof p === 'object');
|
||||
source.dispose();
|
||||
});
|
||||
|
||||
test('showInputBox - undefined on cancel', function () {
|
||||
const source = new CancellationTokenSource();
|
||||
const p = window.showInputBox(undefined, source.token);
|
||||
source.cancel();
|
||||
return p.then(value => {
|
||||
assert.equal(value, undefined);
|
||||
});
|
||||
});
|
||||
|
||||
test('showInputBox - cancel early', function () {
|
||||
const source = new CancellationTokenSource();
|
||||
source.cancel();
|
||||
const p = window.showInputBox(undefined, source.token);
|
||||
return p.then(value => {
|
||||
assert.equal(value, undefined);
|
||||
});
|
||||
});
|
||||
|
||||
test('showInputBox - \'\' on Enter', function () {
|
||||
const p = window.showInputBox();
|
||||
return Promise.all<any>([
|
||||
commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem'),
|
||||
p.then(value => assert.equal(value, ''))
|
||||
]);
|
||||
});
|
||||
|
||||
test('showInputBox - default value on Enter', function () {
|
||||
const p = window.showInputBox({ value: 'farboo' });
|
||||
return Promise.all<any>([
|
||||
p.then(value => assert.equal(value, 'farboo')),
|
||||
commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem'),
|
||||
]);
|
||||
});
|
||||
|
||||
test('showInputBox - `undefined` on Esc', function () {
|
||||
const p = window.showInputBox();
|
||||
return Promise.all<any>([
|
||||
commands.executeCommand('workbench.action.closeQuickOpen'),
|
||||
p.then(value => assert.equal(value, undefined))
|
||||
]);
|
||||
});
|
||||
|
||||
test('showInputBox - `undefined` on Esc (despite default)', function () {
|
||||
const p = window.showInputBox({ value: 'farboo' });
|
||||
return Promise.all<any>([
|
||||
commands.executeCommand('workbench.action.closeQuickOpen'),
|
||||
p.then(value => assert.equal(value, undefined))
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
test('showQuickPick, undefined on cancel', function () {
|
||||
const source = new CancellationTokenSource();
|
||||
const p = window.showQuickPick(['eins', 'zwei', 'drei'], undefined, source.token);
|
||||
source.cancel();
|
||||
return p.then(value => {
|
||||
assert.equal(value, undefined);
|
||||
});
|
||||
});
|
||||
|
||||
test('showQuickPick, cancel early', function () {
|
||||
const source = new CancellationTokenSource();
|
||||
source.cancel();
|
||||
const p = window.showQuickPick(['eins', 'zwei', 'drei'], undefined, source.token);
|
||||
return p.then(value => {
|
||||
assert.equal(value, undefined);
|
||||
});
|
||||
});
|
||||
|
||||
test('showQuickPick, canceled by another picker', function () {
|
||||
|
||||
const result = window.showQuickPick(['eins', 'zwei', 'drei'], { ignoreFocusOut: true }).then(result => {
|
||||
assert.equal(result, undefined);
|
||||
});
|
||||
|
||||
const source = new CancellationTokenSource();
|
||||
source.cancel();
|
||||
window.showQuickPick(['eins', 'zwei', 'drei'], undefined, source.token);
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
test('showQuickPick, canceled by input', function () {
|
||||
|
||||
const result = window.showQuickPick(['eins', 'zwei', 'drei'], { ignoreFocusOut: true }).then(result => {
|
||||
assert.equal(result, undefined);
|
||||
});
|
||||
|
||||
const source = new CancellationTokenSource();
|
||||
source.cancel();
|
||||
window.showInputBox(undefined, source.token);
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
test('showQuickPick, native promise - #11754', function () {
|
||||
|
||||
const data = new Promise<string[]>(resolve => {
|
||||
resolve(['a', 'b', 'c']);
|
||||
});
|
||||
|
||||
const source = new CancellationTokenSource();
|
||||
const result = window.showQuickPick(data, undefined, source.token);
|
||||
source.cancel();
|
||||
return result.then(value => {
|
||||
assert.equal(value, undefined);
|
||||
});
|
||||
});
|
||||
|
||||
test('showQuickPick, never resolve promise and cancel - #22453', function () {
|
||||
|
||||
const result = window.showQuickPick(new Promise<string[]>(resolve => { }));
|
||||
|
||||
const a = result.then(value => {
|
||||
assert.equal(value, undefined);
|
||||
});
|
||||
const b = commands.executeCommand('workbench.action.closeQuickOpen');
|
||||
return Promise.all([a, b]);
|
||||
});
|
||||
|
||||
test('showWorkspaceFolderPick', function () {
|
||||
const p = window.showWorkspaceFolderPick(undefined);
|
||||
|
||||
return commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem').then(() => {
|
||||
return p.then(workspace => {
|
||||
assert.ok(true);
|
||||
}, error => {
|
||||
assert.ok(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('Default value for showInput Box accepted even if fails validateInput, #33691', function () {
|
||||
const result = window.showInputBox({
|
||||
validateInput: (value: string) => {
|
||||
if (!value || value.trim().length === 0) {
|
||||
return 'Cannot set empty description';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}).then(value => {
|
||||
assert.equal(value, undefined);
|
||||
});
|
||||
|
||||
const exec = commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem');
|
||||
return Promise.all([result, exec]);
|
||||
});
|
||||
|
||||
|
||||
test('editor, selection change kind', () => {
|
||||
return workspace.openTextDocument(join(workspace.rootPath || '', './far.js')).then(doc => window.showTextDocument(doc)).then(editor => {
|
||||
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
let subscription = window.onDidChangeTextEditorSelection(e => {
|
||||
assert.ok(e.textEditor === editor);
|
||||
assert.equal(e.kind, TextEditorSelectionChangeKind.Command);
|
||||
|
||||
subscription.dispose();
|
||||
resolve();
|
||||
});
|
||||
|
||||
editor.selection = new Selection(editor.selection.anchor, editor.selection.active.translate(2));
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
test('createTerminal, Terminal.name', () => {
|
||||
const terminal = window.createTerminal('foo');
|
||||
assert.equal(terminal.name, 'foo');
|
||||
|
||||
assert.throws(() => {
|
||||
(<any>terminal).name = 'bar';
|
||||
}, 'Terminal.name should be readonly');
|
||||
});
|
||||
|
||||
test('terminal, sendText immediately after createTerminal should not throw', () => {
|
||||
const terminal = window.createTerminal();
|
||||
assert.doesNotThrow(terminal.sendText.bind(terminal, 'echo "foo"'));
|
||||
});
|
||||
|
||||
test('terminal, onDidCloseTerminal event fires when terminal is disposed', (done) => {
|
||||
const terminal = window.createTerminal();
|
||||
window.onDidCloseTerminal((eventTerminal) => {
|
||||
assert.equal(terminal, eventTerminal);
|
||||
done();
|
||||
});
|
||||
terminal.dispose();
|
||||
});
|
||||
|
||||
test('terminal, processId immediately after createTerminal should fetch the pid', (done) => {
|
||||
window.createTerminal().processId.then(id => {
|
||||
assert.ok(id > 0);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
test('terminal, name should set terminal.name', () => {
|
||||
assert.equal(window.createTerminal('foo').name, 'foo');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,564 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as vscode from 'vscode';
|
||||
import { createRandomFile, deleteFile, closeAllEditors, pathEquals } from '../utils';
|
||||
import { join, basename } from 'path';
|
||||
import * as fs from 'fs';
|
||||
|
||||
suite('workspace-namespace', () => {
|
||||
|
||||
teardown(closeAllEditors);
|
||||
|
||||
test('MarkdownString', function () {
|
||||
let md = new vscode.MarkdownString();
|
||||
assert.equal(md.value, '');
|
||||
assert.equal(md.isTrusted, undefined);
|
||||
|
||||
md = new vscode.MarkdownString('**bold**');
|
||||
assert.equal(md.value, '**bold**');
|
||||
|
||||
md.appendText('**bold?**');
|
||||
assert.equal(md.value, '**bold**\\*\\*bold?\\*\\*');
|
||||
|
||||
md.appendMarkdown('**bold**');
|
||||
assert.equal(md.value, '**bold**\\*\\*bold?\\*\\***bold**');
|
||||
});
|
||||
|
||||
|
||||
test('textDocuments', () => {
|
||||
assert.ok(Array.isArray(vscode.workspace.textDocuments));
|
||||
assert.throws(() => (<any>vscode.workspace).textDocuments = null);
|
||||
});
|
||||
|
||||
test('rootPath', () => {
|
||||
if (vscode.workspace.rootPath) {
|
||||
assert.ok(pathEquals(vscode.workspace.rootPath, join(__dirname, '../../testWorkspace')));
|
||||
}
|
||||
assert.throws(() => vscode.workspace.rootPath = 'farboo');
|
||||
});
|
||||
|
||||
test('workspaceFolders', () => {
|
||||
if (vscode.workspace.workspaceFolders) {
|
||||
assert.equal(vscode.workspace.workspaceFolders.length, 1);
|
||||
assert.ok(pathEquals(vscode.workspace.workspaceFolders[0].uri.fsPath, join(__dirname, '../../testWorkspace')));
|
||||
}
|
||||
});
|
||||
|
||||
test('getWorkspaceFolder', () => {
|
||||
const folder = vscode.workspace.getWorkspaceFolder(vscode.Uri.file(join(__dirname, '../../testWorkspace/far.js')));
|
||||
assert.ok(!!folder);
|
||||
|
||||
if (folder) {
|
||||
assert.ok(pathEquals(folder.uri.fsPath, join(__dirname, '../../testWorkspace')));
|
||||
}
|
||||
});
|
||||
|
||||
test('openTextDocument', () => {
|
||||
let len = vscode.workspace.textDocuments.length;
|
||||
return vscode.workspace.openTextDocument(join(vscode.workspace.rootPath || '', './simple.txt')).then(doc => {
|
||||
assert.ok(doc);
|
||||
assert.equal(vscode.workspace.textDocuments.length, len + 1);
|
||||
});
|
||||
});
|
||||
|
||||
test('openTextDocument, illegal path', () => {
|
||||
return vscode.workspace.openTextDocument('funkydonky.txt').then(doc => {
|
||||
throw new Error('missing error');
|
||||
}, err => {
|
||||
// good!
|
||||
});
|
||||
});
|
||||
|
||||
test('openTextDocument, untitled is dirty', function () {
|
||||
return vscode.workspace.openTextDocument(vscode.Uri.parse('untitled:' + join(vscode.workspace.rootPath || '', './newfile.txt'))).then(doc => {
|
||||
assert.equal(doc.uri.scheme, 'untitled');
|
||||
assert.ok(doc.isDirty);
|
||||
});
|
||||
});
|
||||
|
||||
test('openTextDocument, untitled with host', function () {
|
||||
const uri = vscode.Uri.parse('untitled://localhost/c%24/Users/jrieken/code/samples/foobar.txt');
|
||||
return vscode.workspace.openTextDocument(uri).then(doc => {
|
||||
assert.equal(doc.uri.scheme, 'untitled');
|
||||
});
|
||||
});
|
||||
|
||||
test('openTextDocument, untitled without path', function () {
|
||||
return vscode.workspace.openTextDocument().then(doc => {
|
||||
assert.equal(doc.uri.scheme, 'untitled');
|
||||
assert.ok(doc.isDirty);
|
||||
});
|
||||
});
|
||||
|
||||
test('openTextDocument, untitled without path but language ID', function () {
|
||||
return vscode.workspace.openTextDocument({ language: 'xml' }).then(doc => {
|
||||
assert.equal(doc.uri.scheme, 'untitled');
|
||||
assert.equal(doc.languageId, 'xml');
|
||||
assert.ok(doc.isDirty);
|
||||
});
|
||||
});
|
||||
|
||||
test('openTextDocument, untitled without path but language ID and content', function () {
|
||||
return vscode.workspace.openTextDocument({ language: 'html', content: '<h1>Hello world!</h1>' }).then(doc => {
|
||||
assert.equal(doc.uri.scheme, 'untitled');
|
||||
assert.equal(doc.languageId, 'html');
|
||||
assert.ok(doc.isDirty);
|
||||
assert.equal(doc.getText(), '<h1>Hello world!</h1>');
|
||||
});
|
||||
});
|
||||
|
||||
test('openTextDocument, untitled closes on save', function () {
|
||||
const path = join(vscode.workspace.rootPath || '', './newfile.txt');
|
||||
|
||||
return vscode.workspace.openTextDocument(vscode.Uri.parse('untitled:' + path)).then(doc => {
|
||||
assert.equal(doc.uri.scheme, 'untitled');
|
||||
assert.ok(doc.isDirty);
|
||||
|
||||
let closed: vscode.TextDocument;
|
||||
let d0 = vscode.workspace.onDidCloseTextDocument(e => closed = e);
|
||||
|
||||
return vscode.window.showTextDocument(doc).then(() => {
|
||||
return doc.save().then(() => {
|
||||
assert.ok(closed === doc);
|
||||
assert.ok(!doc.isDirty);
|
||||
assert.ok(fs.existsSync(path));
|
||||
|
||||
d0.dispose();
|
||||
|
||||
return deleteFile(vscode.Uri.file(join(vscode.workspace.rootPath || '', './newfile.txt')));
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
test('openTextDocument, uri scheme/auth/path', function () {
|
||||
|
||||
let registration = vscode.workspace.registerTextDocumentContentProvider('sc', {
|
||||
provideTextDocumentContent() {
|
||||
return 'SC';
|
||||
}
|
||||
});
|
||||
|
||||
return Promise.all([
|
||||
vscode.workspace.openTextDocument(vscode.Uri.parse('sc://auth')).then(doc => {
|
||||
assert.equal(doc.uri.authority, 'auth');
|
||||
assert.equal(doc.uri.path, '');
|
||||
}),
|
||||
vscode.workspace.openTextDocument(vscode.Uri.parse('sc:///path')).then(doc => {
|
||||
assert.equal(doc.uri.authority, '');
|
||||
assert.equal(doc.uri.path, '/path');
|
||||
}),
|
||||
vscode.workspace.openTextDocument(vscode.Uri.parse('sc://auth/path')).then(doc => {
|
||||
assert.equal(doc.uri.authority, 'auth');
|
||||
assert.equal(doc.uri.path, '/path');
|
||||
})
|
||||
]).then(() => {
|
||||
registration.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
test('eol, read', () => {
|
||||
const a = createRandomFile('foo\nbar\nbar').then(file => {
|
||||
return vscode.workspace.openTextDocument(file).then(doc => {
|
||||
assert.equal(doc.eol, vscode.EndOfLine.LF);
|
||||
});
|
||||
});
|
||||
const b = createRandomFile('foo\nbar\nbar\r\nbaz').then(file => {
|
||||
return vscode.workspace.openTextDocument(file).then(doc => {
|
||||
assert.equal(doc.eol, vscode.EndOfLine.LF);
|
||||
});
|
||||
});
|
||||
const c = createRandomFile('foo\r\nbar\r\nbar').then(file => {
|
||||
return vscode.workspace.openTextDocument(file).then(doc => {
|
||||
assert.equal(doc.eol, vscode.EndOfLine.CRLF);
|
||||
});
|
||||
});
|
||||
return Promise.all([a, b, c]);
|
||||
});
|
||||
|
||||
test('eol, change via editor', () => {
|
||||
return createRandomFile('foo\nbar\nbar').then(file => {
|
||||
return vscode.workspace.openTextDocument(file).then(doc => {
|
||||
assert.equal(doc.eol, vscode.EndOfLine.LF);
|
||||
return vscode.window.showTextDocument(doc).then(editor => {
|
||||
return editor.edit(builder => builder.setEndOfLine(vscode.EndOfLine.CRLF));
|
||||
|
||||
}).then(value => {
|
||||
assert.ok(value);
|
||||
assert.ok(doc.isDirty);
|
||||
assert.equal(doc.eol, vscode.EndOfLine.CRLF);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('eol, change via applyEdit', () => {
|
||||
return createRandomFile('foo\nbar\nbar').then(file => {
|
||||
return vscode.workspace.openTextDocument(file).then(doc => {
|
||||
assert.equal(doc.eol, vscode.EndOfLine.LF);
|
||||
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.set(file, [vscode.TextEdit.setEndOfLine(vscode.EndOfLine.CRLF)]);
|
||||
return vscode.workspace.applyEdit(edit).then(value => {
|
||||
assert.ok(value);
|
||||
assert.ok(doc.isDirty);
|
||||
assert.equal(doc.eol, vscode.EndOfLine.CRLF);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('eol, change via onWillSave', () => {
|
||||
|
||||
let called = false;
|
||||
let sub = vscode.workspace.onWillSaveTextDocument(e => {
|
||||
called = true;
|
||||
e.waitUntil(Promise.resolve([vscode.TextEdit.setEndOfLine(vscode.EndOfLine.LF)]));
|
||||
});
|
||||
|
||||
return createRandomFile('foo\r\nbar\r\nbar').then(file => {
|
||||
return vscode.workspace.openTextDocument(file).then(doc => {
|
||||
assert.equal(doc.eol, vscode.EndOfLine.CRLF);
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.set(file, [vscode.TextEdit.insert(new vscode.Position(0, 0), '-changes-')]);
|
||||
|
||||
return vscode.workspace.applyEdit(edit).then(success => {
|
||||
assert.ok(success);
|
||||
return doc.save();
|
||||
|
||||
}).then(success => {
|
||||
assert.ok(success);
|
||||
assert.ok(called);
|
||||
assert.ok(!doc.isDirty);
|
||||
assert.equal(doc.eol, vscode.EndOfLine.LF);
|
||||
sub.dispose();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('events: onDidOpenTextDocument, onDidChangeTextDocument, onDidSaveTextDocument', () => {
|
||||
return createRandomFile().then(file => {
|
||||
let disposables: vscode.Disposable[] = [];
|
||||
|
||||
let onDidOpenTextDocument = false;
|
||||
disposables.push(vscode.workspace.onDidOpenTextDocument(e => {
|
||||
assert.ok(pathEquals(e.uri.fsPath, file.fsPath));
|
||||
onDidOpenTextDocument = true;
|
||||
}));
|
||||
|
||||
let onDidChangeTextDocument = false;
|
||||
disposables.push(vscode.workspace.onDidChangeTextDocument(e => {
|
||||
assert.ok(pathEquals(e.document.uri.fsPath, file.fsPath));
|
||||
onDidChangeTextDocument = true;
|
||||
}));
|
||||
|
||||
let onDidSaveTextDocument = false;
|
||||
disposables.push(vscode.workspace.onDidSaveTextDocument(e => {
|
||||
assert.ok(pathEquals(e.uri.fsPath, file.fsPath));
|
||||
onDidSaveTextDocument = true;
|
||||
}));
|
||||
|
||||
return vscode.workspace.openTextDocument(file).then(doc => {
|
||||
return vscode.window.showTextDocument(doc).then((editor) => {
|
||||
return editor.edit((builder) => {
|
||||
builder.insert(new vscode.Position(0, 0), 'Hello World');
|
||||
}).then(applied => {
|
||||
return doc.save().then(saved => {
|
||||
assert.ok(onDidOpenTextDocument);
|
||||
assert.ok(onDidChangeTextDocument);
|
||||
assert.ok(onDidSaveTextDocument);
|
||||
|
||||
while (disposables.length) {
|
||||
const item = disposables.pop();
|
||||
if (item) {
|
||||
item.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
return deleteFile(file);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('openTextDocument, with selection', function () {
|
||||
return createRandomFile('foo\nbar\nbar').then(file => {
|
||||
return vscode.workspace.openTextDocument(file).then(doc => {
|
||||
return vscode.window.showTextDocument(doc, { selection: new vscode.Range(new vscode.Position(1, 1), new vscode.Position(1, 2)) }).then(editor => {
|
||||
assert.equal(editor.selection.start.line, 1);
|
||||
assert.equal(editor.selection.start.character, 1);
|
||||
assert.equal(editor.selection.end.line, 1);
|
||||
assert.equal(editor.selection.end.character, 2);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('registerTextDocumentContentProvider, simple', function () {
|
||||
|
||||
let registration = vscode.workspace.registerTextDocumentContentProvider('foo', {
|
||||
provideTextDocumentContent(uri) {
|
||||
return uri.toString();
|
||||
}
|
||||
});
|
||||
|
||||
const uri = vscode.Uri.parse('foo://testing/virtual.js');
|
||||
return vscode.workspace.openTextDocument(uri).then(doc => {
|
||||
assert.equal(doc.getText(), uri.toString());
|
||||
assert.equal(doc.isDirty, false);
|
||||
assert.equal(doc.uri.toString(), uri.toString());
|
||||
registration.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
test('registerTextDocumentContentProvider, constrains', function () {
|
||||
|
||||
// built-in
|
||||
assert.throws(function () {
|
||||
vscode.workspace.registerTextDocumentContentProvider('untitled', { provideTextDocumentContent() { return null; } });
|
||||
});
|
||||
// built-in
|
||||
assert.throws(function () {
|
||||
vscode.workspace.registerTextDocumentContentProvider('file', { provideTextDocumentContent() { return null; } });
|
||||
});
|
||||
|
||||
// missing scheme
|
||||
return vscode.workspace.openTextDocument(vscode.Uri.parse('notThere://foo/far/boo/bar')).then(() => {
|
||||
assert.ok(false, 'expected failure');
|
||||
}, err => {
|
||||
// expected
|
||||
});
|
||||
});
|
||||
|
||||
test('registerTextDocumentContentProvider, multiple', function () {
|
||||
|
||||
// duplicate registration
|
||||
let registration1 = vscode.workspace.registerTextDocumentContentProvider('foo', {
|
||||
provideTextDocumentContent(uri) {
|
||||
if (uri.authority === 'foo') {
|
||||
return '1';
|
||||
}
|
||||
}
|
||||
});
|
||||
let registration2 = vscode.workspace.registerTextDocumentContentProvider('foo', {
|
||||
provideTextDocumentContent(uri) {
|
||||
if (uri.authority === 'bar') {
|
||||
return '2';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return Promise.all([
|
||||
vscode.workspace.openTextDocument(vscode.Uri.parse('foo://foo/bla')).then(doc => { assert.equal(doc.getText(), '1'); }),
|
||||
vscode.workspace.openTextDocument(vscode.Uri.parse('foo://bar/bla')).then(doc => { assert.equal(doc.getText(), '2'); })
|
||||
]).then(() => {
|
||||
registration1.dispose();
|
||||
registration2.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
test('registerTextDocumentContentProvider, evil provider', function () {
|
||||
|
||||
// duplicate registration
|
||||
let registration1 = vscode.workspace.registerTextDocumentContentProvider('foo', {
|
||||
provideTextDocumentContent(uri) {
|
||||
return '1';
|
||||
}
|
||||
});
|
||||
let registration2 = vscode.workspace.registerTextDocumentContentProvider('foo', {
|
||||
provideTextDocumentContent(uri): string {
|
||||
throw new Error('fail');
|
||||
}
|
||||
});
|
||||
|
||||
return vscode.workspace.openTextDocument(vscode.Uri.parse('foo://foo/bla')).then(doc => {
|
||||
assert.equal(doc.getText(), '1');
|
||||
registration1.dispose();
|
||||
registration2.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
test('registerTextDocumentContentProvider, invalid text', function () {
|
||||
|
||||
let registration = vscode.workspace.registerTextDocumentContentProvider('foo', {
|
||||
provideTextDocumentContent(uri) {
|
||||
return <any>123;
|
||||
}
|
||||
});
|
||||
return vscode.workspace.openTextDocument(vscode.Uri.parse('foo://auth/path')).then(() => {
|
||||
assert.ok(false, 'expected failure');
|
||||
}, err => {
|
||||
// expected
|
||||
registration.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
test('registerTextDocumentContentProvider, show virtual document', function () {
|
||||
|
||||
let registration = vscode.workspace.registerTextDocumentContentProvider('foo', {
|
||||
provideTextDocumentContent(uri) {
|
||||
return 'I am virtual';
|
||||
}
|
||||
});
|
||||
|
||||
return vscode.workspace.openTextDocument(vscode.Uri.parse('foo://something/path')).then(doc => {
|
||||
return vscode.window.showTextDocument(doc).then(editor => {
|
||||
|
||||
assert.ok(editor.document === doc);
|
||||
assert.equal(editor.document.getText(), 'I am virtual');
|
||||
registration.dispose();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('registerTextDocumentContentProvider, open/open document', function () {
|
||||
|
||||
let callCount = 0;
|
||||
let registration = vscode.workspace.registerTextDocumentContentProvider('foo', {
|
||||
provideTextDocumentContent(uri) {
|
||||
callCount += 1;
|
||||
return 'I am virtual';
|
||||
}
|
||||
});
|
||||
|
||||
const uri = vscode.Uri.parse('foo://testing/path');
|
||||
|
||||
return Promise.all([vscode.workspace.openTextDocument(uri), vscode.workspace.openTextDocument(uri)]).then(docs => {
|
||||
let [first, second] = docs;
|
||||
assert.ok(first === second);
|
||||
assert.ok(vscode.workspace.textDocuments.some(doc => doc.uri.toString() === uri.toString()));
|
||||
assert.equal(callCount, 1);
|
||||
registration.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
test('registerTextDocumentContentProvider, empty doc', function () {
|
||||
|
||||
let registration = vscode.workspace.registerTextDocumentContentProvider('foo', {
|
||||
provideTextDocumentContent(uri) {
|
||||
return '';
|
||||
}
|
||||
});
|
||||
|
||||
const uri = vscode.Uri.parse('foo:doc/empty');
|
||||
|
||||
return vscode.workspace.openTextDocument(uri).then(doc => {
|
||||
assert.equal(doc.getText(), '');
|
||||
assert.equal(doc.uri.toString(), uri.toString());
|
||||
registration.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
test('registerTextDocumentContentProvider, change event', function () {
|
||||
|
||||
let callCount = 0;
|
||||
let emitter = new vscode.EventEmitter<vscode.Uri>();
|
||||
|
||||
let registration = vscode.workspace.registerTextDocumentContentProvider('foo', {
|
||||
onDidChange: emitter.event,
|
||||
provideTextDocumentContent(uri) {
|
||||
return 'call' + (callCount++);
|
||||
}
|
||||
});
|
||||
|
||||
const uri = vscode.Uri.parse('foo://testing/path3');
|
||||
|
||||
return vscode.workspace.openTextDocument(uri).then(doc => {
|
||||
|
||||
assert.equal(callCount, 1);
|
||||
assert.equal(doc.getText(), 'call0');
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
let subscription = vscode.workspace.onDidChangeTextDocument(event => {
|
||||
subscription.dispose();
|
||||
assert.ok(event.document === doc);
|
||||
assert.equal(event.document.getText(), 'call1');
|
||||
resolve();
|
||||
});
|
||||
|
||||
emitter.fire(doc.uri);
|
||||
|
||||
registration.dispose();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test('findFiles', () => {
|
||||
return vscode.workspace.findFiles('*.js').then((res) => {
|
||||
assert.equal(res.length, 1);
|
||||
assert.equal(basename(vscode.workspace.asRelativePath(res[0])), 'far.js');
|
||||
});
|
||||
});
|
||||
|
||||
// TODO@Joh this test fails randomly
|
||||
// test('findFiles, cancellation', () => {
|
||||
|
||||
// const source = new CancellationTokenSource();
|
||||
// const token = source.token; // just to get an instance first
|
||||
// source.cancel();
|
||||
|
||||
// return vscode.workspace.findFiles('*.js', null, 100, token).then((res) => {
|
||||
// assert.equal(res, void 0);
|
||||
// });
|
||||
// });
|
||||
|
||||
test('applyEdit', () => {
|
||||
|
||||
return vscode.workspace.openTextDocument(vscode.Uri.parse('untitled:' + join(vscode.workspace.rootPath || '', './new2.txt'))).then(doc => {
|
||||
let edit = new vscode.WorkspaceEdit();
|
||||
edit.insert(doc.uri, new vscode.Position(0, 0), new Array(1000).join('Hello World'));
|
||||
return vscode.workspace.applyEdit(edit);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
test('applyEdit should fail when editing deleted resource', async () => {
|
||||
const resource = await createRandomFile();
|
||||
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.deleteResource(resource);
|
||||
try {
|
||||
edit.insert(resource, new vscode.Position(0, 0), '');
|
||||
assert.fail(false, 'Should disallow edit of deleted resource');
|
||||
} catch {
|
||||
// noop
|
||||
}
|
||||
});
|
||||
|
||||
test('applyEdit should fail when renaming deleted resource', async () => {
|
||||
const resource = await createRandomFile();
|
||||
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.deleteResource(resource);
|
||||
try {
|
||||
edit.renameResource(resource, resource);
|
||||
assert.fail(false, 'Should disallow rename of deleted resource');
|
||||
} catch {
|
||||
// noop
|
||||
}
|
||||
});
|
||||
|
||||
test('applyEdit should fail when editing renamed from resource', async () => {
|
||||
const resource = await createRandomFile();
|
||||
const newResource = vscode.Uri.parse(resource.fsPath + '.1');
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.renameResource(resource, newResource);
|
||||
try {
|
||||
edit.insert(resource, new vscode.Position(0, 0), '');
|
||||
assert.fail(false, 'Should disallow editing renamed file');
|
||||
} catch {
|
||||
// noop
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user