mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-14 12:08:36 -05:00
Merge from vscode 2c306f762bf9c3db82dc06c7afaa56ef46d72f79 (#14050)
* Merge from vscode 2c306f762bf9c3db82dc06c7afaa56ef46d72f79 * Fix breaks * Extension management fixes * Fix breaks in windows bundling * Fix/skip failing tests * Update distro * Add clear to nuget.config * Add hygiene task * Bump distro * Fix hygiene issue * Add build to hygiene exclusion * Update distro * Update hygiene * Hygiene exclusions * Update tsconfig * Bump distro for server breaks * Update build config * Update darwin path * Add done calls to notebook tests * Skip failing tests * Disable smoke tests
This commit is contained in:
@@ -28,7 +28,7 @@ import 'vs/workbench/contrib/search/browser/search.contribution';
|
||||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
import { ITextModel } from 'vs/editor/common/model';
|
||||
import { nullExtensionDescription, IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { dispose } from 'vs/base/common/lifecycle';
|
||||
import { dispose, ImmortalReference } from 'vs/base/common/lifecycle';
|
||||
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
|
||||
import { mock } from 'vs/base/test/common/mock';
|
||||
import { NullApiDeprecationService } from 'vs/workbench/api/common/extHostApiDeprecationService';
|
||||
@@ -48,6 +48,7 @@ import 'vs/editor/contrib/parameterHints/provideSignatureHelp';
|
||||
import 'vs/editor/contrib/smartSelect/smartSelect';
|
||||
import 'vs/editor/contrib/suggest/suggest';
|
||||
import 'vs/editor/contrib/rename/rename';
|
||||
import { IResolvedTextEditorModel, ITextModelService } from 'vs/editor/common/services/resolverService';
|
||||
|
||||
const defaultSelector = { scheme: 'far' };
|
||||
const model: ITextModel = createTextModel(
|
||||
@@ -108,6 +109,13 @@ suite('ExtHostLanguageFeatureCommands', function () {
|
||||
services.set(IModelService, new class extends mock<IModelService>() {
|
||||
getModel() { return model; }
|
||||
});
|
||||
services.set(ITextModelService, new class extends mock<ITextModelService>() {
|
||||
async createModelReference() {
|
||||
return new ImmortalReference<IResolvedTextEditorModel>(new class extends mock<IResolvedTextEditorModel>() {
|
||||
textEditorModel = model;
|
||||
});
|
||||
}
|
||||
});
|
||||
services.set(IEditorWorkerService, new class extends mock<IEditorWorkerService>() {
|
||||
async computeMoreMinimalEdits(_uri: any, edits: any) {
|
||||
return edits || undefined;
|
||||
@@ -925,6 +933,38 @@ suite('ExtHostLanguageFeatureCommands', function () {
|
||||
});
|
||||
});
|
||||
|
||||
test('resolving code action', async function () {
|
||||
|
||||
let didCallResolve = 0;
|
||||
class MyAction extends types.CodeAction { }
|
||||
|
||||
disposables.push(extHost.registerCodeActionProvider(nullExtensionDescription, defaultSelector, {
|
||||
provideCodeActions(document, rangeOrSelection): vscode.CodeAction[] {
|
||||
return [new MyAction('title', types.CodeActionKind.Empty.append('foo'))];
|
||||
},
|
||||
resolveCodeAction(action): vscode.CodeAction {
|
||||
assert.ok(action instanceof MyAction);
|
||||
|
||||
didCallResolve += 1;
|
||||
action.title = 'resolved title';
|
||||
action.edit = new types.WorkspaceEdit();
|
||||
return action;
|
||||
}
|
||||
}));
|
||||
|
||||
const selection = new types.Selection(0, 0, 1, 1);
|
||||
|
||||
await rpcProtocol.sync();
|
||||
|
||||
const value = await commands.executeCommand<vscode.CodeAction[]>('vscode.executeCodeActionProvider', model.uri, selection, undefined, 1000);
|
||||
assert.equal(didCallResolve, 1);
|
||||
assert.equal(value.length, 1);
|
||||
|
||||
const [first] = value;
|
||||
assert.equal(first.title, 'title'); // does NOT change
|
||||
assert.ok(first.edit); // is set
|
||||
});
|
||||
|
||||
// --- code lens
|
||||
|
||||
test('CodeLens, back and forth', function () {
|
||||
|
||||
@@ -43,6 +43,16 @@ suite('ExtHostBulkEdits.applyWorkspaceEdit', () => {
|
||||
bulkEdits = new ExtHostBulkEdits(rpcProtocol, documentsAndEditors, null!);
|
||||
});
|
||||
|
||||
test('uses version id if document available', async () => {
|
||||
let edit = new extHostTypes.WorkspaceEdit();
|
||||
edit.replace(resource, new extHostTypes.Range(0, 0, 0, 0), 'hello');
|
||||
await bulkEdits.applyWorkspaceEdit(edit);
|
||||
assert.equal(workspaceResourceEdits.edits.length, 1);
|
||||
const [first] = workspaceResourceEdits.edits;
|
||||
assertType(first._type === WorkspaceEditType.Text);
|
||||
assert.equal(first.modelVersionId, 1337);
|
||||
});
|
||||
|
||||
test('does not use version id if document is not available', async () => {
|
||||
let edit = new extHostTypes.WorkspaceEdit();
|
||||
edit.replace(URI.parse('foo:bar2'), new extHostTypes.Range(0, 0, 0, 0), 'hello');
|
||||
|
||||
@@ -15,6 +15,9 @@ import { IWorkspaceFolder, WorkspaceFolder } from 'vs/platform/workspace/common/
|
||||
import { ConfigurationTarget, IConfigurationModel, IConfigurationChange } from 'vs/platform/configuration/common/configuration';
|
||||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
import { IExtHostFileSystemInfo } from 'vs/workbench/api/common/extHostFileSystemInfo';
|
||||
import { FileSystemProviderCapabilities } from 'vs/platform/files/common/files';
|
||||
import { isLinux } from 'vs/base/common/platform';
|
||||
|
||||
suite('ExtHostConfiguration', function () {
|
||||
|
||||
@@ -27,7 +30,7 @@ suite('ExtHostConfiguration', function () {
|
||||
}
|
||||
|
||||
function createExtHostWorkspace(): ExtHostWorkspace {
|
||||
return new ExtHostWorkspace(new TestRPCProtocol(), new class extends mock<IExtHostInitDataService>() { }, new NullLogService());
|
||||
return new ExtHostWorkspace(new TestRPCProtocol(), new class extends mock<IExtHostInitDataService>() { }, new class extends mock<IExtHostFileSystemInfo>() { getCapabilities() { return isLinux ? FileSystemProviderCapabilities.PathCaseSensitive : undefined; } }, new NullLogService());
|
||||
}
|
||||
|
||||
function createExtHostConfiguration(contents: any = Object.create(null), shape?: MainThreadConfigurationShape) {
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
import * as assert from 'assert';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { mock } from 'vs/base/test/common/mock';
|
||||
import { NullLogService } from 'vs/platform/log/common/log';
|
||||
@@ -47,20 +46,20 @@ suite('ExtHostDecorations', function () {
|
||||
let calledB = false;
|
||||
|
||||
// never returns
|
||||
extHostDecorations.registerDecorationProvider({
|
||||
onDidChangeDecorations: Event.None,
|
||||
provideDecoration() {
|
||||
extHostDecorations.registerFileDecorationProvider({
|
||||
|
||||
provideFileDecoration() {
|
||||
calledA = true;
|
||||
return new Promise(() => { });
|
||||
}
|
||||
}, nullExtensionDescription.identifier);
|
||||
|
||||
// always returns
|
||||
extHostDecorations.registerDecorationProvider({
|
||||
onDidChangeDecorations: Event.None,
|
||||
provideDecoration() {
|
||||
extHostDecorations.registerFileDecorationProvider({
|
||||
|
||||
provideFileDecoration() {
|
||||
calledB = true;
|
||||
return new Promise(resolve => resolve({ letter: 'H', title: 'Hello' }));
|
||||
return new Promise(resolve => resolve({ badge: 'H', tooltip: 'Hello' }));
|
||||
}
|
||||
}, nullExtensionDescription.identifier);
|
||||
|
||||
|
||||
@@ -331,6 +331,21 @@ suite('ExtHostDocumentData', () => {
|
||||
assert.equal(range.start.character, 4);
|
||||
assert.equal(range.end.character, 28);
|
||||
});
|
||||
|
||||
test('Custom snippet $TM_SELECTED_TEXT not show suggestion #108892', function () {
|
||||
|
||||
data = new ExtHostDocumentData(undefined!, URI.file(''), [
|
||||
` <p><span xml:lang="en">Sheldon</span>, soprannominato "<span xml:lang="en">Shelly</span> dalla madre e dalla sorella, è nato a <span xml:lang="en">Galveston</span>, in <span xml:lang="en">Texas</span>, il 26 febbraio 1980 in un supermercato. È stato un bambino prodigio, come testimoniato dal suo quoziente d'intelligenza (187, di molto superiore alla norma) e dalla sua rapida carriera scolastica: si è diplomato all'eta di 11 anni approdando alla stessa età alla formazione universitaria e all'età di 16 anni ha ottenuto il suo primo dottorato di ricerca. All'inizio della serie e per gran parte di essa vive con il coinquilino Leonard nell'appartamento 4A al 2311 <span xml:lang="en">North Los Robles Avenue</span> di <span xml:lang="en">Pasadena</span>, per poi trasferirsi nell'appartamento di <span xml:lang="en">Penny</span> con <span xml:lang="en">Amy</span> nella decima stagione. Come più volte afferma lui stesso possiede una memoria eidetica e un orecchio assoluto. È stato educato da una madre estremamente religiosa e, in più occasioni, questo aspetto contrasta con il rigore scientifico di <span xml:lang="en">Sheldon</span>; tuttavia la donna sembra essere l'unica persona in grado di comandarlo a bacchetta.</p>`
|
||||
], '\n', 1, 'text', false);
|
||||
|
||||
const pos = new Position(0, 55);
|
||||
const range = data.document.getWordRangeAtPosition(pos)!;
|
||||
assert.equal(range.start.line, 0);
|
||||
assert.equal(range.end.line, 0);
|
||||
assert.equal(range.start.character, 47);
|
||||
assert.equal(range.end.character, 61);
|
||||
assert.equal(data.document.getText(range), 'soprannominato');
|
||||
});
|
||||
});
|
||||
|
||||
enum AssertDocumentLineMappingDirection {
|
||||
|
||||
@@ -31,6 +31,7 @@ suite('ExtHostDocumentSaveParticipant', () => {
|
||||
engines: undefined!,
|
||||
extensionLocation: undefined!,
|
||||
isBuiltin: false,
|
||||
isUserBuiltin: false,
|
||||
isUnderDevelopment: false,
|
||||
version: undefined!
|
||||
};
|
||||
|
||||
@@ -594,10 +594,10 @@ suite('ExtHostLanguageFeatures', function () {
|
||||
const { validActions: actions } = await getCodeActions(model, model.getFullModelRange(), { type: modes.CodeActionTriggerType.Manual }, Progress.None, CancellationToken.None);
|
||||
assert.equal(actions.length, 2);
|
||||
const [first, second] = actions;
|
||||
assert.equal(first.title, 'Testing1');
|
||||
assert.equal(first.command!.id, 'test1');
|
||||
assert.equal(second.title, 'Testing2');
|
||||
assert.equal(second.command!.id, 'test2');
|
||||
assert.equal(first.action.title, 'Testing1');
|
||||
assert.equal(first.action.command!.id, 'test1');
|
||||
assert.equal(second.action.title, 'Testing2');
|
||||
assert.equal(second.action.command!.id, 'test2');
|
||||
});
|
||||
|
||||
test('Quick Fix, code action data conversion', async () => {
|
||||
@@ -618,10 +618,10 @@ suite('ExtHostLanguageFeatures', function () {
|
||||
const { validActions: actions } = await getCodeActions(model, model.getFullModelRange(), { type: modes.CodeActionTriggerType.Manual }, Progress.None, CancellationToken.None);
|
||||
assert.equal(actions.length, 1);
|
||||
const [first] = actions;
|
||||
assert.equal(first.title, 'Testing1');
|
||||
assert.equal(first.command!.title, 'Testing1Command');
|
||||
assert.equal(first.command!.id, 'test1');
|
||||
assert.equal(first.kind, 'test.scope');
|
||||
assert.equal(first.action.title, 'Testing1');
|
||||
assert.equal(first.action.command!.title, 'Testing1Command');
|
||||
assert.equal(first.action.command!.id, 'test1');
|
||||
assert.equal(first.action.kind, 'test.scope');
|
||||
});
|
||||
|
||||
|
||||
@@ -1170,7 +1170,7 @@ suite('ExtHostLanguageFeatures', function () {
|
||||
|
||||
await rpcProtocol.sync();
|
||||
|
||||
provideSelectionRanges(model, [new Position(1, 17)], CancellationToken.None).then(ranges => {
|
||||
provideSelectionRanges(model, [new Position(1, 17)], { selectLeadingAndTrailingWhitespace: true }, CancellationToken.None).then(ranges => {
|
||||
assert.equal(ranges.length, 1);
|
||||
assert.ok(ranges[0].length >= 2);
|
||||
});
|
||||
|
||||
@@ -25,6 +25,10 @@ const emptyDialogService = new class implements IDialogService {
|
||||
about(): never {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
|
||||
input(): never {
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
};
|
||||
|
||||
const emptyCommandService: ICommandService = {
|
||||
|
||||
@@ -77,6 +77,7 @@ suite('NotebookCell#Document', function () {
|
||||
cellKind: CellKind.Code,
|
||||
outputs: [],
|
||||
}],
|
||||
contentOptions: { transientMetadata: {}, transientOutputs: false }
|
||||
}],
|
||||
addedEditors: [{
|
||||
documentUri: notebookUri,
|
||||
|
||||
@@ -68,6 +68,7 @@ suite('NotebookConcatDocument', function () {
|
||||
cellKind: CellKind.Markdown,
|
||||
outputs: [],
|
||||
}],
|
||||
contentOptions: { transientOutputs: false, transientMetadata: {} },
|
||||
versionId: 0
|
||||
}],
|
||||
addedEditors: [
|
||||
|
||||
310
src/vs/workbench/test/browser/api/extHostTesting.test.ts
Normal file
310
src/vs/workbench/test/browser/api/extHostTesting.test.ts
Normal file
@@ -0,0 +1,310 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { MirroredTestCollection, OwnedTestCollection, SingleUseTestCollection } from 'vs/workbench/api/common/extHostTesting';
|
||||
import * as convert from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { TestRunState, TestState } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { TestDiffOpType, TestsDiff } from 'vs/workbench/contrib/testing/common/testCollection';
|
||||
import { TestChangeEvent, TestItem } from 'vscode';
|
||||
|
||||
const stubTest = (label: string): TestItem => ({
|
||||
label,
|
||||
location: undefined,
|
||||
state: new TestState(TestRunState.Unset),
|
||||
debuggable: true,
|
||||
runnable: true,
|
||||
description: ''
|
||||
});
|
||||
|
||||
const simplify = (item: TestItem) => {
|
||||
if ('toJSON' in item) {
|
||||
item = (item as any).toJSON();
|
||||
}
|
||||
|
||||
return { ...item, children: undefined };
|
||||
};
|
||||
|
||||
const assertTreesEqual = (a: Readonly<TestItem>, b: Readonly<TestItem>) => {
|
||||
assert.deepStrictEqual(simplify(a), simplify(b));
|
||||
|
||||
const aChildren = (a.children ?? []).sort();
|
||||
const bChildren = (b.children ?? []).sort();
|
||||
assert.strictEqual(aChildren.length, bChildren.length, `expected ${a.label}.children.length == ${b.label}.children.length`);
|
||||
aChildren.forEach((_, i) => assertTreesEqual(aChildren[i], bChildren[i]));
|
||||
};
|
||||
|
||||
const assertTreeListEqual = (a: ReadonlyArray<Readonly<TestItem>>, b: ReadonlyArray<Readonly<TestItem>>) => {
|
||||
assert.strictEqual(a.length, b.length, `expected a.length == n.length`);
|
||||
a.forEach((_, i) => assertTreesEqual(a[i], b[i]));
|
||||
};
|
||||
|
||||
const stubNestedTests = () => ({
|
||||
...stubTest('root'),
|
||||
children: [
|
||||
{ ...stubTest('a'), children: [stubTest('aa'), stubTest('ab')] },
|
||||
stubTest('b'),
|
||||
]
|
||||
});
|
||||
|
||||
class TestOwnedTestCollection extends OwnedTestCollection {
|
||||
public get idToInternal() {
|
||||
return this.testIdToInternal;
|
||||
}
|
||||
|
||||
public createForHierarchy(publishDiff: (diff: TestsDiff) => void = () => undefined) {
|
||||
return new TestSingleUseCollection(this.testIdToInternal, publishDiff);
|
||||
}
|
||||
}
|
||||
|
||||
class TestSingleUseCollection extends SingleUseTestCollection {
|
||||
private idCounter = 0;
|
||||
|
||||
public get itemToInternal() {
|
||||
return this.testItemToInternal;
|
||||
}
|
||||
|
||||
public get currentDiff() {
|
||||
return this.diff;
|
||||
}
|
||||
|
||||
protected getId() {
|
||||
return String(this.idCounter++);
|
||||
}
|
||||
|
||||
public setDiff(diff: TestsDiff) {
|
||||
this.diff = diff;
|
||||
}
|
||||
}
|
||||
|
||||
class TestMirroredCollection extends MirroredTestCollection {
|
||||
public changeEvent!: TestChangeEvent;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.onDidChangeTests(evt => this.changeEvent = evt);
|
||||
}
|
||||
|
||||
public get length() {
|
||||
return this.items.size;
|
||||
}
|
||||
}
|
||||
|
||||
suite('ExtHost Testing', () => {
|
||||
let single: TestSingleUseCollection;
|
||||
let owned: TestOwnedTestCollection;
|
||||
setup(() => {
|
||||
owned = new TestOwnedTestCollection();
|
||||
single = owned.createForHierarchy(d => single.setDiff(d /* don't clear during testing */));
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
single.dispose();
|
||||
assert.deepEqual(owned.idToInternal.size, 0, 'expected owned ids to be empty after dispose');
|
||||
});
|
||||
|
||||
suite('OwnedTestCollection', () => {
|
||||
test('adds a root recursively', () => {
|
||||
const tests = stubNestedTests();
|
||||
single.addRoot(tests, 'pid');
|
||||
assert.deepStrictEqual(single.collectDiff(), [
|
||||
[TestDiffOpType.Add, { id: '0', providerId: 'pid', parent: null, item: convert.TestItem.from(stubTest('root')) }],
|
||||
[TestDiffOpType.Add, { id: '1', providerId: 'pid', parent: '0', item: convert.TestItem.from(stubTest('a')) }],
|
||||
[TestDiffOpType.Add, { id: '2', providerId: 'pid', parent: '1', item: convert.TestItem.from(stubTest('aa')) }],
|
||||
[TestDiffOpType.Add, { id: '3', providerId: 'pid', parent: '1', item: convert.TestItem.from(stubTest('ab')) }],
|
||||
[TestDiffOpType.Add, { id: '4', providerId: 'pid', parent: '0', item: convert.TestItem.from(stubTest('b')) }],
|
||||
]);
|
||||
});
|
||||
|
||||
test('no-ops if items not changed', () => {
|
||||
const tests = stubNestedTests();
|
||||
single.addRoot(tests, 'pid');
|
||||
single.collectDiff();
|
||||
assert.deepStrictEqual(single.collectDiff(), []);
|
||||
});
|
||||
|
||||
test('watches property mutations', () => {
|
||||
const tests = stubNestedTests();
|
||||
single.addRoot(tests, 'pid');
|
||||
single.collectDiff();
|
||||
tests.children![0].description = 'Hello world'; /* item a */
|
||||
single.onItemChange(tests, 'pid');
|
||||
assert.deepStrictEqual(single.collectDiff(), [
|
||||
[TestDiffOpType.Update, { id: '1', parent: '0', providerId: 'pid', item: convert.TestItem.from({ ...stubTest('a'), description: 'Hello world' }) }],
|
||||
]);
|
||||
|
||||
single.onItemChange(tests, 'pid');
|
||||
assert.deepStrictEqual(single.collectDiff(), []);
|
||||
});
|
||||
|
||||
test('removes children', () => {
|
||||
const tests = stubNestedTests();
|
||||
single.addRoot(tests, 'pid');
|
||||
single.collectDiff();
|
||||
tests.children!.splice(0, 1);
|
||||
single.onItemChange(tests, 'pid');
|
||||
|
||||
assert.deepStrictEqual(single.collectDiff(), [
|
||||
[TestDiffOpType.Remove, '1'],
|
||||
]);
|
||||
assert.deepStrictEqual([...owned.idToInternal.keys()].sort(), ['0', '4']);
|
||||
assert.strictEqual(single.itemToInternal.size, 2);
|
||||
});
|
||||
|
||||
test('adds new children', () => {
|
||||
const tests = stubNestedTests();
|
||||
single.addRoot(tests, 'pid');
|
||||
single.collectDiff();
|
||||
const child = stubTest('ac');
|
||||
tests.children![0].children!.push(child);
|
||||
single.onItemChange(tests, 'pid');
|
||||
|
||||
assert.deepStrictEqual(single.collectDiff(), [
|
||||
[TestDiffOpType.Add, { id: '5', providerId: 'pid', parent: '1', item: convert.TestItem.from(child) }],
|
||||
]);
|
||||
assert.deepStrictEqual([...owned.idToInternal.keys()].sort(), ['0', '1', '2', '3', '4', '5']);
|
||||
assert.strictEqual(single.itemToInternal.size, 6);
|
||||
});
|
||||
});
|
||||
|
||||
suite('MirroredTestCollection', () => {
|
||||
let m: TestMirroredCollection;
|
||||
setup(() => m = new TestMirroredCollection());
|
||||
|
||||
test('mirrors creation of the root', () => {
|
||||
const tests = stubNestedTests();
|
||||
single.addRoot(tests, 'pid');
|
||||
m.apply(single.collectDiff());
|
||||
assertTreesEqual(m.rootTestItems[0], owned.getTestById('0')!.actual);
|
||||
assert.strictEqual(m.length, single.itemToInternal.size);
|
||||
});
|
||||
|
||||
test('mirrors node deletion', () => {
|
||||
const tests = stubNestedTests();
|
||||
single.addRoot(tests, 'pid');
|
||||
m.apply(single.collectDiff());
|
||||
tests.children!.splice(0, 1);
|
||||
single.onItemChange(tests, 'pid');
|
||||
m.apply(single.collectDiff());
|
||||
|
||||
assertTreesEqual(m.rootTestItems[0], owned.getTestById('0')!.actual);
|
||||
assert.strictEqual(m.length, single.itemToInternal.size);
|
||||
});
|
||||
|
||||
test('mirrors node addition', () => {
|
||||
const tests = stubNestedTests();
|
||||
single.addRoot(tests, 'pid');
|
||||
m.apply(single.collectDiff());
|
||||
tests.children![0].children!.push(stubTest('ac'));
|
||||
single.onItemChange(tests, 'pid');
|
||||
m.apply(single.collectDiff());
|
||||
|
||||
assertTreesEqual(m.rootTestItems[0], owned.getTestById('0')!.actual);
|
||||
assert.strictEqual(m.length, single.itemToInternal.size);
|
||||
});
|
||||
|
||||
test('mirrors node update', () => {
|
||||
const tests = stubNestedTests();
|
||||
single.addRoot(tests, 'pid');
|
||||
m.apply(single.collectDiff());
|
||||
tests.children![0].description = 'Hello world'; /* item a */
|
||||
single.onItemChange(tests, 'pid');
|
||||
m.apply(single.collectDiff());
|
||||
|
||||
assertTreesEqual(m.rootTestItems[0], owned.getTestById('0')!.actual);
|
||||
});
|
||||
|
||||
suite('MirroredChangeCollector', () => {
|
||||
let tests = stubNestedTests();
|
||||
setup(() => {
|
||||
tests = stubNestedTests();
|
||||
single.addRoot(tests, 'pid');
|
||||
m.apply(single.collectDiff());
|
||||
});
|
||||
|
||||
test('creates change for root', () => {
|
||||
assert.deepStrictEqual(m.changeEvent.commonChangeAncestor, null);
|
||||
assertTreeListEqual(m.changeEvent.added, [
|
||||
tests,
|
||||
tests.children[0],
|
||||
tests.children![0].children![0],
|
||||
tests.children![0].children![1],
|
||||
tests.children[1],
|
||||
]);
|
||||
assertTreeListEqual(m.changeEvent.removed, []);
|
||||
assertTreeListEqual(m.changeEvent.updated, []);
|
||||
});
|
||||
|
||||
test('creates change for delete', () => {
|
||||
const rm = tests.children.shift()!;
|
||||
single.onItemChange(tests, 'pid');
|
||||
m.apply(single.collectDiff());
|
||||
|
||||
assertTreesEqual(m.changeEvent.commonChangeAncestor!, tests);
|
||||
assertTreeListEqual(m.changeEvent.added, []);
|
||||
assertTreeListEqual(m.changeEvent.removed, [
|
||||
{ ...rm, children: [] },
|
||||
{ ...rm.children![0], children: [] },
|
||||
{ ...rm.children![1], children: [] },
|
||||
]);
|
||||
assertTreeListEqual(m.changeEvent.updated, []);
|
||||
});
|
||||
|
||||
test('creates change for update', () => {
|
||||
tests.children[0].label = 'updated!';
|
||||
single.onItemChange(tests, 'pid');
|
||||
m.apply(single.collectDiff());
|
||||
|
||||
assert.deepStrictEqual(m.changeEvent.commonChangeAncestor?.label, 'updated!');
|
||||
assertTreeListEqual(m.changeEvent.added, []);
|
||||
assertTreeListEqual(m.changeEvent.removed, []);
|
||||
assertTreeListEqual(m.changeEvent.updated, [tests.children[0]]);
|
||||
});
|
||||
|
||||
test('is a no-op if a node is added and removed', () => {
|
||||
const nested = stubNestedTests();
|
||||
tests.children.push(nested);
|
||||
single.onItemChange(tests, 'pid');
|
||||
tests.children.pop();
|
||||
single.onItemChange(tests, 'pid');
|
||||
const previousEvent = m.changeEvent;
|
||||
m.apply(single.collectDiff());
|
||||
assert.strictEqual(m.changeEvent, previousEvent);
|
||||
});
|
||||
|
||||
test('is a single-op if a node is added and changed', () => {
|
||||
const child = stubTest('c');
|
||||
tests.children.push(child);
|
||||
single.onItemChange(tests, 'pid');
|
||||
child.label = 'd';
|
||||
single.onItemChange(tests, 'pid');
|
||||
m.apply(single.collectDiff());
|
||||
|
||||
assert.strictEqual(m.changeEvent.commonChangeAncestor?.label, 'root');
|
||||
assertTreeListEqual(m.changeEvent.added, [child]);
|
||||
assertTreeListEqual(m.changeEvent.removed, []);
|
||||
assertTreeListEqual(m.changeEvent.updated, []);
|
||||
});
|
||||
|
||||
test('gets the common ancestor (1)', () => {
|
||||
tests.children![0].children![0].label = 'za';
|
||||
tests.children![0].children![1].label = 'zb';
|
||||
single.onItemChange(tests, 'pid');
|
||||
m.apply(single.collectDiff());
|
||||
|
||||
assert.strictEqual(m.changeEvent.commonChangeAncestor?.label, 'a');
|
||||
});
|
||||
|
||||
test('gets the common ancestor (2)', () => {
|
||||
tests.children![0].children![0].label = 'za';
|
||||
tests.children![1].label = 'ab';
|
||||
single.onItemChange(tests, 'pid');
|
||||
m.apply(single.collectDiff());
|
||||
|
||||
assert.strictEqual(m.changeEvent.commonChangeAncestor?.label, 'root');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -488,41 +488,53 @@ suite.skip('ExtHostTreeView', function () {
|
||||
test('reveal will return empty array for root element', () => {
|
||||
const revealTarget = sinon.spy(target, '$reveal');
|
||||
const treeView = testObject.createTreeView('treeDataProvider', { treeDataProvider: aCompleteNodeTreeDataProvider() }, { enableProposedApi: true } as IExtensionDescription);
|
||||
const expected = {
|
||||
item:
|
||||
{ handle: '0/0:a', label: { label: 'a' }, collapsibleState: TreeItemCollapsibleState.Collapsed },
|
||||
parentChain: []
|
||||
};
|
||||
return treeView.reveal({ key: 'a' })
|
||||
.then(() => {
|
||||
assert.ok(revealTarget.calledOnce);
|
||||
assert.deepEqual('treeDataProvider', revealTarget.args[0][0]);
|
||||
assert.deepEqual({ handle: '0/0:a', label: { label: 'a' }, collapsibleState: TreeItemCollapsibleState.Collapsed }, removeUnsetKeys(revealTarget.args[0][1]));
|
||||
assert.deepEqual([], revealTarget.args[0][2]);
|
||||
assert.deepEqual({ select: true, focus: false, expand: false }, revealTarget.args[0][3]);
|
||||
assert.deepEqual(expected, removeUnsetKeys(revealTarget.args[0][1]));
|
||||
assert.deepEqual({ select: true, focus: false, expand: false }, revealTarget.args[0][2]);
|
||||
});
|
||||
});
|
||||
|
||||
test('reveal will return parents array for an element when hierarchy is not loaded', () => {
|
||||
const revealTarget = sinon.spy(target, '$reveal');
|
||||
const treeView = testObject.createTreeView('treeDataProvider', { treeDataProvider: aCompleteNodeTreeDataProvider() }, { enableProposedApi: true } as IExtensionDescription);
|
||||
const expected = {
|
||||
item: { handle: '0/0:a/0:aa', label: { label: 'aa' }, collapsibleState: TreeItemCollapsibleState.None, parentHandle: '0/0:a' },
|
||||
parentChain: [{ handle: '0/0:a', label: { label: 'a' }, collapsibleState: TreeItemCollapsibleState.Collapsed }]
|
||||
};
|
||||
return treeView.reveal({ key: 'aa' })
|
||||
.then(() => {
|
||||
assert.ok(revealTarget.calledOnce);
|
||||
assert.deepEqual('treeDataProvider', revealTarget.args[0][0]);
|
||||
assert.deepEqual({ handle: '0/0:a/0:aa', label: { label: 'aa' }, collapsibleState: TreeItemCollapsibleState.None, parentHandle: '0/0:a' }, removeUnsetKeys(revealTarget.args[0][1]));
|
||||
assert.deepEqual([{ handle: '0/0:a', label: { label: 'a' }, collapsibleState: TreeItemCollapsibleState.Collapsed }], (<Array<any>>revealTarget.args[0][2]).map(arg => removeUnsetKeys(arg)));
|
||||
assert.deepEqual({ select: true, focus: false, expand: false }, revealTarget.args[0][3]);
|
||||
assert.deepEqual(expected.item, removeUnsetKeys(revealTarget.args[0][1].item));
|
||||
assert.deepEqual(expected.parentChain, (<Array<any>>(revealTarget.args[0][1].parentChain)).map(arg => removeUnsetKeys(arg)));
|
||||
assert.deepEqual({ select: true, focus: false, expand: false }, revealTarget.args[0][2]);
|
||||
});
|
||||
});
|
||||
|
||||
test('reveal will return parents array for an element when hierarchy is loaded', () => {
|
||||
const revealTarget = sinon.spy(target, '$reveal');
|
||||
const treeView = testObject.createTreeView('treeDataProvider', { treeDataProvider: aCompleteNodeTreeDataProvider() }, { enableProposedApi: true } as IExtensionDescription);
|
||||
const expected = {
|
||||
item: { handle: '0/0:a/0:aa', label: { label: 'aa' }, collapsibleState: TreeItemCollapsibleState.None, parentHandle: '0/0:a' },
|
||||
parentChain: [{ handle: '0/0:a', label: { label: 'a' }, collapsibleState: TreeItemCollapsibleState.Collapsed }]
|
||||
};
|
||||
return testObject.$getChildren('treeDataProvider')
|
||||
.then(() => testObject.$getChildren('treeDataProvider', '0/0:a'))
|
||||
.then(() => treeView.reveal({ key: 'aa' })
|
||||
.then(() => {
|
||||
assert.ok(revealTarget.calledOnce);
|
||||
assert.deepEqual('treeDataProvider', revealTarget.args[0][0]);
|
||||
assert.deepEqual({ handle: '0/0:a/0:aa', label: { label: 'aa' }, collapsibleState: TreeItemCollapsibleState.None, parentHandle: '0/0:a' }, removeUnsetKeys(revealTarget.args[0][1]));
|
||||
assert.deepEqual([{ handle: '0/0:a', label: { label: 'a' }, collapsibleState: TreeItemCollapsibleState.Collapsed }], (<Array<any>>revealTarget.args[0][2]).map(arg => removeUnsetKeys(arg)));
|
||||
assert.deepEqual({ select: true, focus: false, expand: false }, revealTarget.args[0][3]);
|
||||
assert.deepEqual(expected.item, removeUnsetKeys(revealTarget.args[0][1].item));
|
||||
assert.deepEqual(expected.parentChain, (<Array<any>>(revealTarget.args[0][1].parentChain)).map(arg => removeUnsetKeys(arg)));
|
||||
assert.deepEqual({ select: true, focus: false, expand: false }, revealTarget.args[0][2]);
|
||||
}));
|
||||
});
|
||||
|
||||
@@ -536,22 +548,30 @@ suite.skip('ExtHostTreeView', function () {
|
||||
};
|
||||
const revealTarget = sinon.spy(target, '$reveal');
|
||||
const treeView = testObject.createTreeView('treeDataProvider', { treeDataProvider: aCompleteNodeTreeDataProvider() }, { enableProposedApi: true } as IExtensionDescription);
|
||||
const expected = {
|
||||
item: { handle: '0/0:b/0:ba/0:bac', label: { label: 'bac' }, collapsibleState: TreeItemCollapsibleState.None, parentHandle: '0/0:b/0:ba' },
|
||||
parentChain: [
|
||||
{ handle: '0/0:b', label: { label: 'b' }, collapsibleState: TreeItemCollapsibleState.Collapsed },
|
||||
{ handle: '0/0:b/0:ba', label: { label: 'ba' }, collapsibleState: TreeItemCollapsibleState.Collapsed, parentHandle: '0/0:b' }
|
||||
]
|
||||
};
|
||||
return treeView.reveal({ key: 'bac' }, { select: false, focus: false, expand: false })
|
||||
.then(() => {
|
||||
assert.ok(revealTarget.calledOnce);
|
||||
assert.deepEqual('treeDataProvider', revealTarget.args[0][0]);
|
||||
assert.deepEqual({ handle: '0/0:b/0:ba/0:bac', label: { label: 'bac' }, collapsibleState: TreeItemCollapsibleState.None, parentHandle: '0/0:b/0:ba' }, removeUnsetKeys(revealTarget.args[0][1]));
|
||||
assert.deepEqual([
|
||||
{ handle: '0/0:b', label: { label: 'b' }, collapsibleState: TreeItemCollapsibleState.Collapsed },
|
||||
{ handle: '0/0:b/0:ba', label: { label: 'ba' }, collapsibleState: TreeItemCollapsibleState.Collapsed, parentHandle: '0/0:b' }
|
||||
], (<Array<any>>revealTarget.args[0][2]).map(arg => removeUnsetKeys(arg)));
|
||||
assert.deepEqual({ select: false, focus: false, expand: false }, revealTarget.args[0][3]);
|
||||
assert.deepEqual(expected.item, removeUnsetKeys(revealTarget.args[0][1].item));
|
||||
assert.deepEqual(expected.parentChain, (<Array<any>>(revealTarget.args[0][1].parentChain)).map(arg => removeUnsetKeys(arg)));
|
||||
assert.deepEqual({ select: false, focus: false, expand: false }, revealTarget.args[0][2]);
|
||||
});
|
||||
});
|
||||
|
||||
test('reveal after first udpate', () => {
|
||||
const revealTarget = sinon.spy(target, '$reveal');
|
||||
const treeView = testObject.createTreeView('treeDataProvider', { treeDataProvider: aCompleteNodeTreeDataProvider() }, { enableProposedApi: true } as IExtensionDescription);
|
||||
const expected = {
|
||||
item: { handle: '0/0:a/0:ac', label: { label: 'ac' }, collapsibleState: TreeItemCollapsibleState.None, parentHandle: '0/0:a' },
|
||||
parentChain: [{ handle: '0/0:a', label: { label: 'a' }, collapsibleState: TreeItemCollapsibleState.Collapsed }]
|
||||
};
|
||||
return loadCompleteTree('treeDataProvider')
|
||||
.then(() => {
|
||||
tree = {
|
||||
@@ -570,9 +590,9 @@ suite.skip('ExtHostTreeView', function () {
|
||||
.then(() => {
|
||||
assert.ok(revealTarget.calledOnce);
|
||||
assert.deepEqual('treeDataProvider', revealTarget.args[0][0]);
|
||||
assert.deepEqual({ handle: '0/0:a/0:ac', label: { label: 'ac' }, collapsibleState: TreeItemCollapsibleState.None, parentHandle: '0/0:a' }, removeUnsetKeys(revealTarget.args[0][1]));
|
||||
assert.deepEqual([{ handle: '0/0:a', label: { label: 'a' }, collapsibleState: TreeItemCollapsibleState.Collapsed }], (<Array<any>>revealTarget.args[0][2]).map(arg => removeUnsetKeys(arg)));
|
||||
assert.deepEqual({ select: true, focus: false, expand: false }, revealTarget.args[0][3]);
|
||||
assert.deepEqual(expected.item, removeUnsetKeys(revealTarget.args[0][1].item));
|
||||
assert.deepEqual(expected.parentChain, (<Array<any>>(revealTarget.args[0][1].parentChain)).map(arg => removeUnsetKeys(arg)));
|
||||
assert.deepEqual({ select: true, focus: false, expand: false }, revealTarget.args[0][2]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,10 +5,9 @@
|
||||
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { MarkdownString, LogLevel } from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { MarkdownString } from 'vs/workbench/api/common/extHostTypeConverters';
|
||||
import { isEmptyObject } from 'vs/base/common/types';
|
||||
import { forEach } from 'vs/base/common/collections';
|
||||
import * as types from 'vs/workbench/api/common/extHostTypes';
|
||||
import { LogLevel as _MainLogLevel } from 'vs/platform/log/common/log';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
||||
@@ -82,14 +81,4 @@ suite('ExtHostTypeConverter', function () {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test('LogLevel', () => {
|
||||
assert.equal(LogLevel.from(types.LogLevel.Error), _MainLogLevel.Error);
|
||||
assert.equal(LogLevel.from(types.LogLevel.Info), _MainLogLevel.Info);
|
||||
assert.equal(LogLevel.from(types.LogLevel.Off), _MainLogLevel.Off);
|
||||
|
||||
assert.equal(LogLevel.to(_MainLogLevel.Error), types.LogLevel.Error);
|
||||
assert.equal(LogLevel.to(_MainLogLevel.Info), types.LogLevel.Info);
|
||||
assert.equal(LogLevel.to(_MainLogLevel.Off), types.LogLevel.Off);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -524,6 +524,10 @@ suite('ExtHostTypes', function () {
|
||||
string.appendChoice(['b', 'a', 'r']);
|
||||
assert.equal(string.value, '${1|b,a,r|}');
|
||||
|
||||
string = new types.SnippetString();
|
||||
string.appendChoice(['b,1', 'a,2', 'r,3']);
|
||||
assert.equal(string.value, '${1|b\\,1,a\\,2,r\\,3|}');
|
||||
|
||||
string = new types.SnippetString();
|
||||
string.appendChoice(['b', 'a', 'r'], 0);
|
||||
assert.equal(string.value, '${0|b,a,r|}');
|
||||
|
||||
@@ -14,7 +14,7 @@ import { NullApiDeprecationService } from 'vs/workbench/api/common/extHostApiDep
|
||||
import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { ExtHostWebviews } from 'vs/workbench/api/common/extHostWebview';
|
||||
import { ExtHostWebviewPanels } from 'vs/workbench/api/common/extHostWebviewPanels';
|
||||
import { EditorViewColumn } from 'vs/workbench/api/common/shared/editor';
|
||||
import { EditorGroupColumn } from 'vs/workbench/common/editor';
|
||||
import type * as vscode from 'vscode';
|
||||
import { SingleProxyRPCProtocol } from './testRPCProtocol';
|
||||
|
||||
@@ -53,7 +53,7 @@ suite('ExtHostWebview', () => {
|
||||
|
||||
const serializerARegistration = extHostWebviewPanels.registerWebviewPanelSerializer(extension, viewType, serializerA);
|
||||
|
||||
await extHostWebviewPanels.$deserializeWebviewPanel('x', viewType, 'title', {}, 0 as EditorViewColumn, {});
|
||||
await extHostWebviewPanels.$deserializeWebviewPanel('x', viewType, 'title', {}, 0 as EditorGroupColumn, {});
|
||||
assert.strictEqual(lastInvokedDeserializer, serializerA);
|
||||
|
||||
assert.throws(
|
||||
@@ -64,7 +64,7 @@ suite('ExtHostWebview', () => {
|
||||
|
||||
extHostWebviewPanels.registerWebviewPanelSerializer(extension, viewType, serializerB);
|
||||
|
||||
await extHostWebviewPanels.$deserializeWebviewPanel('x', viewType, 'title', {}, 0 as EditorViewColumn, {});
|
||||
await extHostWebviewPanels.$deserializeWebviewPanel('x', viewType, 'title', {}, 0 as EditorGroupColumn, {});
|
||||
assert.strictEqual(lastInvokedDeserializer, serializerB);
|
||||
});
|
||||
|
||||
|
||||
@@ -20,13 +20,16 @@ import { ExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
import { ITextQueryBuilderOptions } from 'vs/workbench/contrib/search/common/queryBuilder';
|
||||
import { IPatternInfo } from 'vs/workbench/services/search/common/search';
|
||||
import { isWindows } from 'vs/base/common/platform';
|
||||
import { isLinux, isWindows } from 'vs/base/common/platform';
|
||||
import { IExtHostFileSystemInfo } from 'vs/workbench/api/common/extHostFileSystemInfo';
|
||||
import { FileSystemProviderCapabilities } from 'vs/platform/files/common/files';
|
||||
|
||||
function createExtHostWorkspace(mainContext: IMainContext, data: IWorkspaceData, logService: ILogService): ExtHostWorkspace {
|
||||
const result = new ExtHostWorkspace(
|
||||
new ExtHostRpcService(mainContext),
|
||||
new class extends mock<IExtHostInitDataService>() { workspace = data; },
|
||||
logService
|
||||
new class extends mock<IExtHostFileSystemInfo>() { getCapabilities() { return isLinux ? FileSystemProviderCapabilities.PathCaseSensitive : undefined; } },
|
||||
logService,
|
||||
);
|
||||
result.$initializeWorkspace(data);
|
||||
return result;
|
||||
@@ -42,6 +45,7 @@ suite('ExtHostWorkspace', function () {
|
||||
engines: undefined!,
|
||||
extensionLocation: undefined!,
|
||||
isBuiltin: false,
|
||||
isUserBuiltin: false,
|
||||
isUnderDevelopment: false,
|
||||
version: undefined!
|
||||
};
|
||||
@@ -601,7 +605,7 @@ suite('ExtHostWorkspace', function () {
|
||||
});
|
||||
});
|
||||
|
||||
test('findFiles - RelativePattern include', () => {
|
||||
function testFindFilesInclude(pattern: RelativePattern) {
|
||||
const root = '/project/foo';
|
||||
const rpcProtocol = new TestRPCProtocol();
|
||||
|
||||
@@ -610,16 +614,24 @@ suite('ExtHostWorkspace', function () {
|
||||
$startFileSearch(includePattern: string, _includeFolder: UriComponents | null, excludePatternOrDisregardExcludes: string | false, maxResults: number, token: CancellationToken): Promise<URI[] | null> {
|
||||
mainThreadCalled = true;
|
||||
assert.equal(includePattern, 'glob/**');
|
||||
assert.deepEqual(_includeFolder, URI.file('/other/folder').toJSON());
|
||||
assert.deepEqual(_includeFolder ? URI.from(_includeFolder).toJSON() : null, URI.file('/other/folder').toJSON());
|
||||
assert.equal(excludePatternOrDisregardExcludes, null);
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
});
|
||||
|
||||
const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService());
|
||||
return ws.findFiles(new RelativePattern('/other/folder', 'glob/**'), undefined, 10, new ExtensionIdentifier('test')).then(() => {
|
||||
return ws.findFiles(pattern, undefined, 10, new ExtensionIdentifier('test')).then(() => {
|
||||
assert(mainThreadCalled, 'mainThreadCalled');
|
||||
});
|
||||
}
|
||||
|
||||
test('findFiles - RelativePattern include (string)', () => {
|
||||
return testFindFilesInclude(new RelativePattern('/other/folder', 'glob/**'));
|
||||
});
|
||||
|
||||
test('findFiles - RelativePattern include (URI)', () => {
|
||||
return testFindFilesInclude(new RelativePattern(URI.file('/other/folder'), 'glob/**'));
|
||||
});
|
||||
|
||||
test('findFiles - no excludes', () => {
|
||||
|
||||
@@ -15,8 +15,8 @@ import { TestNotificationService } from 'vs/platform/notification/test/common/te
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { CustomTreeView } from 'vs/workbench/contrib/views/browser/treeView';
|
||||
import { ViewDescriptorService } from 'vs/workbench/services/views/browser/viewDescriptorService';
|
||||
import { CustomTreeView } from 'vs/workbench/browser/parts/views/treeView';
|
||||
|
||||
suite('MainThreadHostTreeView', function () {
|
||||
const testTreeViewId = 'testTreeView';
|
||||
|
||||
Reference in New Issue
Block a user