chore(vscode): update to 1.55.2
This commit is contained in:
@ -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
|
||||
};
|
||||
|
||||
|
@ -11,10 +11,10 @@ suite('Notebook Document', function () {
|
||||
|
||||
const contentProvider = new class implements vscode.NotebookContentProvider {
|
||||
async openNotebook(uri: vscode.Uri, _openContext: vscode.NotebookDocumentOpenContext): Promise<vscode.NotebookData> {
|
||||
return {
|
||||
cells: [{ cellKind: vscode.NotebookCellKind.Code, source: uri.toString(), language: 'javascript', metadata: new vscode.NotebookCellMetadata(), outputs: [] }],
|
||||
metadata: new vscode.NotebookDocumentMetadata()
|
||||
};
|
||||
return new vscode.NotebookData(
|
||||
[new vscode.NotebookCellData(vscode.NotebookCellKind.Code, uri.toString(), 'javascript')],
|
||||
new vscode.NotebookDocumentMetadata()
|
||||
);
|
||||
}
|
||||
async resolveNotebook(_document: vscode.NotebookDocument, _webview: vscode.NotebookCommunication) {
|
||||
//
|
||||
@ -100,11 +100,11 @@ suite('Notebook Document', function () {
|
||||
|
||||
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.uri.toString());
|
||||
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.language);
|
||||
assert.strictEqual(doc?.languageId, cell.document.languageId);
|
||||
assert.strictEqual(doc?.isDirty, false);
|
||||
assert.strictEqual(doc?.isClosed, false);
|
||||
}
|
||||
@ -125,13 +125,13 @@ suite('Notebook Document', function () {
|
||||
{
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCells(document.uri, 0, 0, [{
|
||||
cellKind: vscode.NotebookCellKind.Markdown,
|
||||
kind: vscode.NotebookCellKind.Markdown,
|
||||
language: 'markdown',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
source: 'new_markdown'
|
||||
}, {
|
||||
cellKind: vscode.NotebookCellKind.Code,
|
||||
kind: vscode.NotebookCellKind.Code,
|
||||
language: 'fooLang',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
@ -162,13 +162,13 @@ suite('Notebook Document', function () {
|
||||
{
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCells(document.uri, 0, 1, [{
|
||||
cellKind: vscode.NotebookCellKind.Markdown,
|
||||
kind: vscode.NotebookCellKind.Markdown,
|
||||
language: 'markdown',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
source: 'new2_markdown'
|
||||
}, {
|
||||
cellKind: vscode.NotebookCellKind.Code,
|
||||
kind: vscode.NotebookCellKind.Code,
|
||||
language: 'fooLang',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
@ -198,13 +198,13 @@ suite('Notebook Document', function () {
|
||||
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCells(document.uri, 0, 0, [{
|
||||
cellKind: vscode.NotebookCellKind.Markdown,
|
||||
kind: vscode.NotebookCellKind.Markdown,
|
||||
language: 'markdown',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
source: 'new_markdown'
|
||||
}, {
|
||||
cellKind: vscode.NotebookCellKind.Code,
|
||||
kind: vscode.NotebookCellKind.Code,
|
||||
language: 'fooLang',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
@ -306,13 +306,13 @@ suite('Notebook Document', function () {
|
||||
|
||||
const edit = new vscode.WorkspaceEdit();
|
||||
edit.replaceNotebookCells(notebook.uri, 0, 0, [{
|
||||
cellKind: vscode.NotebookCellKind.Markdown,
|
||||
kind: vscode.NotebookCellKind.Markdown,
|
||||
language: 'markdown',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
source: 'new_markdown'
|
||||
}, {
|
||||
cellKind: vscode.NotebookCellKind.Code,
|
||||
kind: vscode.NotebookCellKind.Code,
|
||||
language: 'fooLang',
|
||||
metadata: undefined,
|
||||
outputs: [],
|
||||
@ -344,8 +344,8 @@ suite('Notebook Document', function () {
|
||||
const closed = await pclose;
|
||||
const opened = await popen;
|
||||
|
||||
assert.strictEqual(closed.uri.toString(), first.uri.toString());
|
||||
assert.strictEqual(opened.uri.toString(), first.uri.toString());
|
||||
assert.strictEqual(closed.uri.toString(), first.document.uri.toString());
|
||||
assert.strictEqual(opened.uri.toString(), first.document.uri.toString());
|
||||
assert.strictEqual(opened === closed, true);
|
||||
});
|
||||
|
||||
|
@ -0,0 +1,78 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 resolveNotebook(_document: vscode.NotebookDocument, _webview: vscode.NotebookCommunication) {
|
||||
//
|
||||
}
|
||||
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.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());
|
||||
});
|
||||
});
|
File diff suppressed because it is too large
Load Diff
@ -9,8 +9,7 @@ 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 () => {
|
||||
@ -25,6 +24,8 @@ import { assertNoRpc } from '../utils';
|
||||
await config.update('showExitAlert', false, ConfigurationTarget.Global);
|
||||
// Canvas may cause problems when running in a container
|
||||
await config.update('rendererType', 'dom', ConfigurationTarget.Global);
|
||||
// Disable env var relaunch for tests to prevent terminals relaunching themselves
|
||||
await config.update('environmentChangesRelaunch', false, ConfigurationTarget.Global);
|
||||
});
|
||||
|
||||
suite('Terminal', () => {
|
||||
@ -633,7 +634,7 @@ import { assertNoRpc } from '../utils';
|
||||
});
|
||||
|
||||
suite('environmentVariableCollection', () => {
|
||||
test('should have collection variables apply to terminals immediately after setting', (done) => {
|
||||
test.skip('should have collection variables apply to terminals immediately after setting', (done) => {
|
||||
// Text to match on before passing the test
|
||||
const expectedText = [
|
||||
'~a2~',
|
||||
|
@ -4,13 +4,25 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
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('rendererType', 'dom', 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[] = [];
|
||||
|
||||
@ -20,247 +32,300 @@ import { assertNoRpc } from '../utils';
|
||||
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');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user