mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-23 01:58:53 +01:00
Merge remote-tracking branch 'origin/main' into pr/habibkarim/115276
This commit is contained in:
@@ -7,9 +7,12 @@ import 'mocha';
|
||||
import * as assert from 'assert';
|
||||
import { join } from 'path';
|
||||
import { commands, workspace, window, Uri, Range, Position, ViewColumn } from 'vscode';
|
||||
import { assertNoRpc } from '../utils';
|
||||
|
||||
suite('vscode API - commands', () => {
|
||||
|
||||
teardown(assertNoRpc);
|
||||
|
||||
test('getCommands', function (done) {
|
||||
|
||||
let p1 = commands.getCommands().then(commands => {
|
||||
|
||||
@@ -6,9 +6,12 @@
|
||||
import 'mocha';
|
||||
import * as assert from 'assert';
|
||||
import * as vscode from 'vscode';
|
||||
import { assertNoRpc } from '../utils';
|
||||
|
||||
suite('vscode API - configuration', () => {
|
||||
|
||||
teardown(assertNoRpc);
|
||||
|
||||
test('configurations, language defaults', function () {
|
||||
const defaultLanguageSettings = vscode.workspace.getConfiguration().get('[abcLang]');
|
||||
|
||||
|
||||
@@ -5,11 +5,13 @@
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { debug, workspace, Disposable, commands, window } from 'vscode';
|
||||
import { disposeAll } from '../utils';
|
||||
import { assertNoRpc, disposeAll } from '../utils';
|
||||
import { basename } from 'path';
|
||||
|
||||
suite('vscode API - debug', function () {
|
||||
|
||||
teardown(assertNoRpc);
|
||||
|
||||
test('breakpoints', async function () {
|
||||
assert.equal(debug.breakpoints.length, 0);
|
||||
let onDidChangeBreakpointsCounter = 0;
|
||||
|
||||
@@ -5,11 +5,14 @@
|
||||
|
||||
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';
|
||||
import { createRandomFile, deleteFile, closeAllEditors, assertNoRpc } from '../utils';
|
||||
|
||||
suite('vscode API - editors', () => {
|
||||
|
||||
teardown(closeAllEditors);
|
||||
teardown(async function () {
|
||||
assertNoRpc();
|
||||
await closeAllEditors();
|
||||
});
|
||||
|
||||
function withRandomFileEditor(initialContents: string, run: (editor: TextEditor, doc: TextDocument) => Thenable<void>): Thenable<boolean> {
|
||||
return createRandomFile(initialContents).then(file => {
|
||||
|
||||
@@ -5,9 +5,12 @@
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { env, extensions, ExtensionKind, UIKind, Uri } from 'vscode';
|
||||
import { assertNoRpc } from '../utils';
|
||||
|
||||
suite('vscode API - env', () => {
|
||||
|
||||
teardown(assertNoRpc);
|
||||
|
||||
test('env is set', function () {
|
||||
assert.equal(typeof env.language, 'string');
|
||||
assert.equal(typeof env.appRoot, 'string');
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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('vscode server cli', () => {
|
||||
|
||||
|
||||
test('extension is installed and enabled when installed by server cli', function () {
|
||||
const extension = process.env.TESTRESOLVER_INSTALL_BUILTIN_EXTENSION;
|
||||
if (!process.env.BUILD_SOURCEVERSION // Skip it when running out of sources
|
||||
|| !process.env.REMOTE_VSCODE // Skip it when not a remote integration test
|
||||
|| !extension // Skip it when extension is not provided to server
|
||||
) {
|
||||
this.skip();
|
||||
}
|
||||
|
||||
assert.ok(vscode.extensions.getExtension(extension!));
|
||||
});
|
||||
|
||||
});
|
||||
@@ -8,7 +8,7 @@ const testRunner = require('../../../../test/integration/electron/testrunner');
|
||||
|
||||
const options: any = {
|
||||
ui: 'tdd',
|
||||
useColors: (!process.env.BUILD_ARTIFACTSTAGINGDIRECTORY && process.platform !== 'win32'),
|
||||
color: (!process.env.BUILD_ARTIFACTSTAGINGDIRECTORY && process.platform !== 'win32'),
|
||||
timeout: 60000
|
||||
};
|
||||
|
||||
|
||||
@@ -6,10 +6,12 @@
|
||||
import * as assert from 'assert';
|
||||
import { join } from 'path';
|
||||
import * as vscode from 'vscode';
|
||||
import { createRandomFile, testFs } from '../utils';
|
||||
import { assertNoRpc, createRandomFile, testFs } from '../utils';
|
||||
|
||||
suite('vscode API - languages', () => {
|
||||
|
||||
teardown(assertNoRpc);
|
||||
|
||||
const isWindows = process.platform === 'win32';
|
||||
|
||||
function positionToString(p: vscode.Position) {
|
||||
|
||||
@@ -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.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as vscode from 'vscode';
|
||||
import * as utils from '../utils';
|
||||
|
||||
suite('Notebook Document', function () {
|
||||
|
||||
const simpleContentProvider = new class implements vscode.NotebookSerializer {
|
||||
dataToNotebook(_data: Uint8Array): vscode.NotebookData | Thenable<vscode.NotebookData> {
|
||||
return new vscode.NotebookData(
|
||||
[new vscode.NotebookCellData(vscode.NotebookCellKind.Code, '// SIMPLE', 'javascript')],
|
||||
new vscode.NotebookDocumentMetadata()
|
||||
);
|
||||
}
|
||||
notebookToData(_data: vscode.NotebookData): Uint8Array | Thenable<Uint8Array> {
|
||||
return new Uint8Array();
|
||||
}
|
||||
};
|
||||
|
||||
const complexContentProvider = new class implements vscode.NotebookContentProvider {
|
||||
async openNotebook(uri: vscode.Uri, _openContext: vscode.NotebookDocumentOpenContext): Promise<vscode.NotebookData> {
|
||||
return new vscode.NotebookData(
|
||||
[new vscode.NotebookCellData(vscode.NotebookCellKind.Code, uri.toString(), 'javascript')],
|
||||
new vscode.NotebookDocumentMetadata()
|
||||
);
|
||||
}
|
||||
async saveNotebook(_document: vscode.NotebookDocument, _cancellation: vscode.CancellationToken) {
|
||||
//
|
||||
}
|
||||
async saveNotebookAs(_targetResource: vscode.Uri, _document: vscode.NotebookDocument, _cancellation: vscode.CancellationToken) {
|
||||
//
|
||||
}
|
||||
async backupNotebook(_document: vscode.NotebookDocument, _context: vscode.NotebookDocumentBackupContext, _cancellation: vscode.CancellationToken) {
|
||||
return { id: '', delete() { } };
|
||||
}
|
||||
};
|
||||
|
||||
const disposables: vscode.Disposable[] = [];
|
||||
|
||||
suiteTeardown(async function () {
|
||||
utils.assertNoRpc();
|
||||
await utils.revertAllDirty();
|
||||
await utils.closeAllEditors();
|
||||
utils.disposeAll(disposables);
|
||||
disposables.length = 0;
|
||||
|
||||
for (let doc of vscode.notebook.notebookDocuments) {
|
||||
assert.strictEqual(doc.isDirty, false, doc.uri.toString());
|
||||
}
|
||||
});
|
||||
|
||||
suiteSetup(function () {
|
||||
disposables.push(vscode.notebook.registerNotebookContentProvider('notebook.nbdtest', complexContentProvider));
|
||||
disposables.push(vscode.notebook.registerNotebookSerializer('notebook.nbdserializer', simpleContentProvider));
|
||||
});
|
||||
|
||||
test('cannot register sample provider multiple times', function () {
|
||||
assert.throws(() => {
|
||||
vscode.notebook.registerNotebookContentProvider('notebook.nbdtest', complexContentProvider);
|
||||
});
|
||||
// assert.throws(() => {
|
||||
// vscode.notebook.registerNotebookSerializer('notebook.nbdserializer', simpleContentProvider);
|
||||
// });
|
||||
});
|
||||
|
||||
test('cannot open unknown types', async function () {
|
||||
try {
|
||||
await vscode.notebook.openNotebookDocument(vscode.Uri.parse('some:///thing.notTypeKnown'));
|
||||
assert.ok(false);
|
||||
} catch {
|
||||
assert.ok(true);
|
||||
}
|
||||
});
|
||||
|
||||
test('document basics', async function () {
|
||||
const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
const notebook = await vscode.notebook.openNotebookDocument(uri);
|
||||
|
||||
assert.strictEqual(notebook.uri.toString(), uri.toString());
|
||||
assert.strictEqual(notebook.isDirty, false);
|
||||
assert.strictEqual(notebook.isUntitled, false);
|
||||
assert.strictEqual(notebook.cells.length, 1);
|
||||
|
||||
assert.strictEqual(notebook.viewType, 'notebook.nbdtest');
|
||||
});
|
||||
|
||||
test('notebook open/close, notebook ready when cell-document open event is fired', async function () {
|
||||
const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
let didHappen = false;
|
||||
const p = utils.asPromise(vscode.workspace.onDidOpenTextDocument).then(doc => {
|
||||
if (doc.uri.scheme !== 'vscode-notebook-cell') {
|
||||
return;
|
||||
}
|
||||
const notebook = vscode.notebook.notebookDocuments.find(notebook => {
|
||||
const cell = notebook.cells.find(cell => cell.document === doc);
|
||||
return Boolean(cell);
|
||||
});
|
||||
assert.ok(notebook, `notebook for cell ${doc.uri} NOT found`);
|
||||
didHappen = true;
|
||||
});
|
||||
|
||||
await vscode.notebook.openNotebookDocument(uri);
|
||||
await p;
|
||||
assert.strictEqual(didHappen, true);
|
||||
});
|
||||
|
||||
test('notebook open/close, all cell-documents are ready', async function () {
|
||||
const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
|
||||
const p = utils.asPromise(vscode.notebook.onDidOpenNotebookDocument).then(notebook => {
|
||||
for (let cell of notebook.cells) {
|
||||
const doc = vscode.workspace.textDocuments.find(doc => doc.uri.toString() === cell.document.uri.toString());
|
||||
assert.ok(doc);
|
||||
assert.strictEqual(doc.notebook === notebook, true);
|
||||
assert.strictEqual(doc === cell.document, true);
|
||||
assert.strictEqual(doc?.languageId, cell.document.languageId);
|
||||
assert.strictEqual(doc?.isDirty, false);
|
||||
assert.strictEqual(doc?.isClosed, false);
|
||||
}
|
||||
});
|
||||
|
||||
await vscode.notebook.openNotebookDocument(uri);
|
||||
await p;
|
||||
});
|
||||
|
||||
|
||||
test('workspace edit API (replaceCells)', async function () {
|
||||
const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
|
||||
const document = await vscode.notebook.openNotebookDocument(uri);
|
||||
assert.strictEqual(document.cells.length, 1);
|
||||
|
||||
// inserting two new cells
|
||||
{
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCells(document.uri, 0, 0, [{
|
||||
kind: vscode.NotebookCellKind.Markdown,
|
||||
language: 'markdown',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
source: 'new_markdown'
|
||||
}, {
|
||||
kind: vscode.NotebookCellKind.Code,
|
||||
language: 'fooLang',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
source: 'new_code'
|
||||
}]);
|
||||
|
||||
const success = await vscode.workspace.applyEdit(edit);
|
||||
assert.strictEqual(success, true);
|
||||
}
|
||||
|
||||
assert.strictEqual(document.cells.length, 3);
|
||||
assert.strictEqual(document.cells[0].document.getText(), 'new_markdown');
|
||||
assert.strictEqual(document.cells[1].document.getText(), 'new_code');
|
||||
|
||||
// deleting cell 1 and 3
|
||||
{
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCells(document.uri, 0, 1, []);
|
||||
edit.replaceNotebookCells(document.uri, 2, 3, []);
|
||||
const success = await vscode.workspace.applyEdit(edit);
|
||||
assert.strictEqual(success, true);
|
||||
}
|
||||
|
||||
assert.strictEqual(document.cells.length, 1);
|
||||
assert.strictEqual(document.cells[0].document.getText(), 'new_code');
|
||||
|
||||
// replacing all cells
|
||||
{
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCells(document.uri, 0, 1, [{
|
||||
kind: vscode.NotebookCellKind.Markdown,
|
||||
language: 'markdown',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
source: 'new2_markdown'
|
||||
}, {
|
||||
kind: vscode.NotebookCellKind.Code,
|
||||
language: 'fooLang',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
source: 'new2_code'
|
||||
}]);
|
||||
const success = await vscode.workspace.applyEdit(edit);
|
||||
assert.strictEqual(success, true);
|
||||
}
|
||||
assert.strictEqual(document.cells.length, 2);
|
||||
assert.strictEqual(document.cells[0].document.getText(), 'new2_markdown');
|
||||
assert.strictEqual(document.cells[1].document.getText(), 'new2_code');
|
||||
|
||||
// remove all cells
|
||||
{
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCells(document.uri, 0, document.cells.length, []);
|
||||
const success = await vscode.workspace.applyEdit(edit);
|
||||
assert.strictEqual(success, true);
|
||||
}
|
||||
assert.strictEqual(document.cells.length, 0);
|
||||
});
|
||||
|
||||
test('workspace edit API (replaceCells, event)', async function () {
|
||||
const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
const document = await vscode.notebook.openNotebookDocument(uri);
|
||||
assert.strictEqual(document.cells.length, 1);
|
||||
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCells(document.uri, 0, 0, [{
|
||||
kind: vscode.NotebookCellKind.Markdown,
|
||||
language: 'markdown',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
source: 'new_markdown'
|
||||
}, {
|
||||
kind: vscode.NotebookCellKind.Code,
|
||||
language: 'fooLang',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
source: 'new_code'
|
||||
}]);
|
||||
|
||||
const event = utils.asPromise<vscode.NotebookCellsChangeEvent>(vscode.notebook.onDidChangeNotebookCells);
|
||||
|
||||
const success = await vscode.workspace.applyEdit(edit);
|
||||
assert.strictEqual(success, true);
|
||||
|
||||
const data = await event;
|
||||
|
||||
// check document
|
||||
assert.strictEqual(document.cells.length, 3);
|
||||
assert.strictEqual(document.cells[0].document.getText(), 'new_markdown');
|
||||
assert.strictEqual(document.cells[1].document.getText(), 'new_code');
|
||||
|
||||
// check event data
|
||||
assert.strictEqual(data.document === document, true);
|
||||
assert.strictEqual(data.changes.length, 1);
|
||||
assert.strictEqual(data.changes[0].deletedCount, 0);
|
||||
assert.strictEqual(data.changes[0].deletedItems.length, 0);
|
||||
assert.strictEqual(data.changes[0].items.length, 2);
|
||||
assert.strictEqual(data.changes[0].items[0], document.cells[0]);
|
||||
assert.strictEqual(data.changes[0].items[1], document.cells[1]);
|
||||
});
|
||||
|
||||
test('workspace edit API (appendNotebookCellOutput, replaceCellOutput, event)', async function () {
|
||||
const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
const document = await vscode.notebook.openNotebookDocument(uri);
|
||||
|
||||
const outputChangeEvent = utils.asPromise<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs);
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
const firstCellOutput = new vscode.NotebookCellOutput([new vscode.NotebookCellOutputItem('foo', 'bar')]);
|
||||
edit.appendNotebookCellOutput(document.uri, 0, [firstCellOutput]);
|
||||
const success = await vscode.workspace.applyEdit(edit);
|
||||
const data = await outputChangeEvent;
|
||||
|
||||
assert.strictEqual(success, true);
|
||||
assert.strictEqual(document.cells.length, 1);
|
||||
assert.strictEqual(document.cells[0].outputs.length, 1);
|
||||
assert.deepStrictEqual(document.cells[0].outputs, [firstCellOutput]);
|
||||
|
||||
assert.strictEqual(data.document === document, true);
|
||||
assert.strictEqual(data.cells.length, 1);
|
||||
assert.strictEqual(data.cells[0].outputs.length, 1);
|
||||
assert.deepStrictEqual(data.cells[0].outputs, [firstCellOutput]);
|
||||
|
||||
|
||||
{
|
||||
const outputChangeEvent = utils.asPromise<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs);
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
const secondCellOutput = new vscode.NotebookCellOutput([new vscode.NotebookCellOutputItem('foo', 'baz')]);
|
||||
edit.appendNotebookCellOutput(document.uri, 0, [secondCellOutput]);
|
||||
const success = await vscode.workspace.applyEdit(edit);
|
||||
const data = await outputChangeEvent;
|
||||
|
||||
assert.strictEqual(success, true);
|
||||
assert.strictEqual(document.cells.length, 1);
|
||||
assert.strictEqual(document.cells[0].outputs.length, 2);
|
||||
assert.deepStrictEqual(document.cells[0].outputs, [firstCellOutput, secondCellOutput]);
|
||||
|
||||
assert.strictEqual(data.document === document, true);
|
||||
assert.strictEqual(data.cells.length, 1);
|
||||
assert.strictEqual(data.cells[0].outputs.length, 2);
|
||||
assert.deepStrictEqual(data.cells[0].outputs, [firstCellOutput, secondCellOutput]);
|
||||
}
|
||||
|
||||
{
|
||||
const outputChangeEvent = utils.asPromise<vscode.NotebookCellOutputsChangeEvent>(vscode.notebook.onDidChangeCellOutputs);
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
const thirdOutput = new vscode.NotebookCellOutput([new vscode.NotebookCellOutputItem('foo', 'baz1')]);
|
||||
edit.replaceNotebookCellOutput(document.uri, 0, [thirdOutput]);
|
||||
const success = await vscode.workspace.applyEdit(edit);
|
||||
const data = await outputChangeEvent;
|
||||
|
||||
assert.strictEqual(success, true);
|
||||
assert.strictEqual(document.cells.length, 1);
|
||||
assert.strictEqual(document.cells[0].outputs.length, 1);
|
||||
assert.deepStrictEqual(document.cells[0].outputs, [thirdOutput]);
|
||||
|
||||
assert.strictEqual(data.document === document, true);
|
||||
assert.strictEqual(data.cells.length, 1);
|
||||
assert.strictEqual(data.cells[0].outputs.length, 1);
|
||||
assert.deepStrictEqual(data.cells[0].outputs, [thirdOutput]);
|
||||
}
|
||||
});
|
||||
|
||||
test('document save API', async function () {
|
||||
const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
const notebook = await vscode.notebook.openNotebookDocument(uri);
|
||||
|
||||
assert.strictEqual(notebook.uri.toString(), uri.toString());
|
||||
assert.strictEqual(notebook.isDirty, false);
|
||||
assert.strictEqual(notebook.isUntitled, false);
|
||||
assert.strictEqual(notebook.cells.length, 1);
|
||||
assert.strictEqual(notebook.viewType, 'notebook.nbdtest');
|
||||
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCells(notebook.uri, 0, 0, [{
|
||||
kind: vscode.NotebookCellKind.Markdown,
|
||||
language: 'markdown',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
source: 'new_markdown'
|
||||
}, {
|
||||
kind: vscode.NotebookCellKind.Code,
|
||||
language: 'fooLang',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
source: 'new_code'
|
||||
}]);
|
||||
|
||||
const success = await vscode.workspace.applyEdit(edit);
|
||||
assert.strictEqual(success, true);
|
||||
assert.strictEqual(notebook.isDirty, true);
|
||||
|
||||
await notebook.save();
|
||||
assert.strictEqual(notebook.isDirty, false);
|
||||
});
|
||||
|
||||
|
||||
test('setTextDocumentLanguage for notebook cells', async function () {
|
||||
|
||||
const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
const notebook = await vscode.notebook.openNotebookDocument(uri);
|
||||
const first = notebook.cells[0];
|
||||
assert.strictEqual(first.document.languageId, 'javascript');
|
||||
|
||||
const pclose = utils.asPromise(vscode.workspace.onDidCloseTextDocument);
|
||||
const popen = utils.asPromise(vscode.workspace.onDidOpenTextDocument);
|
||||
|
||||
await vscode.languages.setTextDocumentLanguage(first.document, 'css');
|
||||
assert.strictEqual(first.document.languageId, 'css');
|
||||
|
||||
const closed = await pclose;
|
||||
const opened = await popen;
|
||||
|
||||
assert.strictEqual(closed.uri.toString(), first.document.uri.toString());
|
||||
assert.strictEqual(opened.uri.toString(), first.document.uri.toString());
|
||||
assert.strictEqual(opened === closed, true);
|
||||
});
|
||||
|
||||
|
||||
test('#117273, Add multiple outputs', async function () {
|
||||
|
||||
const resource = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
const document = await vscode.notebook.openNotebookDocument(resource);
|
||||
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCellOutput(document.uri, 0, [
|
||||
new vscode.NotebookCellOutput(
|
||||
[new vscode.NotebookCellOutputItem('application/x.notebook.stream', '1', { outputType: 'stream', streamName: 'stdout' })],
|
||||
{ outputType: 'stream', streamName: 'stdout' }
|
||||
)
|
||||
]);
|
||||
let success = await vscode.workspace.applyEdit(edit);
|
||||
|
||||
assert.ok(success);
|
||||
assert.strictEqual(document.cells[0].outputs.length, 1);
|
||||
assert.strictEqual(document.cells[0].outputs[0].outputs.length, 1);
|
||||
assert.deepStrictEqual(document.cells[0].outputs[0].metadata, { outputType: 'stream', streamName: 'stdout' });
|
||||
assert.deepStrictEqual(document.cells[0].outputs[0].outputs[0].metadata, { outputType: 'stream', streamName: 'stdout' });
|
||||
|
||||
const edit2 = new vscode.WorkspaceEdit();
|
||||
edit2.appendNotebookCellOutput(document.uri, 0, [
|
||||
new vscode.NotebookCellOutput(
|
||||
[new vscode.NotebookCellOutputItem('hello', '1', { outputType: 'stream', streamName: 'stderr' })],
|
||||
{ outputType: 'stream', streamName: 'stderr' }
|
||||
)
|
||||
]);
|
||||
success = await vscode.workspace.applyEdit(edit2);
|
||||
assert.ok(success);
|
||||
|
||||
assert.strictEqual(document.cells[0].outputs.length, 2);
|
||||
assert.strictEqual(document.cells[0].outputs[0].outputs.length, 1);
|
||||
assert.strictEqual(document.cells[0].outputs[1].outputs.length, 1);
|
||||
assert.deepStrictEqual(document.cells[0].outputs[0].metadata, { outputType: 'stream', streamName: 'stdout' });
|
||||
assert.deepStrictEqual(document.cells[0].outputs[0].outputs[0].metadata, { outputType: 'stream', streamName: 'stdout' });
|
||||
assert.deepStrictEqual(document.cells[0].outputs[1].metadata, { outputType: 'stream', streamName: 'stderr' });
|
||||
assert.deepStrictEqual(document.cells[0].outputs[1].outputs[0].metadata, { outputType: 'stream', streamName: 'stderr' });
|
||||
});
|
||||
|
||||
test('dirty state - complex', async function () {
|
||||
const resource = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
const document = await vscode.notebook.openNotebookDocument(resource);
|
||||
assert.strictEqual(document.isDirty, false);
|
||||
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCells(document.uri, 0, document.getCells().length, []);
|
||||
assert.ok(await vscode.workspace.applyEdit(edit));
|
||||
|
||||
assert.strictEqual(document.isDirty, true);
|
||||
|
||||
await document.save();
|
||||
assert.strictEqual(document.isDirty, false);
|
||||
});
|
||||
|
||||
test('dirty state - serializer', async function () {
|
||||
const resource = await utils.createRandomFile(undefined, undefined, '.nbdserializer');
|
||||
const document = await vscode.notebook.openNotebookDocument(resource);
|
||||
assert.strictEqual(document.isDirty, false);
|
||||
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCells(document.uri, 0, document.getCells().length, []);
|
||||
assert.ok(await vscode.workspace.applyEdit(edit));
|
||||
|
||||
assert.strictEqual(document.isDirty, true);
|
||||
|
||||
await document.save();
|
||||
assert.strictEqual(document.isDirty, false);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,87 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 * as vscode from 'vscode';
|
||||
import * as utils from '../utils';
|
||||
|
||||
suite('Notebook Editor', function () {
|
||||
|
||||
const contentProvider = new class implements vscode.NotebookContentProvider {
|
||||
async openNotebook(uri: vscode.Uri, _openContext: vscode.NotebookDocumentOpenContext): Promise<vscode.NotebookData> {
|
||||
return new vscode.NotebookData(
|
||||
[new vscode.NotebookCellData(vscode.NotebookCellKind.Code, uri.toString(), 'javascript')],
|
||||
new vscode.NotebookDocumentMetadata()
|
||||
);
|
||||
|
||||
}
|
||||
async saveNotebook(_document: vscode.NotebookDocument, _cancellation: vscode.CancellationToken) {
|
||||
//
|
||||
}
|
||||
async saveNotebookAs(_targetResource: vscode.Uri, _document: vscode.NotebookDocument, _cancellation: vscode.CancellationToken) {
|
||||
//
|
||||
}
|
||||
async backupNotebook(_document: vscode.NotebookDocument, _context: vscode.NotebookDocumentBackupContext, _cancellation: vscode.CancellationToken) {
|
||||
return { id: '', delete() { } };
|
||||
}
|
||||
};
|
||||
|
||||
const disposables: vscode.Disposable[] = [];
|
||||
|
||||
suiteTeardown(async function () {
|
||||
utils.assertNoRpc();
|
||||
await utils.revertAllDirty();
|
||||
await utils.closeAllEditors();
|
||||
utils.disposeAll(disposables);
|
||||
disposables.length = 0;
|
||||
|
||||
for (let doc of vscode.notebook.notebookDocuments) {
|
||||
assert.strictEqual(doc.isDirty, false, doc.uri.toString());
|
||||
}
|
||||
});
|
||||
|
||||
suiteSetup(function () {
|
||||
disposables.push(vscode.notebook.registerNotebookContentProvider('notebook.nbdtest', contentProvider));
|
||||
});
|
||||
|
||||
|
||||
test('showNotebookDocment', async function () {
|
||||
|
||||
const count1 = vscode.notebook.notebookDocuments.length;
|
||||
|
||||
const p = utils.asPromise(vscode.notebook.onDidOpenNotebookDocument);
|
||||
const uri = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
|
||||
const editor = await vscode.window.showNotebookDocument(uri);
|
||||
assert.strictEqual(uri.toString(), editor.document.uri.toString());
|
||||
|
||||
const event = await p;
|
||||
assert.strictEqual(event.uri.toString(), uri.toString());
|
||||
|
||||
const count2 = vscode.notebook.notebookDocuments.length;
|
||||
assert.strictEqual(count1 + 1, count2);
|
||||
|
||||
});
|
||||
|
||||
test('notebook editor has viewColumn', async function () {
|
||||
|
||||
const uri1 = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
const editor1 = await vscode.window.showNotebookDocument(uri1);
|
||||
|
||||
assert.strictEqual(editor1.viewColumn, vscode.ViewColumn.One);
|
||||
|
||||
const uri2 = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
const editor2 = await vscode.window.showNotebookDocument(uri2, { viewColumn: vscode.ViewColumn.Beside });
|
||||
assert.strictEqual(editor2.viewColumn, vscode.ViewColumn.Two);
|
||||
});
|
||||
|
||||
test.skip('Opening a notebook should fire activeNotebook event changed only once', async function () {
|
||||
const openedEditor = utils.asPromise(vscode.window.onDidChangeActiveNotebookEditor);
|
||||
const resource = await utils.createRandomFile(undefined, undefined, '.nbdtest');
|
||||
const editor = await vscode.window.showNotebookDocument(resource);
|
||||
assert.ok(await openedEditor);
|
||||
assert.strictEqual(editor.document.uri.toString(), resource.toString());
|
||||
});
|
||||
});
|
||||
1443
extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts
Normal file
1443
extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { window, commands } from 'vscode';
|
||||
import { closeAllEditors } from '../utils';
|
||||
import { assertNoRpc, closeAllEditors } from '../utils';
|
||||
|
||||
interface QuickPickExpected {
|
||||
events: string[];
|
||||
@@ -20,7 +20,10 @@ interface QuickPickExpected {
|
||||
|
||||
suite('vscode API - quick input', function () {
|
||||
|
||||
teardown(closeAllEditors);
|
||||
teardown(async function () {
|
||||
assertNoRpc();
|
||||
await closeAllEditors();
|
||||
});
|
||||
|
||||
test('createQuickPick, select second', function (_done) {
|
||||
let done = (err?: any) => {
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { assertNoRpcFromEntry, assertNoRpc, disposeAll } from '../utils';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
suite('vscode', function () {
|
||||
|
||||
const dispo: vscode.Disposable[] = [];
|
||||
|
||||
teardown(() => {
|
||||
assertNoRpc();
|
||||
disposeAll(dispo);
|
||||
});
|
||||
|
||||
test('no rpc', function () {
|
||||
assertNoRpc();
|
||||
});
|
||||
|
||||
test('no rpc, createTextEditorDecorationType(...)', function () {
|
||||
const item = vscode.window.createTextEditorDecorationType({});
|
||||
dispo.push(item);
|
||||
assertNoRpcFromEntry([item, 'TextEditorDecorationType']);
|
||||
});
|
||||
|
||||
test('no rpc, createOutputChannel(...)', function () {
|
||||
const item = vscode.window.createOutputChannel('hello');
|
||||
dispo.push(item);
|
||||
assertNoRpcFromEntry([item, 'OutputChannel']);
|
||||
});
|
||||
|
||||
test('no rpc, createDiagnosticCollection(...)', function () {
|
||||
const item = vscode.languages.createDiagnosticCollection();
|
||||
dispo.push(item);
|
||||
assertNoRpcFromEntry([item, 'DiagnosticCollection']);
|
||||
});
|
||||
|
||||
test('no rpc, createQuickPick(...)', function () {
|
||||
const item = vscode.window.createQuickPick();
|
||||
dispo.push(item);
|
||||
assertNoRpcFromEntry([item, 'QuickPick']);
|
||||
});
|
||||
|
||||
test('no rpc, createInputBox(...)', function () {
|
||||
const item = vscode.window.createInputBox();
|
||||
dispo.push(item);
|
||||
assertNoRpcFromEntry([item, 'InputBox']);
|
||||
});
|
||||
|
||||
test('no rpc, createStatusBarItem(...)', function () {
|
||||
const item = vscode.window.createStatusBarItem();
|
||||
dispo.push(item);
|
||||
assertNoRpcFromEntry([item, 'StatusBarItem']);
|
||||
});
|
||||
|
||||
test('no rpc, createSourceControl(...)', function () {
|
||||
this.skip();
|
||||
const item = vscode.scm.createSourceControl('foo', 'Hello');
|
||||
dispo.push(item);
|
||||
assertNoRpcFromEntry([item, 'SourceControl']);
|
||||
});
|
||||
|
||||
test('no rpc, createCommentController(...)', function () {
|
||||
this.skip();
|
||||
const item = vscode.comments.createCommentController('foo', 'Hello');
|
||||
dispo.push(item);
|
||||
assertNoRpcFromEntry([item, 'CommentController']);
|
||||
});
|
||||
|
||||
test('no rpc, createWebviewPanel(...)', function () {
|
||||
const item = vscode.window.createWebviewPanel('webview', 'Hello', vscode.ViewColumn.Active);
|
||||
dispo.push(item);
|
||||
assertNoRpcFromEntry([item, 'WebviewPanel']);
|
||||
});
|
||||
|
||||
test('no rpc, createTreeView(...)', function () {
|
||||
const treeDataProvider = new class implements vscode.TreeDataProvider<string> {
|
||||
getTreeItem(element: string): vscode.TreeItem | Thenable<vscode.TreeItem> {
|
||||
return new vscode.TreeItem(element);
|
||||
}
|
||||
getChildren(_element?: string): vscode.ProviderResult<string[]> {
|
||||
return ['foo', 'bar'];
|
||||
}
|
||||
};
|
||||
const item = vscode.window.createTreeView('test.treeId', { treeDataProvider });
|
||||
dispo.push(item);
|
||||
assertNoRpcFromEntry([item, 'TreeView']);
|
||||
});
|
||||
|
||||
test('no rpc, createNotebookEditorDecorationType(...)', function () {
|
||||
const item = vscode.notebook.createNotebookEditorDecorationType({ top: {} });
|
||||
dispo.push(item);
|
||||
assertNoRpcFromEntry([item, 'NotebookEditorDecorationType']);
|
||||
});
|
||||
});
|
||||
@@ -3,13 +3,13 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { window, Pseudoterminal, EventEmitter, TerminalDimensions, workspace, ConfigurationTarget, Disposable, UIKind, env, EnvironmentVariableMutatorType, EnvironmentVariableMutator, extensions, ExtensionContext, TerminalOptions, ExtensionTerminalOptions } from 'vscode';
|
||||
import { doesNotThrow, equal, ok, deepEqual, throws } from 'assert';
|
||||
import { window, Pseudoterminal, EventEmitter, TerminalDimensions, workspace, ConfigurationTarget, Disposable, UIKind, env, EnvironmentVariableMutatorType, EnvironmentVariableMutator, extensions, ExtensionContext, TerminalOptions, ExtensionTerminalOptions, Terminal } from 'vscode';
|
||||
import { doesNotThrow, equal, deepEqual, throws, strictEqual } from 'assert';
|
||||
import { assertNoRpc } from '../utils';
|
||||
|
||||
// Disable terminal tests:
|
||||
// - Web https://github.com/microsoft/vscode/issues/92826
|
||||
// - Remote https://github.com/microsoft/vscode/issues/96057
|
||||
((env.uiKind === UIKind.Web || typeof env.remoteName !== 'undefined') ? suite.skip : suite)('vscode API - terminal', () => {
|
||||
(env.uiKind === UIKind.Web ? suite.skip : suite)('vscode API - terminal', () => {
|
||||
let extensionContext: ExtensionContext;
|
||||
|
||||
suiteSetup(async () => {
|
||||
@@ -23,68 +23,65 @@ import { doesNotThrow, equal, ok, deepEqual, throws } from 'assert';
|
||||
// Disable exit alerts as tests may trigger then and we're not testing the notifications
|
||||
await config.update('showExitAlert', false, ConfigurationTarget.Global);
|
||||
// Canvas may cause problems when running in a container
|
||||
await config.update('rendererType', 'dom', ConfigurationTarget.Global);
|
||||
await config.update('gpuAcceleration', 'off', ConfigurationTarget.Global);
|
||||
// Disable env var relaunch for tests to prevent terminals relaunching themselves
|
||||
await config.update('environmentChangesRelaunch', false, ConfigurationTarget.Global);
|
||||
});
|
||||
|
||||
suite('Terminal', () => {
|
||||
let disposables: Disposable[] = [];
|
||||
|
||||
teardown(() => {
|
||||
assertNoRpc();
|
||||
disposables.forEach(d => d.dispose());
|
||||
disposables.length = 0;
|
||||
});
|
||||
|
||||
test('sendText immediately after createTerminal should not throw', (done) => {
|
||||
disposables.push(window.onDidOpenTerminal(term => {
|
||||
try {
|
||||
equal(terminal, term);
|
||||
} catch (e) {
|
||||
done(e);
|
||||
return;
|
||||
}
|
||||
terminal.dispose();
|
||||
disposables.push(window.onDidCloseTerminal(() => done()));
|
||||
}));
|
||||
test('sendText immediately after createTerminal should not throw', async () => {
|
||||
const terminal = window.createTerminal();
|
||||
const result = await new Promise<Terminal>(r => {
|
||||
disposables.push(window.onDidOpenTerminal(t => {
|
||||
if (t === terminal) {
|
||||
r(t);
|
||||
}
|
||||
}));
|
||||
});
|
||||
equal(result, terminal);
|
||||
doesNotThrow(terminal.sendText.bind(terminal, 'echo "foo"'));
|
||||
await new Promise<void>(r => {
|
||||
disposables.push(window.onDidCloseTerminal(t => {
|
||||
if (t === terminal) {
|
||||
r();
|
||||
}
|
||||
}));
|
||||
terminal.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
(process.platform === 'linux' ? test.skip : test)('echo works in the default shell', (done) => {
|
||||
disposables.push(window.onDidOpenTerminal(term => {
|
||||
try {
|
||||
equal(terminal, term);
|
||||
} catch (e) {
|
||||
done(e);
|
||||
return;
|
||||
}
|
||||
let data = '';
|
||||
const dataDisposable = window.onDidWriteTerminalData(e => {
|
||||
try {
|
||||
equal(terminal, e.terminal);
|
||||
} catch (e) {
|
||||
done(e);
|
||||
return;
|
||||
}
|
||||
data += e.data;
|
||||
if (data.indexOf(expected) !== 0) {
|
||||
dataDisposable.dispose();
|
||||
terminal.dispose();
|
||||
disposables.push(window.onDidCloseTerminal(() => {
|
||||
done();
|
||||
}));
|
||||
test('echo works in the default shell', async () => {
|
||||
const terminal = await new Promise<Terminal>(r => {
|
||||
disposables.push(window.onDidOpenTerminal(t => {
|
||||
if (t === terminal) {
|
||||
r(terminal);
|
||||
}
|
||||
}));
|
||||
// Use a single character to avoid winpty/conpty issues with injected sequences
|
||||
const terminal = window.createTerminal({
|
||||
env: { TEST: '`' }
|
||||
});
|
||||
disposables.push(dataDisposable);
|
||||
}));
|
||||
// Use a single character to avoid winpty/conpty issues with injected sequences
|
||||
const expected = '`';
|
||||
const terminal = window.createTerminal({
|
||||
env: {
|
||||
TEST: '`'
|
||||
}
|
||||
terminal.show();
|
||||
});
|
||||
terminal.show();
|
||||
doesNotThrow(() => {
|
||||
|
||||
let data = '';
|
||||
await new Promise<void>(r => {
|
||||
disposables.push(window.onDidWriteTerminalData(e => {
|
||||
if (e.terminal === terminal) {
|
||||
data += e.data;
|
||||
if (data.indexOf('`') !== 0) {
|
||||
r();
|
||||
}
|
||||
}
|
||||
}));
|
||||
// Print an environment variable value so the echo statement doesn't get matched
|
||||
if (process.platform === 'win32') {
|
||||
terminal.sendText(`$env:TEST`);
|
||||
@@ -92,126 +89,143 @@ import { doesNotThrow, equal, ok, deepEqual, throws } from 'assert';
|
||||
terminal.sendText(`echo $TEST`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('onDidCloseTerminal event fires when terminal is disposed', (done) => {
|
||||
disposables.push(window.onDidOpenTerminal(term => {
|
||||
try {
|
||||
equal(terminal, term);
|
||||
} catch (e) {
|
||||
done(e);
|
||||
return;
|
||||
}
|
||||
await new Promise<void>(r => {
|
||||
terminal.dispose();
|
||||
disposables.push(window.onDidCloseTerminal(() => done()));
|
||||
}));
|
||||
const terminal = window.createTerminal();
|
||||
disposables.push(window.onDidCloseTerminal(t => {
|
||||
strictEqual(terminal, t);
|
||||
r();
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
test('processId immediately after createTerminal should fetch the pid', (done) => {
|
||||
disposables.push(window.onDidOpenTerminal(term => {
|
||||
try {
|
||||
equal(terminal, term);
|
||||
} catch (e) {
|
||||
done(e);
|
||||
return;
|
||||
}
|
||||
terminal.processId.then(id => {
|
||||
try {
|
||||
ok(id && id > 0);
|
||||
} catch (e) {
|
||||
done(e);
|
||||
return;
|
||||
test('onDidCloseTerminal event fires when terminal is disposed', async () => {
|
||||
const terminal = window.createTerminal();
|
||||
const result = await new Promise<Terminal>(r => {
|
||||
disposables.push(window.onDidOpenTerminal(t => {
|
||||
if (t === terminal) {
|
||||
r(t);
|
||||
}
|
||||
terminal.dispose();
|
||||
disposables.push(window.onDidCloseTerminal(() => done()));
|
||||
});
|
||||
}));
|
||||
}));
|
||||
});
|
||||
equal(result, terminal);
|
||||
await new Promise<void>(r => {
|
||||
disposables.push(window.onDidCloseTerminal(t => {
|
||||
if (t === terminal) {
|
||||
r();
|
||||
}
|
||||
}));
|
||||
terminal.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
test('processId immediately after createTerminal should fetch the pid', async () => {
|
||||
const terminal = window.createTerminal();
|
||||
const result = await new Promise<Terminal>(r => {
|
||||
disposables.push(window.onDidOpenTerminal(t => {
|
||||
if (t === terminal) {
|
||||
r(t);
|
||||
}
|
||||
}));
|
||||
});
|
||||
equal(result, terminal);
|
||||
let pid = await result.processId;
|
||||
equal(true, pid && pid > 0);
|
||||
await new Promise<void>(r => {
|
||||
disposables.push(window.onDidCloseTerminal(t => {
|
||||
if (t === terminal) {
|
||||
r();
|
||||
}
|
||||
}));
|
||||
terminal.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
test('name in constructor should set terminal.name', (done) => {
|
||||
disposables.push(window.onDidOpenTerminal(term => {
|
||||
try {
|
||||
equal(terminal, term);
|
||||
} catch (e) {
|
||||
done(e);
|
||||
return;
|
||||
}
|
||||
terminal.dispose();
|
||||
disposables.push(window.onDidCloseTerminal(() => done()));
|
||||
}));
|
||||
test('name in constructor should set terminal.name', async () => {
|
||||
const terminal = window.createTerminal('a');
|
||||
try {
|
||||
equal(terminal.name, 'a');
|
||||
} catch (e) {
|
||||
done(e);
|
||||
return;
|
||||
}
|
||||
const result = await new Promise<Terminal>(r => {
|
||||
disposables.push(window.onDidOpenTerminal(t => {
|
||||
if (t === terminal) {
|
||||
r(t);
|
||||
}
|
||||
}));
|
||||
});
|
||||
equal(result, terminal);
|
||||
await new Promise<void>(r => {
|
||||
disposables.push(window.onDidCloseTerminal(t => {
|
||||
if (t === terminal) {
|
||||
r();
|
||||
}
|
||||
}));
|
||||
terminal.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
test('creationOptions should be set and readonly for TerminalOptions terminals', (done) => {
|
||||
disposables.push(window.onDidOpenTerminal(term => {
|
||||
try {
|
||||
equal(terminal, term);
|
||||
} catch (e) {
|
||||
done(e);
|
||||
return;
|
||||
}
|
||||
terminal.dispose();
|
||||
disposables.push(window.onDidCloseTerminal(() => done()));
|
||||
}));
|
||||
test('creationOptions should be set and readonly for TerminalOptions terminals', async () => {
|
||||
const options = {
|
||||
name: 'foo',
|
||||
hideFromUser: true
|
||||
};
|
||||
const terminal = window.createTerminal(options);
|
||||
try {
|
||||
equal(terminal.name, 'foo');
|
||||
const terminalOptions = terminal.creationOptions as TerminalOptions;
|
||||
equal(terminalOptions.name, 'foo');
|
||||
equal(terminalOptions.hideFromUser, true);
|
||||
throws(() => terminalOptions.name = 'bad', 'creationOptions should be readonly at runtime');
|
||||
} catch (e) {
|
||||
done(e);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
test('onDidOpenTerminal should fire when a terminal is created', (done) => {
|
||||
disposables.push(window.onDidOpenTerminal(term => {
|
||||
try {
|
||||
equal(term.name, 'b');
|
||||
} catch (e) {
|
||||
done(e);
|
||||
return;
|
||||
}
|
||||
disposables.push(window.onDidCloseTerminal(() => done()));
|
||||
terminal.dispose();
|
||||
}));
|
||||
const terminal = window.createTerminal('b');
|
||||
});
|
||||
|
||||
test('exitStatus.code should be set to undefined after a terminal is disposed', (done) => {
|
||||
disposables.push(window.onDidOpenTerminal(term => {
|
||||
try {
|
||||
equal(term, terminal);
|
||||
} catch (e) {
|
||||
done(e);
|
||||
return;
|
||||
}
|
||||
disposables.push(window.onDidCloseTerminal(t => {
|
||||
try {
|
||||
deepEqual(t.exitStatus, { code: undefined });
|
||||
} catch (e) {
|
||||
done(e);
|
||||
return;
|
||||
const terminalOptions = terminal.creationOptions as TerminalOptions;
|
||||
const result = await new Promise<Terminal>(r => {
|
||||
disposables.push(window.onDidOpenTerminal(t => {
|
||||
if (t === terminal) {
|
||||
r(t);
|
||||
}
|
||||
}));
|
||||
});
|
||||
equal(result, terminal);
|
||||
await new Promise<void>(r => {
|
||||
disposables.push(window.onDidCloseTerminal(t => {
|
||||
if (t === terminal) {
|
||||
r();
|
||||
}
|
||||
done();
|
||||
}));
|
||||
terminal.dispose();
|
||||
}));
|
||||
});
|
||||
throws(() => terminalOptions.name = 'bad', 'creationOptions should be readonly at runtime');
|
||||
});
|
||||
|
||||
test('onDidOpenTerminal should fire when a terminal is created', async () => {
|
||||
const terminal = window.createTerminal('b');
|
||||
const result = await new Promise<Terminal>(r => {
|
||||
disposables.push(window.onDidOpenTerminal(t => {
|
||||
if (t === terminal) {
|
||||
r(t);
|
||||
}
|
||||
}));
|
||||
});
|
||||
equal(result, terminal);
|
||||
await new Promise<void>(r => {
|
||||
disposables.push(window.onDidCloseTerminal(t => {
|
||||
if (t === terminal) {
|
||||
r();
|
||||
}
|
||||
}));
|
||||
terminal.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
test('exitStatus.code should be set to undefined after a terminal is disposed', async () => {
|
||||
const terminal = window.createTerminal();
|
||||
const result = await new Promise<Terminal>(r => {
|
||||
disposables.push(window.onDidOpenTerminal(t => {
|
||||
if (t === terminal) {
|
||||
r(t);
|
||||
}
|
||||
}));
|
||||
});
|
||||
equal(result, terminal);
|
||||
await new Promise<void>(r => {
|
||||
disposables.push(window.onDidCloseTerminal(t => {
|
||||
if (t === terminal) {
|
||||
deepEqual(t.exitStatus, { code: undefined });
|
||||
r();
|
||||
}
|
||||
}));
|
||||
terminal.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
// test('onDidChangeActiveTerminal should fire when new terminals are created', (done) => {
|
||||
@@ -285,23 +299,25 @@ import { doesNotThrow, equal, ok, deepEqual, throws } from 'assert';
|
||||
// });
|
||||
|
||||
suite('hideFromUser', () => {
|
||||
test('should be available to terminals API', done => {
|
||||
test('should be available to terminals API', async () => {
|
||||
const terminal = window.createTerminal({ name: 'bg', hideFromUser: true });
|
||||
disposables.push(window.onDidOpenTerminal(t => {
|
||||
try {
|
||||
equal(t, terminal);
|
||||
equal(t.name, 'bg');
|
||||
ok(window.terminals.indexOf(terminal) !== -1);
|
||||
} catch (e) {
|
||||
done(e);
|
||||
return;
|
||||
}
|
||||
disposables.push(window.onDidCloseTerminal(() => {
|
||||
// reg3.dispose();
|
||||
done();
|
||||
const result = await new Promise<Terminal>(r => {
|
||||
disposables.push(window.onDidOpenTerminal(t => {
|
||||
if (t === terminal) {
|
||||
r(t);
|
||||
}
|
||||
}));
|
||||
});
|
||||
equal(result, terminal);
|
||||
equal(true, window.terminals.indexOf(terminal) !== -1);
|
||||
await new Promise<void>(r => {
|
||||
disposables.push(window.onDidCloseTerminal(t => {
|
||||
if (t === terminal) {
|
||||
r();
|
||||
}
|
||||
}));
|
||||
terminal.dispose();
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -652,7 +668,8 @@ import { doesNotThrow, equal, ok, deepEqual, throws } from 'assert';
|
||||
});
|
||||
});
|
||||
|
||||
suite('environmentVariableCollection', () => {
|
||||
// https://github.com/microsoft/vscode/issues/119826
|
||||
suite.skip('environmentVariableCollection', () => {
|
||||
test('should have collection variables apply to terminals immediately after setting', (done) => {
|
||||
// Text to match on before passing the test
|
||||
const expectedText = [
|
||||
@@ -661,10 +678,7 @@ import { doesNotThrow, equal, ok, deepEqual, throws } from 'assert';
|
||||
'~c2~c1'
|
||||
];
|
||||
disposables.push(window.onDidWriteTerminalData(e => {
|
||||
try {
|
||||
equal(terminal, e.terminal);
|
||||
} catch (e) {
|
||||
done(e);
|
||||
if (terminal !== e.terminal) {
|
||||
return;
|
||||
}
|
||||
// Multiple expected could show up in the same data event
|
||||
@@ -707,10 +721,7 @@ import { doesNotThrow, equal, ok, deepEqual, throws } from 'assert';
|
||||
'~c2~'
|
||||
];
|
||||
disposables.push(window.onDidWriteTerminalData(e => {
|
||||
try {
|
||||
equal(terminal, e.terminal);
|
||||
} catch (e) {
|
||||
done(e);
|
||||
if (terminal !== e.terminal) {
|
||||
return;
|
||||
}
|
||||
// Multiple expected could show up in the same data event
|
||||
@@ -752,10 +763,7 @@ import { doesNotThrow, equal, ok, deepEqual, throws } from 'assert';
|
||||
'~b1~'
|
||||
];
|
||||
disposables.push(window.onDidWriteTerminalData(e => {
|
||||
try {
|
||||
equal(terminal, e.terminal);
|
||||
} catch (e) {
|
||||
done(e);
|
||||
if (terminal !== e.terminal) {
|
||||
return;
|
||||
}
|
||||
// Multiple expected could show up in the same data event
|
||||
@@ -794,10 +802,7 @@ import { doesNotThrow, equal, ok, deepEqual, throws } from 'assert';
|
||||
'~b2~'
|
||||
];
|
||||
disposables.push(window.onDidWriteTerminalData(e => {
|
||||
try {
|
||||
equal(terminal, e.terminal);
|
||||
} catch (e) {
|
||||
done(e);
|
||||
if (terminal !== e.terminal) {
|
||||
return;
|
||||
}
|
||||
// Multiple expected could show up in the same data event
|
||||
|
||||
@@ -6,9 +6,12 @@
|
||||
import 'mocha';
|
||||
import * as assert from 'assert';
|
||||
import * as vscode from 'vscode';
|
||||
import { assertNoRpc } from '../utils';
|
||||
|
||||
suite('vscode API - types', () => {
|
||||
|
||||
teardown(assertNoRpc);
|
||||
|
||||
test('static properties, es5 compat class', function () {
|
||||
assert.ok(vscode.ThemeIcon.File instanceof vscode.ThemeIcon);
|
||||
assert.ok(vscode.ThemeIcon.Folder instanceof vscode.ThemeIcon);
|
||||
|
||||
@@ -7,7 +7,7 @@ import * as assert from 'assert';
|
||||
import 'mocha';
|
||||
import * as os from 'os';
|
||||
import * as vscode from 'vscode';
|
||||
import { closeAllEditors, delay, disposeAll } from '../utils';
|
||||
import { assertNoRpc, closeAllEditors, delay, disposeAll } from '../utils';
|
||||
|
||||
const webviewId = 'myWebview';
|
||||
|
||||
@@ -26,14 +26,14 @@ suite.skip('vscode API - webview', () => {
|
||||
}
|
||||
|
||||
teardown(async () => {
|
||||
assertNoRpc();
|
||||
await closeAllEditors();
|
||||
|
||||
disposeAll(disposables);
|
||||
});
|
||||
|
||||
test('webviews should be able to send and receive messages', async () => {
|
||||
const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true }));
|
||||
const firstResponse = getMesssage(webview);
|
||||
const firstResponse = getMessage(webview);
|
||||
webview.webview.html = createHtmlDocumentWithBody(/*html*/`
|
||||
<script>
|
||||
const vscode = acquireVsCodeApi();
|
||||
@@ -49,7 +49,7 @@ suite.skip('vscode API - webview', () => {
|
||||
test('webviews should not have scripts enabled by default', async () => {
|
||||
const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, {}));
|
||||
const response = Promise.race<any>([
|
||||
getMesssage(webview),
|
||||
getMessage(webview),
|
||||
new Promise<{}>(resolve => setTimeout(() => resolve({ value: '🎉' }), 1000))
|
||||
]);
|
||||
webview.webview.html = createHtmlDocumentWithBody(/*html*/`
|
||||
@@ -65,7 +65,7 @@ suite.skip('vscode API - webview', () => {
|
||||
const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true }));
|
||||
|
||||
{
|
||||
const response = getMesssage(webview);
|
||||
const response = getMessage(webview);
|
||||
webview.webview.html = createHtmlDocumentWithBody(/*html*/`
|
||||
<script>
|
||||
const vscode = acquireVsCodeApi();
|
||||
@@ -75,7 +75,7 @@ suite.skip('vscode API - webview', () => {
|
||||
assert.strictEqual((await response).value, 'first');
|
||||
}
|
||||
{
|
||||
const response = getMesssage(webview);
|
||||
const response = getMessage(webview);
|
||||
webview.webview.html = createHtmlDocumentWithBody(/*html*/`
|
||||
<script>
|
||||
const vscode = acquireVsCodeApi();
|
||||
@@ -88,7 +88,7 @@ suite.skip('vscode API - webview', () => {
|
||||
|
||||
test.skip('webviews should preserve vscode API state when they are hidden', async () => {
|
||||
const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true }));
|
||||
const ready = getMesssage(webview);
|
||||
const ready = getMessage(webview);
|
||||
webview.webview.html = createHtmlDocumentWithBody(/*html*/`
|
||||
<script>
|
||||
const vscode = acquireVsCodeApi();
|
||||
@@ -120,7 +120,7 @@ suite.skip('vscode API - webview', () => {
|
||||
await vscode.window.showTextDocument(doc);
|
||||
|
||||
// And then back
|
||||
const ready2 = getMesssage(webview);
|
||||
const ready2 = getMessage(webview);
|
||||
webview.reveal(vscode.ViewColumn.One);
|
||||
await ready2;
|
||||
|
||||
@@ -135,7 +135,7 @@ suite.skip('vscode API - webview', () => {
|
||||
|
||||
// Open webview in same column
|
||||
const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true }));
|
||||
const ready = getMesssage(webview);
|
||||
const ready = getMessage(webview);
|
||||
webview.webview.html = statefulWebviewHtml;
|
||||
await ready;
|
||||
|
||||
@@ -152,7 +152,7 @@ suite.skip('vscode API - webview', () => {
|
||||
|
||||
test('webviews with retainContextWhenHidden should preserve their context when they are hidden', async () => {
|
||||
const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true, retainContextWhenHidden: true }));
|
||||
const ready = getMesssage(webview);
|
||||
const ready = getMessage(webview);
|
||||
|
||||
webview.webview.html = statefulWebviewHtml;
|
||||
await ready;
|
||||
@@ -174,7 +174,7 @@ suite.skip('vscode API - webview', () => {
|
||||
|
||||
test('webviews with retainContextWhenHidden should preserve their page position when hidden', async () => {
|
||||
const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true, retainContextWhenHidden: true }));
|
||||
const ready = getMesssage(webview);
|
||||
const ready = getMessage(webview);
|
||||
webview.webview.html = createHtmlDocumentWithBody(/*html*/`
|
||||
${'<h1>Header</h1>'.repeat(200)}
|
||||
<script>
|
||||
@@ -196,7 +196,7 @@ suite.skip('vscode API - webview', () => {
|
||||
</script>`);
|
||||
await ready;
|
||||
|
||||
const firstResponse = getMesssage(webview);
|
||||
const firstResponse = getMessage(webview);
|
||||
|
||||
assert.strictEqual(Math.round((await firstResponse).value), 100);
|
||||
|
||||
@@ -214,7 +214,7 @@ suite.skip('vscode API - webview', () => {
|
||||
|
||||
test('webviews with retainContextWhenHidden should be able to recive messages while hidden', async () => {
|
||||
const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true, retainContextWhenHidden: true }));
|
||||
const ready = getMesssage(webview);
|
||||
const ready = getMessage(webview);
|
||||
|
||||
webview.webview.html = statefulWebviewHtml;
|
||||
await ready;
|
||||
@@ -264,7 +264,7 @@ suite.skip('vscode API - webview', () => {
|
||||
vscode.postMessage({ type: 'ready' });
|
||||
</script>`);
|
||||
|
||||
const ready = getMesssage(webview);
|
||||
const ready = getMessage(webview);
|
||||
await ready;
|
||||
|
||||
{
|
||||
@@ -341,7 +341,7 @@ suite.skip('vscode API - webview', () => {
|
||||
img.addEventListener('error', () => { vscode.postMessage({ value: false }); });
|
||||
</script>`);
|
||||
|
||||
const firstResponse = getMesssage(webview);
|
||||
const firstResponse = getMessage(webview);
|
||||
|
||||
assert.strictEqual((await firstResponse).value, true);
|
||||
});
|
||||
@@ -365,7 +365,7 @@ suite.skip('vscode API - webview', () => {
|
||||
|
||||
assert.strictEqual((await viewStateChanged).webviewPanel.viewColumn, vscode.ViewColumn.One);
|
||||
|
||||
const firstResponse = getMesssage(webview);
|
||||
const firstResponse = getMessage(webview);
|
||||
webview.webview.html = createHtmlDocumentWithBody(/*html*/`
|
||||
<script>
|
||||
const vscode = acquireVsCodeApi();
|
||||
@@ -382,7 +382,7 @@ suite.skip('vscode API - webview', () => {
|
||||
const expectedText = `webview text from: ${Date.now()}!`;
|
||||
|
||||
const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true, retainContextWhenHidden: true }));
|
||||
const ready = getMesssage(webview);
|
||||
const ready = getMessage(webview);
|
||||
|
||||
|
||||
webview.webview.html = createHtmlDocumentWithBody(/*html*/`
|
||||
@@ -399,6 +399,118 @@ suite.skip('vscode API - webview', () => {
|
||||
assert.strictEqual(await vscode.env.clipboard.readText(), expectedText);
|
||||
});
|
||||
}
|
||||
|
||||
test('webviews should transfer ArrayBuffers to and from webviews', async () => {
|
||||
const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true, retainContextWhenHidden: true }));
|
||||
const ready = getMessage(webview);
|
||||
webview.webview.html = createHtmlDocumentWithBody(/*html*/`
|
||||
<script>
|
||||
const vscode = acquireVsCodeApi();
|
||||
|
||||
window.addEventListener('message', (message) => {
|
||||
switch (message.data.type) {
|
||||
case 'add1':
|
||||
const arrayBuffer = message.data.array;
|
||||
const uint8Array = new Uint8Array(arrayBuffer);
|
||||
|
||||
for (let i = 0; i < uint8Array.length; ++i) {
|
||||
uint8Array[i] = uint8Array[i] + 1;
|
||||
}
|
||||
|
||||
vscode.postMessage({ array: arrayBuffer }, [arrayBuffer]);
|
||||
break;
|
||||
}
|
||||
});
|
||||
vscode.postMessage({ type: 'ready' });
|
||||
</script>`);
|
||||
await ready;
|
||||
|
||||
const responsePromise = getMessage(webview);
|
||||
|
||||
const bufferLen = 100;
|
||||
|
||||
{
|
||||
const arrayBuffer = new ArrayBuffer(bufferLen);
|
||||
const uint8Array = new Uint8Array(arrayBuffer);
|
||||
for (let i = 0; i < bufferLen; ++i) {
|
||||
uint8Array[i] = i;
|
||||
}
|
||||
webview.webview.postMessage({
|
||||
type: 'add1',
|
||||
array: arrayBuffer
|
||||
});
|
||||
}
|
||||
{
|
||||
const response = await responsePromise;
|
||||
assert.ok(response.array instanceof ArrayBuffer);
|
||||
|
||||
const uint8Array = new Uint8Array(response.array);
|
||||
for (let i = 0; i < bufferLen; ++i) {
|
||||
assert.strictEqual(uint8Array[i], i + 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('webviews should transfer Typed arrays to and from webviews', async () => {
|
||||
const webview = _register(vscode.window.createWebviewPanel(webviewId, 'title', { viewColumn: vscode.ViewColumn.One }, { enableScripts: true, retainContextWhenHidden: true }));
|
||||
const ready = getMessage(webview);
|
||||
webview.webview.html = createHtmlDocumentWithBody(/*html*/`
|
||||
<script>
|
||||
const vscode = acquireVsCodeApi();
|
||||
|
||||
window.addEventListener('message', (message) => {
|
||||
switch (message.data.type) {
|
||||
case 'add1':
|
||||
const uint8Array = message.data.array1;
|
||||
|
||||
// This should update both buffers since they use the same ArrayBuffer storage
|
||||
const uint16Array = message.data.array2;
|
||||
for (let i = 0; i < uint16Array.length; ++i) {
|
||||
uint16Array[i] = uint16Array[i] + 1;
|
||||
}
|
||||
|
||||
vscode.postMessage({ array1: uint8Array, array2: uint16Array, }, [uint16Array.buffer]);
|
||||
break;
|
||||
}
|
||||
});
|
||||
vscode.postMessage({ type: 'ready' });
|
||||
</script>`);
|
||||
await ready;
|
||||
|
||||
const responsePromise = getMessage(webview);
|
||||
|
||||
const bufferLen = 100;
|
||||
{
|
||||
const arrayBuffer = new ArrayBuffer(bufferLen);
|
||||
const uint8Array = new Uint8Array(arrayBuffer);
|
||||
const uint16Array = new Uint16Array(arrayBuffer);
|
||||
for (let i = 0; i < uint16Array.length; ++i) {
|
||||
uint16Array[i] = i;
|
||||
}
|
||||
|
||||
webview.webview.postMessage({
|
||||
type: 'add1',
|
||||
array1: uint8Array,
|
||||
array2: uint16Array,
|
||||
});
|
||||
}
|
||||
{
|
||||
const response = await responsePromise;
|
||||
|
||||
assert.ok(response.array1 instanceof Uint8Array);
|
||||
assert.ok(response.array2 instanceof Uint16Array);
|
||||
assert.ok(response.array1.buffer === response.array2.buffer);
|
||||
|
||||
const uint8Array = response.array1;
|
||||
for (let i = 0; i < bufferLen; ++i) {
|
||||
if (i % 2 === 0) {
|
||||
assert.strictEqual(uint8Array[i], Math.floor(i / 2) + 1);
|
||||
} else {
|
||||
assert.strictEqual(uint8Array[i], 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function createHtmlDocumentWithBody(body: string): string {
|
||||
@@ -437,7 +549,7 @@ const statefulWebviewHtml = createHtmlDocumentWithBody(/*html*/ `
|
||||
</script>`);
|
||||
|
||||
|
||||
function getMesssage<R = any>(webview: vscode.WebviewPanel): Promise<R> {
|
||||
function getMessage<R = any>(webview: vscode.WebviewPanel): Promise<R> {
|
||||
return new Promise<R>(resolve => {
|
||||
const sub = webview.webview.onDidReceiveMessage(message => {
|
||||
sub.dispose();
|
||||
@@ -447,7 +559,7 @@ function getMesssage<R = any>(webview: vscode.WebviewPanel): Promise<R> {
|
||||
}
|
||||
|
||||
function sendRecieveMessage<T = {}, R = any>(webview: vscode.WebviewPanel, message: T): Promise<R> {
|
||||
const p = getMesssage<R>(webview);
|
||||
const p = getMessage<R>(webview);
|
||||
webview.webview.postMessage(message);
|
||||
return p;
|
||||
}
|
||||
|
||||
@@ -6,12 +6,15 @@
|
||||
import * as assert from 'assert';
|
||||
import { workspace, window, commands, ViewColumn, TextEditorViewColumnChangeEvent, Uri, Selection, Position, CancellationTokenSource, TextEditorSelectionChangeKind, QuickPickItem, TextEditor } from 'vscode';
|
||||
import { join } from 'path';
|
||||
import { closeAllEditors, pathEquals, createRandomFile } from '../utils';
|
||||
import { closeAllEditors, pathEquals, createRandomFile, assertNoRpc } from '../utils';
|
||||
|
||||
|
||||
suite('vscode API - window', () => {
|
||||
|
||||
teardown(closeAllEditors);
|
||||
teardown(async function () {
|
||||
assertNoRpc();
|
||||
await closeAllEditors();
|
||||
});
|
||||
|
||||
test('editor, active text editor', async () => {
|
||||
const doc = await workspace.openTextDocument(join(workspace.rootPath || '', './far.js'));
|
||||
@@ -147,6 +150,13 @@ suite('vscode API - window', () => {
|
||||
});
|
||||
|
||||
test('active editor not always correct... #49125', async function () {
|
||||
|
||||
if (!window.state.focused) {
|
||||
// no focus!
|
||||
this.skip();
|
||||
return;
|
||||
}
|
||||
|
||||
if (process.env['BUILD_SOURCEVERSION']) {
|
||||
this.skip();
|
||||
return;
|
||||
@@ -429,8 +439,8 @@ suite('vscode API - window', () => {
|
||||
});
|
||||
|
||||
test('showQuickPick, select first two', async function () {
|
||||
const label = 'showQuickPick, select first two';
|
||||
let i = 0;
|
||||
// const label = 'showQuickPick, select first two';
|
||||
// let i = 0;
|
||||
const resolves: ((value: string) => void)[] = [];
|
||||
let done: () => void;
|
||||
const unexpected = new Promise<void>((resolve, reject) => {
|
||||
@@ -442,26 +452,26 @@ suite('vscode API - window', () => {
|
||||
canPickMany: true
|
||||
});
|
||||
const first = new Promise(resolve => resolves.push(resolve));
|
||||
console.log(`${label}: ${++i}`);
|
||||
// console.log(`${label}: ${++i}`);
|
||||
await new Promise(resolve => setTimeout(resolve, 100)); // Allow UI to update.
|
||||
console.log(`${label}: ${++i}`);
|
||||
// console.log(`${label}: ${++i}`);
|
||||
await commands.executeCommand('workbench.action.quickOpenSelectNext');
|
||||
console.log(`${label}: ${++i}`);
|
||||
// console.log(`${label}: ${++i}`);
|
||||
assert.equal(await first, 'eins');
|
||||
console.log(`${label}: ${++i}`);
|
||||
// console.log(`${label}: ${++i}`);
|
||||
await commands.executeCommand('workbench.action.quickPickManyToggle');
|
||||
console.log(`${label}: ${++i}`);
|
||||
// console.log(`${label}: ${++i}`);
|
||||
const second = new Promise(resolve => resolves.push(resolve));
|
||||
await commands.executeCommand('workbench.action.quickOpenSelectNext');
|
||||
console.log(`${label}: ${++i}`);
|
||||
// console.log(`${label}: ${++i}`);
|
||||
assert.equal(await second, 'zwei');
|
||||
console.log(`${label}: ${++i}`);
|
||||
// console.log(`${label}: ${++i}`);
|
||||
await commands.executeCommand('workbench.action.quickPickManyToggle');
|
||||
console.log(`${label}: ${++i}`);
|
||||
// console.log(`${label}: ${++i}`);
|
||||
await commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem');
|
||||
console.log(`${label}: ${++i}`);
|
||||
// console.log(`${label}: ${++i}`);
|
||||
assert.deepStrictEqual(await picks, ['eins', 'zwei']);
|
||||
console.log(`${label}: ${++i}`);
|
||||
// console.log(`${label}: ${++i}`);
|
||||
done!();
|
||||
return unexpected;
|
||||
});
|
||||
|
||||
@@ -5,20 +5,19 @@
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as vscode from 'vscode';
|
||||
import { createRandomFile, withLogDisabled } from '../utils';
|
||||
import { assertNoRpc, createRandomFile, disposeAll, withLogDisabled } from '../utils';
|
||||
|
||||
suite('vscode API - workspace events', () => {
|
||||
|
||||
const disposables: vscode.Disposable[] = [];
|
||||
|
||||
teardown(() => {
|
||||
for (const dispo of disposables) {
|
||||
dispo.dispose();
|
||||
}
|
||||
assertNoRpc();
|
||||
disposeAll(disposables);
|
||||
disposables.length = 0;
|
||||
});
|
||||
|
||||
test('onWillCreate/onDidCreate', async function () {
|
||||
test('onWillCreate/onDidCreate', withLogDisabled(async function () {
|
||||
|
||||
const base = await createRandomFile();
|
||||
const newUri = base.with({ path: base.path + '-foo' });
|
||||
@@ -42,9 +41,9 @@ suite('vscode API - workspace events', () => {
|
||||
assert.ok(onDidCreate);
|
||||
assert.equal(onDidCreate?.files.length, 1);
|
||||
assert.equal(onDidCreate?.files[0].toString(), newUri.toString());
|
||||
});
|
||||
}));
|
||||
|
||||
test('onWillCreate/onDidCreate, make changes, edit another file', async function () {
|
||||
test('onWillCreate/onDidCreate, make changes, edit another file', withLogDisabled(async function () {
|
||||
|
||||
const base = await createRandomFile();
|
||||
const baseDoc = await vscode.workspace.openTextDocument(base);
|
||||
@@ -64,7 +63,7 @@ suite('vscode API - workspace events', () => {
|
||||
assert.ok(success);
|
||||
|
||||
assert.equal(baseDoc.getText(), 'HALLO_NEW');
|
||||
});
|
||||
}));
|
||||
|
||||
test('onWillCreate/onDidCreate, make changes, edit new file fails', withLogDisabled(async function () {
|
||||
|
||||
@@ -88,7 +87,7 @@ suite('vscode API - workspace events', () => {
|
||||
assert.equal((await vscode.workspace.openTextDocument(newUri)).getText(), '');
|
||||
}));
|
||||
|
||||
test('onWillDelete/onDidDelete', async function () {
|
||||
test('onWillDelete/onDidDelete', withLogDisabled(async function () {
|
||||
|
||||
const base = await createRandomFile();
|
||||
|
||||
@@ -111,9 +110,9 @@ suite('vscode API - workspace events', () => {
|
||||
assert.ok(onDiddelete);
|
||||
assert.equal(onDiddelete?.files.length, 1);
|
||||
assert.equal(onDiddelete?.files[0].toString(), base.toString());
|
||||
});
|
||||
}));
|
||||
|
||||
test('onWillDelete/onDidDelete, make changes', async function () {
|
||||
test('onWillDelete/onDidDelete, make changes', withLogDisabled(async function () {
|
||||
|
||||
const base = await createRandomFile();
|
||||
const newUri = base.with({ path: base.path + '-NEW' });
|
||||
@@ -131,9 +130,9 @@ suite('vscode API - workspace events', () => {
|
||||
|
||||
const success = await vscode.workspace.applyEdit(edit);
|
||||
assert.ok(success);
|
||||
});
|
||||
}));
|
||||
|
||||
test('onWillDelete/onDidDelete, make changes, del another file', async function () {
|
||||
test('onWillDelete/onDidDelete, make changes, del another file', withLogDisabled(async function () {
|
||||
|
||||
const base = await createRandomFile();
|
||||
const base2 = await createRandomFile();
|
||||
@@ -152,9 +151,9 @@ suite('vscode API - workspace events', () => {
|
||||
assert.ok(success);
|
||||
|
||||
|
||||
});
|
||||
}));
|
||||
|
||||
test('onWillDelete/onDidDelete, make changes, double delete', async function () {
|
||||
test('onWillDelete/onDidDelete, make changes, double delete', withLogDisabled(async function () {
|
||||
|
||||
const base = await createRandomFile();
|
||||
let cnt = 0;
|
||||
@@ -171,9 +170,9 @@ suite('vscode API - workspace events', () => {
|
||||
|
||||
const success = await vscode.workspace.applyEdit(edit);
|
||||
assert.ok(success);
|
||||
});
|
||||
}));
|
||||
|
||||
test('onWillRename/onDidRename', async function () {
|
||||
test('onWillRename/onDidRename', withLogDisabled(async function () {
|
||||
|
||||
const oldUri = await createRandomFile();
|
||||
const newUri = oldUri.with({ path: oldUri.path + '-NEW' });
|
||||
@@ -199,15 +198,15 @@ suite('vscode API - workspace events', () => {
|
||||
assert.equal(onDidRename?.files.length, 1);
|
||||
assert.equal(onDidRename?.files[0].oldUri.toString(), oldUri.toString());
|
||||
assert.equal(onDidRename?.files[0].newUri.toString(), newUri.toString());
|
||||
});
|
||||
}));
|
||||
|
||||
test('onWillRename - make changes (saved file)', function () {
|
||||
test('onWillRename - make changes (saved file)', withLogDisabled(function () {
|
||||
return testOnWillRename(false);
|
||||
});
|
||||
}));
|
||||
|
||||
test('onWillRename - make changes (dirty file)', function () {
|
||||
test('onWillRename - make changes (dirty file)', withLogDisabled(function () {
|
||||
return testOnWillRename(true);
|
||||
});
|
||||
}));
|
||||
|
||||
async function testOnWillRename(withDirtyFile: boolean): Promise<void> {
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import * as assert from 'assert';
|
||||
import * as vscode from 'vscode';
|
||||
import { posix } from 'path';
|
||||
import { assertNoRpc } from '../utils';
|
||||
|
||||
suite('vscode API - workspace-fs', () => {
|
||||
|
||||
@@ -15,6 +16,8 @@ suite('vscode API - workspace-fs', () => {
|
||||
root = vscode.workspace.workspaceFolders![0]!.uri;
|
||||
});
|
||||
|
||||
teardown(assertNoRpc);
|
||||
|
||||
test('fs.stat', async function () {
|
||||
const stat = await vscode.workspace.fs.stat(root);
|
||||
assert.equal(stat.type, vscode.FileType.Directory);
|
||||
|
||||
@@ -4,261 +4,328 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { window, tasks, Disposable, TaskDefinition, Task, EventEmitter, CustomExecution, Pseudoterminal, TaskScope, commands, env, UIKind, ShellExecution, TaskExecution, Terminal, Event } from 'vscode';
|
||||
import { window, tasks, Disposable, TaskDefinition, Task, EventEmitter, CustomExecution, Pseudoterminal, TaskScope, commands, env, UIKind, ShellExecution, TaskExecution, Terminal, Event, workspace, ConfigurationTarget, TaskProcessStartEvent } from 'vscode';
|
||||
import { assertNoRpc } from '../utils';
|
||||
|
||||
// Disable tasks tests:
|
||||
// - Web https://github.com/microsoft/vscode/issues/90528
|
||||
((env.uiKind === UIKind.Web) ? suite.skip : suite)('vscode API - tasks', () => {
|
||||
|
||||
suiteSetup(async () => {
|
||||
const config = workspace.getConfiguration('terminal.integrated');
|
||||
// Disable conpty in integration tests because of https://github.com/microsoft/vscode/issues/76548
|
||||
await config.update('windowsEnableConpty', false, ConfigurationTarget.Global);
|
||||
// Disable exit alerts as tests may trigger then and we're not testing the notifications
|
||||
await config.update('showExitAlert', false, ConfigurationTarget.Global);
|
||||
// Canvas may cause problems when running in a container
|
||||
await config.update('gpuAcceleration', 'off', ConfigurationTarget.Global);
|
||||
// Disable env var relaunch for tests to prevent terminals relaunching themselves
|
||||
await config.update('environmentChangesRelaunch', false, ConfigurationTarget.Global);
|
||||
});
|
||||
|
||||
suite('Tasks', () => {
|
||||
let disposables: Disposable[] = [];
|
||||
|
||||
teardown(() => {
|
||||
assertNoRpc();
|
||||
disposables.forEach(d => d.dispose());
|
||||
disposables.length = 0;
|
||||
});
|
||||
|
||||
test('CustomExecution task should start and shutdown successfully', (done) => {
|
||||
interface CustomTestingTaskDefinition extends TaskDefinition {
|
||||
/**
|
||||
* One of the task properties. This can be used to customize the task in the tasks.json
|
||||
*/
|
||||
customProp1: string;
|
||||
}
|
||||
const taskType: string = 'customTesting';
|
||||
const taskName = 'First custom task';
|
||||
let isPseudoterminalClosed = false;
|
||||
let terminal: Terminal | undefined;
|
||||
// There's a strict order that should be observed here:
|
||||
// 1. The terminal opens
|
||||
// 2. The terminal is written to.
|
||||
// 3. The terminal is closed.
|
||||
enum TestOrder {
|
||||
Start,
|
||||
TerminalOpened,
|
||||
TerminalWritten,
|
||||
TerminalClosed
|
||||
}
|
||||
|
||||
let testOrder = TestOrder.Start;
|
||||
|
||||
disposables.push(window.onDidOpenTerminal(term => {
|
||||
try {
|
||||
assert.equal(testOrder, TestOrder.Start);
|
||||
} catch (e) {
|
||||
done(e);
|
||||
}
|
||||
testOrder = TestOrder.TerminalOpened;
|
||||
terminal = term;
|
||||
}));
|
||||
disposables.push(window.onDidWriteTerminalData(e => {
|
||||
try {
|
||||
assert.equal(testOrder, TestOrder.TerminalOpened);
|
||||
testOrder = TestOrder.TerminalWritten;
|
||||
assert.notEqual(terminal, undefined);
|
||||
assert.equal(e.data, 'testing\r\n');
|
||||
} catch (e) {
|
||||
done(e);
|
||||
}
|
||||
|
||||
if (terminal) {
|
||||
terminal.dispose();
|
||||
}
|
||||
}));
|
||||
disposables.push(window.onDidCloseTerminal(() => {
|
||||
try {
|
||||
assert.equal(testOrder, TestOrder.TerminalWritten);
|
||||
testOrder = TestOrder.TerminalClosed;
|
||||
// Pseudoterminal.close should have fired by now, additionally we want
|
||||
// to make sure all events are flushed before continuing with more tests
|
||||
assert.ok(isPseudoterminalClosed);
|
||||
} catch (e) {
|
||||
done(e);
|
||||
return;
|
||||
}
|
||||
done();
|
||||
}));
|
||||
disposables.push(tasks.registerTaskProvider(taskType, {
|
||||
provideTasks: () => {
|
||||
const result: Task[] = [];
|
||||
const kind: CustomTestingTaskDefinition = {
|
||||
type: taskType,
|
||||
customProp1: 'testing task one'
|
||||
};
|
||||
const writeEmitter = new EventEmitter<string>();
|
||||
const execution = new CustomExecution((): Thenable<Pseudoterminal> => {
|
||||
const pty: Pseudoterminal = {
|
||||
onDidWrite: writeEmitter.event,
|
||||
open: () => writeEmitter.fire('testing\r\n'),
|
||||
close: () => isPseudoterminalClosed = true
|
||||
};
|
||||
return Promise.resolve(pty);
|
||||
suite('ShellExecution', () => {
|
||||
test('Execution from onDidEndTaskProcess and onDidStartTaskProcess are equal to original', () => {
|
||||
return new Promise<void>(async (resolve) => {
|
||||
const task = new Task({ type: 'testTask' }, TaskScope.Workspace, 'echo', 'testTask', new ShellExecution('echo', ['hello test']));
|
||||
let taskExecution: TaskExecution | undefined;
|
||||
const executeDoneEvent: EventEmitter<void> = new EventEmitter();
|
||||
const taskExecutionShouldBeSet: Promise<void> = new Promise(resolve => {
|
||||
const disposable = executeDoneEvent.event(() => {
|
||||
resolve();
|
||||
disposable.dispose();
|
||||
});
|
||||
});
|
||||
const task = new Task(kind, TaskScope.Workspace, taskName, taskType, execution);
|
||||
result.push(task);
|
||||
return result;
|
||||
},
|
||||
resolveTask(_task: Task): Task | undefined {
|
||||
try {
|
||||
assert.fail('resolveTask should not trigger during the test');
|
||||
} catch (e) {
|
||||
done(e);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}));
|
||||
commands.executeCommand('workbench.action.tasks.runTask', `${taskType}: ${taskName}`);
|
||||
});
|
||||
let count = 2;
|
||||
const progressMade: EventEmitter<void> = new EventEmitter();
|
||||
let startSucceeded = false;
|
||||
let endSucceeded = false;
|
||||
disposables.push(progressMade.event(() => {
|
||||
count--;
|
||||
if ((count === 0) && startSucceeded && endSucceeded) {
|
||||
resolve();
|
||||
}
|
||||
}));
|
||||
|
||||
test('sync CustomExecution task should flush all data on close', (done) => {
|
||||
interface CustomTestingTaskDefinition extends TaskDefinition {
|
||||
/**
|
||||
* One of the task properties. This can be used to customize the task in the tasks.json
|
||||
*/
|
||||
customProp1: string;
|
||||
}
|
||||
const taskType: string = 'customTesting';
|
||||
const taskName = 'First custom task';
|
||||
disposables.push(window.onDidOpenTerminal(term => {
|
||||
disposables.push(window.onDidWriteTerminalData(e => {
|
||||
try {
|
||||
assert.equal(e.data, 'exiting');
|
||||
} catch (e) {
|
||||
done(e);
|
||||
}
|
||||
disposables.push(window.onDidCloseTerminal(() => done()));
|
||||
term.dispose();
|
||||
}));
|
||||
}));
|
||||
disposables.push(tasks.registerTaskProvider(taskType, {
|
||||
provideTasks: () => {
|
||||
const result: Task[] = [];
|
||||
const kind: CustomTestingTaskDefinition = {
|
||||
type: taskType,
|
||||
customProp1: 'testing task one'
|
||||
};
|
||||
const writeEmitter = new EventEmitter<string>();
|
||||
const closeEmitter = new EventEmitter<void>();
|
||||
const execution = new CustomExecution((): Thenable<Pseudoterminal> => {
|
||||
const pty: Pseudoterminal = {
|
||||
onDidWrite: writeEmitter.event,
|
||||
onDidClose: closeEmitter.event,
|
||||
open: () => {
|
||||
writeEmitter.fire('exiting');
|
||||
closeEmitter.fire();
|
||||
},
|
||||
close: () => { }
|
||||
};
|
||||
return Promise.resolve(pty);
|
||||
});
|
||||
const task = new Task(kind, TaskScope.Workspace, taskName, taskType, execution);
|
||||
result.push(task);
|
||||
return result;
|
||||
},
|
||||
resolveTask(_task: Task): Task | undefined {
|
||||
try {
|
||||
assert.fail('resolveTask should not trigger during the test');
|
||||
} catch (e) {
|
||||
done(e);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}));
|
||||
commands.executeCommand('workbench.action.tasks.runTask', `${taskType}: ${taskName}`);
|
||||
});
|
||||
|
||||
test('Execution from onDidEndTaskProcess and onDidStartTaskProcess are equal to original', () => {
|
||||
return new Promise<void>(async (resolve) => {
|
||||
const task = new Task({ type: 'testTask' }, TaskScope.Workspace, 'echo', 'testTask', new ShellExecution('echo', ['hello test']));
|
||||
let taskExecution: TaskExecution | undefined;
|
||||
const executeDoneEvent: EventEmitter<void> = new EventEmitter();
|
||||
const taskExecutionShouldBeSet: Promise<void> = new Promise(resolve => {
|
||||
const disposable = executeDoneEvent.event(() => {
|
||||
resolve();
|
||||
disposable.dispose();
|
||||
disposables.push(tasks.onDidStartTaskProcess(async (e) => {
|
||||
await taskExecutionShouldBeSet;
|
||||
if (e.execution === taskExecution) {
|
||||
startSucceeded = true;
|
||||
progressMade.fire();
|
||||
}
|
||||
}));
|
||||
|
||||
disposables.push(tasks.onDidEndTaskProcess(async (e) => {
|
||||
await taskExecutionShouldBeSet;
|
||||
if (e.execution === taskExecution) {
|
||||
endSucceeded = true;
|
||||
progressMade.fire();
|
||||
}
|
||||
}));
|
||||
taskExecution = await tasks.executeTask(task);
|
||||
executeDoneEvent.fire();
|
||||
});
|
||||
});
|
||||
|
||||
test('dependsOn task should start with a different processId (#118256)', async () => {
|
||||
// Set up dependsOn task by creating tasks.json since this is not possible via the API
|
||||
// Tasks API
|
||||
const tasksConfig = workspace.getConfiguration('tasks');
|
||||
await tasksConfig.update('version', '2.0.0', ConfigurationTarget.Workspace);
|
||||
await tasksConfig.update('tasks', [
|
||||
{
|
||||
label: 'taskToDependOn',
|
||||
type: 'shell',
|
||||
command: 'sleep 1',
|
||||
problemMatcher: []
|
||||
},
|
||||
{
|
||||
label: 'Run this task',
|
||||
type: 'shell',
|
||||
command: 'sleep 1',
|
||||
problemMatcher: [],
|
||||
dependsOn: 'taskToDependOn'
|
||||
}
|
||||
], ConfigurationTarget.Workspace);
|
||||
|
||||
// Run the task
|
||||
commands.executeCommand('workbench.action.tasks.runTask', 'Run this task');
|
||||
|
||||
// Listen for first task and verify valid process ID
|
||||
const startEvent1 = await new Promise<TaskProcessStartEvent>(r => {
|
||||
const listener = tasks.onDidStartTaskProcess(async (e) => {
|
||||
if (e.execution.task.name === 'taskToDependOn') {
|
||||
listener.dispose();
|
||||
r(e);
|
||||
}
|
||||
});
|
||||
});
|
||||
let count = 2;
|
||||
const progressMade: EventEmitter<void> = new EventEmitter();
|
||||
let startSucceeded = false;
|
||||
let endSucceeded = false;
|
||||
disposables.push(progressMade.event(() => {
|
||||
count--;
|
||||
if ((count === 0) && startSucceeded && endSucceeded) {
|
||||
resolve();
|
||||
}
|
||||
}));
|
||||
assert.ok(startEvent1.processId);
|
||||
|
||||
// Listen for second task, verify valid process ID and that it's not the process ID of
|
||||
// the first task
|
||||
const startEvent2 = await new Promise<TaskProcessStartEvent>(r => {
|
||||
const listener = tasks.onDidStartTaskProcess(async (e) => {
|
||||
if (e.execution.task.name === 'Run this task') {
|
||||
listener.dispose();
|
||||
r(e);
|
||||
}
|
||||
});
|
||||
});
|
||||
assert.ok(startEvent2.processId);
|
||||
assert.notStrictEqual(startEvent1.processId, startEvent2.processId);
|
||||
|
||||
disposables.push(tasks.onDidStartTaskProcess(async (e) => {
|
||||
await taskExecutionShouldBeSet;
|
||||
if (e.execution === taskExecution) {
|
||||
startSucceeded = true;
|
||||
progressMade.fire();
|
||||
}
|
||||
}));
|
||||
|
||||
disposables.push(tasks.onDidEndTaskProcess(async (e) => {
|
||||
await taskExecutionShouldBeSet;
|
||||
if (e.execution === taskExecution) {
|
||||
endSucceeded = true;
|
||||
progressMade.fire();
|
||||
}
|
||||
}));
|
||||
|
||||
taskExecution = await tasks.executeTask(task);
|
||||
executeDoneEvent.fire();
|
||||
// Clear out tasks config
|
||||
await tasksConfig.update('tasks', []);
|
||||
});
|
||||
});
|
||||
|
||||
// https://github.com/microsoft/vscode/issues/100577
|
||||
test('A CustomExecution task can be fetched and executed', () => {
|
||||
return new Promise<void>(async (resolve, reject) => {
|
||||
class CustomTerminal implements Pseudoterminal {
|
||||
private readonly writeEmitter = new EventEmitter<string>();
|
||||
public readonly onDidWrite: Event<string> = this.writeEmitter.event;
|
||||
public async close(): Promise<void> { }
|
||||
private closeEmitter = new EventEmitter<void>();
|
||||
onDidClose: Event<void> = this.closeEmitter.event;
|
||||
public open(): void {
|
||||
this.closeEmitter.fire();
|
||||
resolve();
|
||||
}
|
||||
suite('CustomExecution', () => {
|
||||
test('task should start and shutdown successfully', async () => {
|
||||
interface CustomTestingTaskDefinition extends TaskDefinition {
|
||||
/**
|
||||
* One of the task properties. This can be used to customize the task in the tasks.json
|
||||
*/
|
||||
customProp1: string;
|
||||
}
|
||||
const taskType: string = 'customTesting';
|
||||
const taskName = 'First custom task';
|
||||
let isPseudoterminalClosed = false;
|
||||
// There's a strict order that should be observed here:
|
||||
// 1. The terminal opens
|
||||
// 2. The terminal is written to.
|
||||
// 3. The terminal is closed.
|
||||
enum TestOrder {
|
||||
Start,
|
||||
TerminalOpened,
|
||||
TerminalWritten,
|
||||
TerminalClosed
|
||||
}
|
||||
|
||||
function buildTask(): Task {
|
||||
const task = new Task(
|
||||
{
|
||||
type: 'customTesting',
|
||||
let testOrder = TestOrder.Start;
|
||||
|
||||
// Launch the task
|
||||
const terminal = await new Promise<Terminal>(r => {
|
||||
disposables.push(window.onDidOpenTerminal(e => {
|
||||
assert.strictEqual(testOrder, TestOrder.Start);
|
||||
testOrder = TestOrder.TerminalOpened;
|
||||
r(e);
|
||||
}));
|
||||
disposables.push(tasks.registerTaskProvider(taskType, {
|
||||
provideTasks: () => {
|
||||
const result: Task[] = [];
|
||||
const kind: CustomTestingTaskDefinition = {
|
||||
type: taskType,
|
||||
customProp1: 'testing task one'
|
||||
};
|
||||
const writeEmitter = new EventEmitter<string>();
|
||||
const execution = new CustomExecution((): Thenable<Pseudoterminal> => {
|
||||
const pty: Pseudoterminal = {
|
||||
onDidWrite: writeEmitter.event,
|
||||
open: () => writeEmitter.fire('testing\r\n'),
|
||||
close: () => isPseudoterminalClosed = true
|
||||
};
|
||||
return Promise.resolve(pty);
|
||||
});
|
||||
const task = new Task(kind, TaskScope.Workspace, taskName, taskType, execution);
|
||||
result.push(task);
|
||||
return result;
|
||||
},
|
||||
TaskScope.Workspace,
|
||||
'Test Task',
|
||||
'customTesting',
|
||||
new CustomExecution(
|
||||
async (): Promise<Pseudoterminal> => {
|
||||
return new CustomTerminal();
|
||||
}
|
||||
)
|
||||
);
|
||||
return task;
|
||||
}
|
||||
resolveTask(_task: Task): Task | undefined {
|
||||
assert.fail('resolveTask should not trigger during the test');
|
||||
}
|
||||
}));
|
||||
commands.executeCommand('workbench.action.tasks.runTask', `${taskType}: ${taskName}`);
|
||||
});
|
||||
|
||||
disposables.push(tasks.registerTaskProvider('customTesting', {
|
||||
provideTasks: () => {
|
||||
return [buildTask()];
|
||||
},
|
||||
resolveTask(_task: Task): undefined {
|
||||
return undefined;
|
||||
// Verify the output
|
||||
await new Promise<void>(r => {
|
||||
disposables.push(window.onDidWriteTerminalData(e => {
|
||||
if (e.terminal !== terminal) {
|
||||
return;
|
||||
}
|
||||
assert.strictEqual(testOrder, TestOrder.TerminalOpened);
|
||||
testOrder = TestOrder.TerminalWritten;
|
||||
assert.notStrictEqual(terminal, undefined);
|
||||
assert.strictEqual(e.data, 'testing\r\n');
|
||||
r();
|
||||
}));
|
||||
});
|
||||
|
||||
// Dispose the terminal
|
||||
await new Promise<void>(r => {
|
||||
disposables.push(window.onDidCloseTerminal(() => {
|
||||
assert.strictEqual(testOrder, TestOrder.TerminalWritten);
|
||||
testOrder = TestOrder.TerminalClosed;
|
||||
// Pseudoterminal.close should have fired by now, additionally we want
|
||||
// to make sure all events are flushed before continuing with more tests
|
||||
assert.ok(isPseudoterminalClosed);
|
||||
r();
|
||||
}));
|
||||
terminal.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
test('sync task should flush all data on close', async () => {
|
||||
interface CustomTestingTaskDefinition extends TaskDefinition {
|
||||
/**
|
||||
* One of the task properties. This can be used to customize the task in the tasks.json
|
||||
*/
|
||||
customProp1: string;
|
||||
}
|
||||
const taskType: string = 'customTesting';
|
||||
const taskName = 'First custom task';
|
||||
|
||||
// Launch the task
|
||||
const terminal = await new Promise<Terminal>(r => {
|
||||
disposables.push(window.onDidOpenTerminal(e => r(e)));
|
||||
disposables.push(tasks.registerTaskProvider(taskType, {
|
||||
provideTasks: () => {
|
||||
const result: Task[] = [];
|
||||
const kind: CustomTestingTaskDefinition = {
|
||||
type: taskType,
|
||||
customProp1: 'testing task one'
|
||||
};
|
||||
const writeEmitter = new EventEmitter<string>();
|
||||
const closeEmitter = new EventEmitter<void>();
|
||||
const execution = new CustomExecution((): Thenable<Pseudoterminal> => {
|
||||
const pty: Pseudoterminal = {
|
||||
onDidWrite: writeEmitter.event,
|
||||
onDidClose: closeEmitter.event,
|
||||
open: () => {
|
||||
writeEmitter.fire('exiting');
|
||||
closeEmitter.fire();
|
||||
},
|
||||
close: () => { }
|
||||
};
|
||||
return Promise.resolve(pty);
|
||||
});
|
||||
const task = new Task(kind, TaskScope.Workspace, taskName, taskType, execution);
|
||||
result.push(task);
|
||||
return result;
|
||||
},
|
||||
resolveTask(_task: Task): Task | undefined {
|
||||
assert.fail('resolveTask should not trigger during the test');
|
||||
}
|
||||
}));
|
||||
commands.executeCommand('workbench.action.tasks.runTask', `${taskType}: ${taskName}`);
|
||||
});
|
||||
|
||||
// Verify the output
|
||||
await new Promise<void>(r => {
|
||||
disposables.push(window.onDidWriteTerminalData(e => {
|
||||
if (e.terminal !== terminal) {
|
||||
return;
|
||||
}
|
||||
assert.strictEqual(e.data, 'exiting');
|
||||
r();
|
||||
}));
|
||||
});
|
||||
|
||||
// Dispose the terminal
|
||||
await new Promise<void>(r => {
|
||||
disposables.push(window.onDidCloseTerminal(() => r()));
|
||||
terminal.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
test('A task can be fetched and executed (#100577)', () => {
|
||||
return new Promise<void>(async (resolve, reject) => {
|
||||
class CustomTerminal implements Pseudoterminal {
|
||||
private readonly writeEmitter = new EventEmitter<string>();
|
||||
public readonly onDidWrite: Event<string> = this.writeEmitter.event;
|
||||
public async close(): Promise<void> { }
|
||||
private closeEmitter = new EventEmitter<void>();
|
||||
onDidClose: Event<void> = this.closeEmitter.event;
|
||||
public open(): void {
|
||||
this.closeEmitter.fire();
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
const task = await tasks.fetchTasks({ type: 'customTesting' });
|
||||
function buildTask(): Task {
|
||||
const task = new Task(
|
||||
{
|
||||
type: 'customTesting',
|
||||
},
|
||||
TaskScope.Workspace,
|
||||
'Test Task',
|
||||
'customTesting',
|
||||
new CustomExecution(
|
||||
async (): Promise<Pseudoterminal> => {
|
||||
return new CustomTerminal();
|
||||
}
|
||||
)
|
||||
);
|
||||
return task;
|
||||
}
|
||||
|
||||
if (task && task.length > 0) {
|
||||
await tasks.executeTask(task[0]);
|
||||
} else {
|
||||
reject('fetched task can\'t be undefined');
|
||||
}
|
||||
disposables.push(tasks.registerTaskProvider('customTesting', {
|
||||
provideTasks: () => {
|
||||
return [buildTask()];
|
||||
},
|
||||
resolveTask(_task: Task): undefined {
|
||||
return undefined;
|
||||
}
|
||||
}));
|
||||
|
||||
const task = await tasks.fetchTasks({ type: 'customTesting' });
|
||||
|
||||
if (task && task.length > 0) {
|
||||
await tasks.executeTask(task[0]);
|
||||
} else {
|
||||
reject('fetched task can\'t be undefined');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,14 +5,17 @@
|
||||
|
||||
import * as assert from 'assert';
|
||||
import * as vscode from 'vscode';
|
||||
import { createRandomFile, deleteFile, closeAllEditors, pathEquals, rndName, disposeAll, testFs, delay, withLogDisabled, revertAllDirty } from '../utils';
|
||||
import { createRandomFile, deleteFile, closeAllEditors, pathEquals, rndName, disposeAll, testFs, delay, withLogDisabled, revertAllDirty, assertNoRpc } from '../utils';
|
||||
import { join, posix, basename } from 'path';
|
||||
import * as fs from 'fs';
|
||||
import { TestFS } from '../memfs';
|
||||
|
||||
suite('vscode API - workspace', () => {
|
||||
|
||||
teardown(closeAllEditors);
|
||||
teardown(async function () {
|
||||
assertNoRpc();
|
||||
await closeAllEditors();
|
||||
});
|
||||
|
||||
test('MarkdownString', function () {
|
||||
let md = new vscode.MarkdownString();
|
||||
|
||||
Reference in New Issue
Block a user