diff --git a/src/vs/base/test/browser/dom.test.ts b/src/vs/base/test/browser/dom.test.ts index c19a785476..96c6cbbadd 100644 --- a/src/vs/base/test/browser/dom.test.ts +++ b/src/vs/base/test/browser/dom.test.ts @@ -7,11 +7,83 @@ import * as assert from 'assert'; import * as dom from 'vs/base/browser/dom'; const $ = dom.$; -// {{SQL CARBON EDIT}} disable broken tests suite('dom', () => { - test('hasClass', () => { + test.skip('hasClass', () => { //{{SQL CARBON EDIT}} skip test + + let element = document.createElement('div'); + element.className = 'foobar boo far'; + + assert(dom.hasClass(element, 'foobar')); + assert(dom.hasClass(element, 'boo')); + assert(dom.hasClass(element, 'far')); + assert(!dom.hasClass(element, 'bar')); + assert(!dom.hasClass(element, 'foo')); + assert(!dom.hasClass(element, '')); }); + test.skip('removeClass', () => { //{{SQL CARBON EDIT}} skip test + + let element = document.createElement('div'); + element.className = 'foobar boo far'; + + dom.removeClass(element, 'boo'); + assert(dom.hasClass(element, 'far')); + assert(!dom.hasClass(element, 'boo')); + assert(dom.hasClass(element, 'foobar')); + assert.equal(element.className, 'foobar far'); + + element = document.createElement('div'); + element.className = 'foobar boo far'; + + dom.removeClass(element, 'far'); + assert(!dom.hasClass(element, 'far')); + assert(dom.hasClass(element, 'boo')); + assert(dom.hasClass(element, 'foobar')); + assert.equal(element.className, 'foobar boo'); + + dom.removeClass(element, 'boo'); + assert(!dom.hasClass(element, 'far')); + assert(!dom.hasClass(element, 'boo')); + assert(dom.hasClass(element, 'foobar')); + assert.equal(element.className, 'foobar'); + + dom.removeClass(element, 'foobar'); + assert(!dom.hasClass(element, 'far')); + assert(!dom.hasClass(element, 'boo')); + assert(!dom.hasClass(element, 'foobar')); + assert.equal(element.className, ''); + }); + + test.skip('removeClass should consider hyphens', function () { //{{SQL CARBON EDIT}} skip test + let element = document.createElement('div'); + + dom.addClass(element, 'foo-bar'); + dom.addClass(element, 'bar'); + + assert(dom.hasClass(element, 'foo-bar')); + assert(dom.hasClass(element, 'bar')); + + dom.removeClass(element, 'bar'); + assert(dom.hasClass(element, 'foo-bar')); + assert(!dom.hasClass(element, 'bar')); + + dom.removeClass(element, 'foo-bar'); + assert(!dom.hasClass(element, 'foo-bar')); + assert(!dom.hasClass(element, 'bar')); + }); + + //test('[perf] hasClass * 100000', () => { + // + // for (let i = 0; i < 100000; i++) { + // let element = document.createElement('div'); + // element.className = 'foobar boo far'; + // + // assert(dom.hasClass(element, 'far')); + // assert(dom.hasClass(element, 'boo')); + // assert(dom.hasClass(element, 'foobar')); + // } + //}); + suite('$', () => { test('should build simple nodes', () => { const div = $('div'); diff --git a/src/vs/code/electron-browser/issue/test/testReporterModel.test.ts b/src/vs/code/electron-browser/issue/test/testReporterModel.test.ts index 1bc1a0d9cb..678b54455e 100644 --- a/src/vs/code/electron-browser/issue/test/testReporterModel.test.ts +++ b/src/vs/code/electron-browser/issue/test/testReporterModel.test.ts @@ -24,8 +24,7 @@ suite('IssueReporter', () => { }); }); - // {{SQL CARBON EDIT}} - test('serializes model skeleton when no data is provided', () => { + test('serializes model skeleton when no data is provided', () => { // {{SQL CARBON EDIT}} modify test for ads const issueReporterModel = new IssueReporterModel({}); assert.equal(issueReporterModel.serialize(), ` @@ -40,7 +39,7 @@ Extensions: none `); }); - test('serializes GPU information when data is provided', () => { + test('serializes GPU information when data is provided', () => { // {{SQL CARBON EDIT}} modify test for ads const issueReporterModel = new IssueReporterModel({ issueType: 0, systemInfo: { @@ -58,7 +57,6 @@ Extensions: none } }); assert.equal(issueReporterModel.serialize(), - // {{SQL CARBON EDIT}} ` Issue Type: Bug @@ -83,7 +81,66 @@ OS version: undefined `); }); - // {{SQL CARBON EDIT}} - remove VS Code test that isn't valid in ADS context + test.skip('serializes remote information when data is provided', () => { //{{SQL CARBON EDIT}} skip test + const issueReporterModel = new IssueReporterModel({ + issueType: 0, + systemInfo: { + os: 'Darwin', + cpus: 'Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz (8 x 2800)', + memory: '16.00GB', + vmHint: '0%', + processArgs: '', + screenReader: 'no', + gpuStatus: { + '2d_canvas': 'enabled', + 'checker_imaging': 'disabled_off' + }, + remoteData: [ + { + hostName: 'SSH: Pineapple', + machineInfo: { + os: 'Linux x64 4.18.0', + cpus: 'Intel(R) Xeon(R) CPU E5-2673 v4 @ 2.30GHz (2 x 2294)', + memory: '8GB', + vmHint: '100%' + } + } + ] + } + }); + assert.equal(issueReporterModel.serialize(), + ` +Issue Type: Bug + +undefined + +VS Code version: undefined +OS version: undefined +Remote OS version: Linux x64 4.18.0 + +
+System Info + +|Item|Value| +|---|---| +|CPUs|Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz (8 x 2800)| +|GPU Status|2d_canvas: enabled
checker_imaging: disabled_off| +|Load (avg)|undefined| +|Memory (System)|16.00GB| +|Process Argv|| +|Screen Reader|no| +|VM|0%| + +|Item|Value| +|---|---| +|Remote|SSH: Pineapple| +|OS|Linux x64 4.18.0| +|CPUs|Intel(R) Xeon(R) CPU E5-2673 v4 @ 2.30GHz (2 x 2294)| +|Memory (System)|8GB| +|VM|100%| +
Extensions: none +`); + }); test('should normalize GitHub urls', () => { [ diff --git a/src/vs/editor/test/browser/services/decorationRenderOptions.test.ts b/src/vs/editor/test/browser/services/decorationRenderOptions.test.ts index 87e4c4f003..40a1ca784f 100644 --- a/src/vs/editor/test/browser/services/decorationRenderOptions.test.ts +++ b/src/vs/editor/test/browser/services/decorationRenderOptions.test.ts @@ -14,9 +14,167 @@ import { TestTheme, TestThemeService } from 'vs/platform/theme/test/common/testT const themeServiceMock = new TestThemeService(); -// {{SQL CARBON EDIT}} - Remove exported test class -suite('Decoration Render Options', () => { +export class TestCodeEditorServiceImpl extends CodeEditorServiceImpl { + getActiveCodeEditor(): ICodeEditor | null { + return null; + } + + openCodeEditor(input: IResourceInput, source: ICodeEditor | null, sideBySide?: boolean): Promise { + return Promise.resolve(null); + } +} + +suite.skip('Decoration Render Options', () => { // {{SQL CARBON EDIT}} skip suite + let options: IDecorationRenderOptions = { + gutterIconPath: URI.parse('https://github.com/Microsoft/vscode/blob/master/resources/linux/code.png'), + gutterIconSize: 'contain', + backgroundColor: 'red', + borderColor: 'yellow' + }; test('register and resolve decoration type', () => { - // {{SQL CARBON EDIT}} - Remove test + let s = new TestCodeEditorServiceImpl(themeServiceMock); + s.registerDecorationType('example', options); + assert.notEqual(s.resolveDecorationOptions('example', false), undefined); + }); + test('remove decoration type', () => { + let s = new TestCodeEditorServiceImpl(themeServiceMock); + s.registerDecorationType('example', options); + assert.notEqual(s.resolveDecorationOptions('example', false), undefined); + s.removeDecorationType('example'); + assert.throws(() => s.resolveDecorationOptions('example', false)); + }); + + function readStyleSheet(styleSheet: HTMLStyleElement): string { + if ((styleSheet.sheet).rules) { + return Array.prototype.map.call((styleSheet.sheet).rules, (r: { cssText: string }) => r.cssText).join('\n'); + } + return styleSheet.sheet!.toString(); + } + + test('css properties', () => { + let styleSheet = dom.createStyleSheet(); + let s = new TestCodeEditorServiceImpl(themeServiceMock, styleSheet); + s.registerDecorationType('example', options); + let sheet = readStyleSheet(styleSheet); + assert( + sheet.indexOf('background: url(\'https://github.com/Microsoft/vscode/blob/master/resources/linux/code.png\') center center no-repeat;') > 0 + || sheet.indexOf('background: url("https://github.com/Microsoft/vscode/blob/master/resources/linux/code.png") center center / contain no-repeat;') > 0 + ); + assert(sheet.indexOf('border-color: yellow;') > 0); + assert(sheet.indexOf('background-color: red;') > 0); + }); + + test('theme color', () => { + let options: IDecorationRenderOptions = { + backgroundColor: { id: 'editorBackground' }, + borderColor: { id: 'editorBorder' }, + }; + let colors: { [key: string]: string } = { + editorBackground: '#FF0000' + }; + + let styleSheet = dom.createStyleSheet(); + let themeService = new TestThemeService(new TestTheme(colors)); + let s = new TestCodeEditorServiceImpl(themeService, styleSheet); + s.registerDecorationType('example', options); + let sheet = readStyleSheet(styleSheet); + assert.equal(sheet, '.monaco-editor .ced-example-0 { background-color: rgb(255, 0, 0); border-color: transparent; box-sizing: border-box; }'); + + colors = { + editorBackground: '#EE0000', + editorBorder: '#00FFFF' + }; + themeService.setTheme(new TestTheme(colors)); + sheet = readStyleSheet(styleSheet); + assert.equal(sheet, '.monaco-editor .ced-example-0 { background-color: rgb(238, 0, 0); border-color: rgb(0, 255, 255); box-sizing: border-box; }'); + + s.removeDecorationType('example'); + sheet = readStyleSheet(styleSheet); + assert.equal(sheet, ''); + + }); + + test('theme overrides', () => { + let options: IDecorationRenderOptions = { + color: { id: 'editorBackground' }, + light: { + color: '#FF00FF' + }, + dark: { + color: '#000000', + after: { + color: { id: 'infoForeground' } + } + } + }; + let colors: { [key: string]: string } = { + editorBackground: '#FF0000', + infoForeground: '#444444' + }; + + let styleSheet = dom.createStyleSheet(); + let themeService = new TestThemeService(new TestTheme(colors)); + let s = new TestCodeEditorServiceImpl(themeService, styleSheet); + s.registerDecorationType('example', options); + let sheet = readStyleSheet(styleSheet); + let expected = + '.vs-dark.monaco-editor .ced-example-4::after, .hc-black.monaco-editor .ced-example-4::after { color: rgb(68, 68, 68) !important; }\n' + + '.vs-dark.monaco-editor .ced-example-1, .hc-black.monaco-editor .ced-example-1 { color: rgb(0, 0, 0) !important; }\n' + + '.vs.monaco-editor .ced-example-1 { color: rgb(255, 0, 255) !important; }\n' + + '.monaco-editor .ced-example-1 { color: rgb(255, 0, 0) !important; }'; + assert.equal(sheet, expected); + + s.removeDecorationType('example'); + sheet = readStyleSheet(styleSheet); + assert.equal(sheet, ''); + }); + + test('css properties, gutterIconPaths', () => { + let styleSheet = dom.createStyleSheet(); + + // unix file path (used as string) + let s = new TestCodeEditorServiceImpl(themeServiceMock, styleSheet); + s.registerDecorationType('example', { gutterIconPath: URI.file('/Users/foo/bar.png') }); + let sheet = readStyleSheet(styleSheet);//.innerHTML || styleSheet.sheet.toString(); + assert( + sheet.indexOf('background: url(\'file:///Users/foo/bar.png\') center center no-repeat;') > 0 + || sheet.indexOf('background: url("file:///Users/foo/bar.png") center center no-repeat;') > 0 + ); + + // windows file path (used as string) + s = new TestCodeEditorServiceImpl(themeServiceMock, styleSheet); + s.registerDecorationType('example', { gutterIconPath: URI.file('c:\\files\\miles\\more.png') }); + sheet = readStyleSheet(styleSheet); + // TODO@Alex test fails + // assert( + // sheet.indexOf('background: url(\'file:///c%3A/files/miles/more.png\') center center no-repeat;') > 0 + // || sheet.indexOf('background: url("file:///c%3A/files/miles/more.png") center center no-repeat;') > 0 + // ); + + // URI, only minimal encoding + s = new TestCodeEditorServiceImpl(themeServiceMock, styleSheet); + s.registerDecorationType('example', { gutterIconPath: URI.parse('data:image/svg+xml;base64,PHN2ZyB4b+') }); + sheet = readStyleSheet(styleSheet); + assert( + sheet.indexOf('background: url(\'data:image/svg+xml;base64,PHN2ZyB4b+\') center center no-repeat;') > 0 + || sheet.indexOf('background: url("data:image/svg+xml;base64,PHN2ZyB4b+") center center no-repeat;') > 0 + ); + + // single quote must always be escaped/encoded + s = new TestCodeEditorServiceImpl(themeServiceMock, styleSheet); + s.registerDecorationType('example', { gutterIconPath: URI.file('/Users/foo/b\'ar.png') }); + sheet = readStyleSheet(styleSheet); + assert( + sheet.indexOf('background: url(\'file:///Users/foo/b%27ar.png\') center center no-repeat;') > 0 + || sheet.indexOf('background: url("file:///Users/foo/b%27ar.png") center center no-repeat;') > 0 + ); + + s = new TestCodeEditorServiceImpl(themeServiceMock, styleSheet); + s.registerDecorationType('example', { gutterIconPath: URI.parse('http://test/pa\'th') }); + sheet = readStyleSheet(styleSheet); + assert( + sheet.indexOf('background: url(\'http://test/pa%27th\') center center no-repeat;') > 0 + || sheet.indexOf('background: url("http://test/pa%27th") center center no-repeat;') > 0 + ); }); }); diff --git a/src/vs/editor/test/common/config/commonEditorConfig.test.ts b/src/vs/editor/test/common/config/commonEditorConfig.test.ts index 4fe98286da..a6ff4ca63d 100644 --- a/src/vs/editor/test/common/config/commonEditorConfig.test.ts +++ b/src/vs/editor/test/common/config/commonEditorConfig.test.ts @@ -87,16 +87,14 @@ suite('Common Editor Config', () => { let config = new TestWrappingConfiguration({ wordWrap: true }); - // {{SQL CARBON EDIT}} - assertWrapping(config, true, 88); + assertWrapping(config, true, 88); // {{SQL CARBON EDIT}} modify expected value }); test('wordWrap on', () => { let config = new TestWrappingConfiguration({ wordWrap: 'on' }); - // {{SQL CARBON EDIT}} - assertWrapping(config, true, 88); + assertWrapping(config, true, 88); // {{SQL CARBON EDIT}} modify expected value }); test('wordWrap on without minimap', () => { @@ -114,8 +112,7 @@ suite('Common Editor Config', () => { wordWrap: 'on', wordWrapColumn: 10 }); - // {{SQL CARBON EDIT}} - assertWrapping(config, true, 88); + assertWrapping(config, true, 88); // {{SQL CARBON EDIT}} modify expected value }); test('wordWrap off', () => { diff --git a/src/vs/platform/extensionManagement/test/node/extensionGalleryService.test.ts b/src/vs/platform/extensionManagement/test/node/extensionGalleryService.test.ts index 6fb7d2b5fa..681cf39d48 100644 --- a/src/vs/platform/extensionManagement/test/node/extensionGalleryService.test.ts +++ b/src/vs/platform/extensionManagement/test/node/extensionGalleryService.test.ts @@ -10,8 +10,7 @@ import { parseArgs } from 'vs/platform/environment/node/argv'; import { getRandomTestPath } from 'vs/base/test/node/testUtils'; import { join } from 'vs/base/common/path'; import { mkdirp, RimRafMode, rimraf } from 'vs/base/node/pfs'; -// {{SQL CARBON EDIT}} -import { resolveMarketplaceHeaders, ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService'; +import { resolveMarketplaceHeaders, ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService'; // {{SQL CARBON EDIT}} add imports import { isUUID } from 'vs/base/common/uuid'; import { DisposableStore } from 'vs/base/common/lifecycle'; import { IFileService } from 'vs/platform/files/common/files'; @@ -63,8 +62,7 @@ suite('Extension Gallery Service', () => { }); }); - // {{SQL CARBON EDIT}} - test('sortByField', () => { + test('sortByField', () => { // {{SQL CARBON EDIT}} add test let a: { extensionId: string | undefined; extensionName: string | undefined; @@ -120,8 +118,7 @@ suite('Extension Gallery Service', () => { assert.equal(ExtensionGalleryService.compareByField(a, b, 'displayName'), 0); }); - // {{SQL CARBON EDIT}} - test('isMatchingExtension', () => { + test('isMatchingExtension', () => { // {{SQL CARBON EDIT}} add test let createEmptyExtension = () => { return { extensionId: '', diff --git a/src/vs/platform/extensions/test/node/extensionValidator.test.ts b/src/vs/platform/extensions/test/node/extensionValidator.test.ts index c68f4f35b3..bfeeb45dd1 100644 --- a/src/vs/platform/extensions/test/node/extensionValidator.test.ts +++ b/src/vs/platform/extensions/test/node/extensionValidator.test.ts @@ -200,197 +200,195 @@ suite('Extension Version Validator', () => { testIsValidVersion('2.0.0', '*', true); }); - // {{SQL CARBON EDIT}} + test.skip('isValidExtensionVersion', () => { // {{SQL CARBON EDIT}} skip test - // test('isValidExtensionVersion', () => { + function testExtensionVersion(version: string, desiredVersion: string, isBuiltin: boolean, hasMain: boolean, expectedResult: boolean): void { + let desc: IReducedExtensionDescription = { + isBuiltin: isBuiltin, + engines: { + vscode: desiredVersion + }, + main: hasMain ? 'something' : undefined + }; + let reasons: string[] = []; + let actual = isValidExtensionVersion(version, desc, reasons); - // function testExtensionVersion(version: string, desiredVersion: string, isBuiltin: boolean, hasMain: boolean, expectedResult: boolean): void { - // let desc: IReducedExtensionDescription = { - // isBuiltin: isBuiltin, - // engines: { - // vscode: desiredVersion - // }, - // main: hasMain ? 'something' : undefined - // }; - // let reasons: string[] = []; - // let actual = isValidExtensionVersion(version, desc, reasons); + assert.equal(actual, expectedResult, 'version: ' + version + ', desiredVersion: ' + desiredVersion + ', desc: ' + JSON.stringify(desc) + ', reasons: ' + JSON.stringify(reasons)); + } - // assert.equal(actual, expectedResult, 'version: ' + version + ', desiredVersion: ' + desiredVersion + ', desc: ' + JSON.stringify(desc) + ', reasons: ' + JSON.stringify(reasons)); - // } + function testIsInvalidExtensionVersion(version: string, desiredVersion: string, isBuiltin: boolean, hasMain: boolean): void { + testExtensionVersion(version, desiredVersion, isBuiltin, hasMain, false); + } - // function testIsInvalidExtensionVersion(version: string, desiredVersion: string, isBuiltin: boolean, hasMain: boolean): void { - // testExtensionVersion(version, desiredVersion, isBuiltin, hasMain, false); - // } + function testIsValidExtensionVersion(version: string, desiredVersion: string, isBuiltin: boolean, hasMain: boolean): void { + testExtensionVersion(version, desiredVersion, isBuiltin, hasMain, true); + } - // function testIsValidExtensionVersion(version: string, desiredVersion: string, isBuiltin: boolean, hasMain: boolean): void { - // testExtensionVersion(version, desiredVersion, isBuiltin, hasMain, true); - // } + function testIsValidVersion(version: string, desiredVersion: string, expectedResult: boolean): void { + testExtensionVersion(version, desiredVersion, false, true, expectedResult); + } - // function testIsValidVersion(version: string, desiredVersion: string, expectedResult: boolean): void { - // testExtensionVersion(version, desiredVersion, false, true, expectedResult); - // } + // builtin are allowed to use * or x.x.x + testIsValidExtensionVersion('0.10.0-dev', '*', true, true); + testIsValidExtensionVersion('0.10.0-dev', 'x.x.x', true, true); + testIsValidExtensionVersion('0.10.0-dev', '0.x.x', true, true); + testIsValidExtensionVersion('0.10.0-dev', '0.10.x', true, true); + testIsValidExtensionVersion('1.10.0-dev', '1.x.x', true, true); + testIsValidExtensionVersion('1.10.0-dev', '1.10.x', true, true); + testIsValidExtensionVersion('0.10.0-dev', '*', true, false); + testIsValidExtensionVersion('0.10.0-dev', 'x.x.x', true, false); + testIsValidExtensionVersion('0.10.0-dev', '0.x.x', true, false); + testIsValidExtensionVersion('0.10.0-dev', '0.10.x', true, false); + testIsValidExtensionVersion('1.10.0-dev', '1.x.x', true, false); + testIsValidExtensionVersion('1.10.0-dev', '1.10.x', true, false); - // // builtin are allowed to use * or x.x.x - // testIsValidExtensionVersion('0.10.0-dev', '*', true, true); - // testIsValidExtensionVersion('0.10.0-dev', 'x.x.x', true, true); - // testIsValidExtensionVersion('0.10.0-dev', '0.x.x', true, true); - // testIsValidExtensionVersion('0.10.0-dev', '0.10.x', true, true); - // testIsValidExtensionVersion('1.10.0-dev', '1.x.x', true, true); - // testIsValidExtensionVersion('1.10.0-dev', '1.10.x', true, true); - // testIsValidExtensionVersion('0.10.0-dev', '*', true, false); - // testIsValidExtensionVersion('0.10.0-dev', 'x.x.x', true, false); - // testIsValidExtensionVersion('0.10.0-dev', '0.x.x', true, false); - // testIsValidExtensionVersion('0.10.0-dev', '0.10.x', true, false); - // testIsValidExtensionVersion('1.10.0-dev', '1.x.x', true, false); - // testIsValidExtensionVersion('1.10.0-dev', '1.10.x', true, false); + // normal extensions are allowed to use * or x.x.x only if they have no main + testIsInvalidExtensionVersion('0.10.0-dev', '*', false, true); + testIsInvalidExtensionVersion('0.10.0-dev', 'x.x.x', false, true); + testIsInvalidExtensionVersion('0.10.0-dev', '0.x.x', false, true); + testIsValidExtensionVersion('0.10.0-dev', '0.10.x', false, true); + testIsValidExtensionVersion('1.10.0-dev', '1.x.x', false, true); + testIsValidExtensionVersion('1.10.0-dev', '1.10.x', false, true); + testIsValidExtensionVersion('0.10.0-dev', '*', false, false); + testIsValidExtensionVersion('0.10.0-dev', 'x.x.x', false, false); + testIsValidExtensionVersion('0.10.0-dev', '0.x.x', false, false); + testIsValidExtensionVersion('0.10.0-dev', '0.10.x', false, false); + testIsValidExtensionVersion('1.10.0-dev', '1.x.x', false, false); + testIsValidExtensionVersion('1.10.0-dev', '1.10.x', false, false); - // // normal extensions are allowed to use * or x.x.x only if they have no main - // testIsInvalidExtensionVersion('0.10.0-dev', '*', false, true); - // testIsInvalidExtensionVersion('0.10.0-dev', 'x.x.x', false, true); - // testIsInvalidExtensionVersion('0.10.0-dev', '0.x.x', false, true); - // testIsValidExtensionVersion('0.10.0-dev', '0.10.x', false, true); - // testIsValidExtensionVersion('1.10.0-dev', '1.x.x', false, true); - // testIsValidExtensionVersion('1.10.0-dev', '1.10.x', false, true); - // testIsValidExtensionVersion('0.10.0-dev', '*', false, false); - // testIsValidExtensionVersion('0.10.0-dev', 'x.x.x', false, false); - // testIsValidExtensionVersion('0.10.0-dev', '0.x.x', false, false); - // testIsValidExtensionVersion('0.10.0-dev', '0.10.x', false, false); - // testIsValidExtensionVersion('1.10.0-dev', '1.x.x', false, false); - // testIsValidExtensionVersion('1.10.0-dev', '1.10.x', false, false); + // extensions without "main" get no version check + testIsValidExtensionVersion('0.10.0-dev', '>=0.9.1-pre.1', false, false); + testIsValidExtensionVersion('0.10.0-dev', '*', false, false); + testIsValidExtensionVersion('0.10.0-dev', 'x.x.x', false, false); + testIsValidExtensionVersion('0.10.0-dev', '0.x.x', false, false); + testIsValidExtensionVersion('0.10.0-dev', '0.10.x', false, false); + testIsValidExtensionVersion('1.10.0-dev', '1.x.x', false, false); + testIsValidExtensionVersion('1.10.0-dev', '1.10.x', false, false); + testIsValidExtensionVersion('0.10.0-dev', '*', false, false); + testIsValidExtensionVersion('0.10.0-dev', 'x.x.x', false, false); + testIsValidExtensionVersion('0.10.0-dev', '0.x.x', false, false); + testIsValidExtensionVersion('0.10.0-dev', '0.10.x', false, false); + testIsValidExtensionVersion('1.10.0-dev', '1.x.x', false, false); + testIsValidExtensionVersion('1.10.0-dev', '1.10.x', false, false); - // // extensions without "main" get no version check - // testIsValidExtensionVersion('0.10.0-dev', '>=0.9.1-pre.1', false, false); - // testIsValidExtensionVersion('0.10.0-dev', '*', false, false); - // testIsValidExtensionVersion('0.10.0-dev', 'x.x.x', false, false); - // testIsValidExtensionVersion('0.10.0-dev', '0.x.x', false, false); - // testIsValidExtensionVersion('0.10.0-dev', '0.10.x', false, false); - // testIsValidExtensionVersion('1.10.0-dev', '1.x.x', false, false); - // testIsValidExtensionVersion('1.10.0-dev', '1.10.x', false, false); - // testIsValidExtensionVersion('0.10.0-dev', '*', false, false); - // testIsValidExtensionVersion('0.10.0-dev', 'x.x.x', false, false); - // testIsValidExtensionVersion('0.10.0-dev', '0.x.x', false, false); - // testIsValidExtensionVersion('0.10.0-dev', '0.10.x', false, false); - // testIsValidExtensionVersion('1.10.0-dev', '1.x.x', false, false); - // testIsValidExtensionVersion('1.10.0-dev', '1.10.x', false, false); + // normal extensions with code + testIsValidVersion('0.10.0-dev', 'x.x.x', false); // fails due to lack of specificity + testIsValidVersion('0.10.0-dev', '0.x.x', false); // fails due to lack of specificity + testIsValidVersion('0.10.0-dev', '0.10.0', true); + testIsValidVersion('0.10.0-dev', '0.10.2', false); + testIsValidVersion('0.10.0-dev', '^0.10.2', false); + testIsValidVersion('0.10.0-dev', '0.10.x', true); + testIsValidVersion('0.10.0-dev', '^0.10.0', true); + testIsValidVersion('0.10.0-dev', '*', false); // fails due to lack of specificity - // // normal extensions with code - // testIsValidVersion('0.10.0-dev', 'x.x.x', false); // fails due to lack of specificity - // testIsValidVersion('0.10.0-dev', '0.x.x', false); // fails due to lack of specificity - // testIsValidVersion('0.10.0-dev', '0.10.0', true); - // testIsValidVersion('0.10.0-dev', '0.10.2', false); - // testIsValidVersion('0.10.0-dev', '^0.10.2', false); - // testIsValidVersion('0.10.0-dev', '0.10.x', true); - // testIsValidVersion('0.10.0-dev', '^0.10.0', true); - // testIsValidVersion('0.10.0-dev', '*', false); // fails due to lack of specificity + testIsValidVersion('0.10.0', 'x.x.x', false); // fails due to lack of specificity + testIsValidVersion('0.10.0', '0.x.x', false); // fails due to lack of specificity + testIsValidVersion('0.10.0', '0.10.0', true); + testIsValidVersion('0.10.0', '0.10.2', false); + testIsValidVersion('0.10.0', '^0.10.2', false); + testIsValidVersion('0.10.0', '0.10.x', true); + testIsValidVersion('0.10.0', '^0.10.0', true); + testIsValidVersion('0.10.0', '*', false); // fails due to lack of specificity - // testIsValidVersion('0.10.0', 'x.x.x', false); // fails due to lack of specificity - // testIsValidVersion('0.10.0', '0.x.x', false); // fails due to lack of specificity - // testIsValidVersion('0.10.0', '0.10.0', true); - // testIsValidVersion('0.10.0', '0.10.2', false); - // testIsValidVersion('0.10.0', '^0.10.2', false); - // testIsValidVersion('0.10.0', '0.10.x', true); - // testIsValidVersion('0.10.0', '^0.10.0', true); - // testIsValidVersion('0.10.0', '*', false); // fails due to lack of specificity + testIsValidVersion('0.10.1', 'x.x.x', false); // fails due to lack of specificity + testIsValidVersion('0.10.1', '0.x.x', false); // fails due to lack of specificity + testIsValidVersion('0.10.1', '0.10.0', false); + testIsValidVersion('0.10.1', '0.10.2', false); + testIsValidVersion('0.10.1', '^0.10.2', false); + testIsValidVersion('0.10.1', '0.10.x', true); + testIsValidVersion('0.10.1', '^0.10.0', true); + testIsValidVersion('0.10.1', '*', false); // fails due to lack of specificity - // testIsValidVersion('0.10.1', 'x.x.x', false); // fails due to lack of specificity - // testIsValidVersion('0.10.1', '0.x.x', false); // fails due to lack of specificity - // testIsValidVersion('0.10.1', '0.10.0', false); - // testIsValidVersion('0.10.1', '0.10.2', false); - // testIsValidVersion('0.10.1', '^0.10.2', false); - // testIsValidVersion('0.10.1', '0.10.x', true); - // testIsValidVersion('0.10.1', '^0.10.0', true); - // testIsValidVersion('0.10.1', '*', false); // fails due to lack of specificity + testIsValidVersion('0.10.100', 'x.x.x', false); // fails due to lack of specificity + testIsValidVersion('0.10.100', '0.x.x', false); // fails due to lack of specificity + testIsValidVersion('0.10.100', '0.10.0', false); + testIsValidVersion('0.10.100', '0.10.2', false); + testIsValidVersion('0.10.100', '^0.10.2', true); + testIsValidVersion('0.10.100', '0.10.x', true); + testIsValidVersion('0.10.100', '^0.10.0', true); + testIsValidVersion('0.10.100', '*', false); // fails due to lack of specificity - // testIsValidVersion('0.10.100', 'x.x.x', false); // fails due to lack of specificity - // testIsValidVersion('0.10.100', '0.x.x', false); // fails due to lack of specificity - // testIsValidVersion('0.10.100', '0.10.0', false); - // testIsValidVersion('0.10.100', '0.10.2', false); - // testIsValidVersion('0.10.100', '^0.10.2', true); - // testIsValidVersion('0.10.100', '0.10.x', true); - // testIsValidVersion('0.10.100', '^0.10.0', true); - // testIsValidVersion('0.10.100', '*', false); // fails due to lack of specificity + testIsValidVersion('0.11.0', 'x.x.x', false); // fails due to lack of specificity + testIsValidVersion('0.11.0', '0.x.x', false); // fails due to lack of specificity + testIsValidVersion('0.11.0', '0.10.0', false); + testIsValidVersion('0.11.0', '0.10.2', false); + testIsValidVersion('0.11.0', '^0.10.2', false); + testIsValidVersion('0.11.0', '0.10.x', false); + testIsValidVersion('0.11.0', '^0.10.0', false); + testIsValidVersion('0.11.0', '*', false); // fails due to lack of specificity - // testIsValidVersion('0.11.0', 'x.x.x', false); // fails due to lack of specificity - // testIsValidVersion('0.11.0', '0.x.x', false); // fails due to lack of specificity - // testIsValidVersion('0.11.0', '0.10.0', false); - // testIsValidVersion('0.11.0', '0.10.2', false); - // testIsValidVersion('0.11.0', '^0.10.2', false); - // testIsValidVersion('0.11.0', '0.10.x', false); - // testIsValidVersion('0.11.0', '^0.10.0', false); - // testIsValidVersion('0.11.0', '*', false); // fails due to lack of specificity + testIsValidVersion('1.0.0', 'x.x.x', false); // fails due to lack of specificity + testIsValidVersion('1.0.0', '0.x.x', false); // fails due to lack of specificity + testIsValidVersion('1.0.0', '0.10.0', false); + testIsValidVersion('1.0.0', '0.10.2', false); + testIsValidVersion('1.0.0', '^0.10.2', true); + testIsValidVersion('1.0.0', '0.10.x', true); + testIsValidVersion('1.0.0', '^0.10.0', true); + testIsValidVersion('1.0.0', '*', false); // fails due to lack of specificity - // testIsValidVersion('1.0.0', 'x.x.x', false); // fails due to lack of specificity - // testIsValidVersion('1.0.0', '0.x.x', false); // fails due to lack of specificity - // testIsValidVersion('1.0.0', '0.10.0', false); - // testIsValidVersion('1.0.0', '0.10.2', false); - // testIsValidVersion('1.0.0', '^0.10.2', true); - // testIsValidVersion('1.0.0', '0.10.x', true); - // testIsValidVersion('1.0.0', '^0.10.0', true); - // testIsValidVersion('1.0.0', '*', false); // fails due to lack of specificity - - // testIsValidVersion('1.10.0', 'x.x.x', false); // fails due to lack of specificity - // testIsValidVersion('1.10.0', '1.x.x', true); - // testIsValidVersion('1.10.0', '1.10.0', true); - // testIsValidVersion('1.10.0', '1.10.2', false); - // testIsValidVersion('1.10.0', '^1.10.2', false); - // testIsValidVersion('1.10.0', '1.10.x', true); - // testIsValidVersion('1.10.0', '^1.10.0', true); - // testIsValidVersion('1.10.0', '*', false); // fails due to lack of specificity + testIsValidVersion('1.10.0', 'x.x.x', false); // fails due to lack of specificity + testIsValidVersion('1.10.0', '1.x.x', true); + testIsValidVersion('1.10.0', '1.10.0', true); + testIsValidVersion('1.10.0', '1.10.2', false); + testIsValidVersion('1.10.0', '^1.10.2', false); + testIsValidVersion('1.10.0', '1.10.x', true); + testIsValidVersion('1.10.0', '^1.10.0', true); + testIsValidVersion('1.10.0', '*', false); // fails due to lack of specificity - // // Anything < 1.0.0 is compatible + // Anything < 1.0.0 is compatible - // testIsValidVersion('1.0.0', 'x.x.x', false); // fails due to lack of specificity - // testIsValidVersion('1.0.0', '0.x.x', false); // fails due to lack of specificity - // testIsValidVersion('1.0.0', '0.10.0', false); - // testIsValidVersion('1.0.0', '0.10.2', false); - // testIsValidVersion('1.0.0', '^0.10.2', true); - // testIsValidVersion('1.0.0', '0.10.x', true); - // testIsValidVersion('1.0.0', '^0.10.0', true); - // testIsValidVersion('1.0.0', '1.0.0', true); - // testIsValidVersion('1.0.0', '^1.0.0', true); - // testIsValidVersion('1.0.0', '^2.0.0', false); - // testIsValidVersion('1.0.0', '*', false); // fails due to lack of specificity + testIsValidVersion('1.0.0', 'x.x.x', false); // fails due to lack of specificity + testIsValidVersion('1.0.0', '0.x.x', false); // fails due to lack of specificity + testIsValidVersion('1.0.0', '0.10.0', false); + testIsValidVersion('1.0.0', '0.10.2', false); + testIsValidVersion('1.0.0', '^0.10.2', true); + testIsValidVersion('1.0.0', '0.10.x', true); + testIsValidVersion('1.0.0', '^0.10.0', true); + testIsValidVersion('1.0.0', '1.0.0', true); + testIsValidVersion('1.0.0', '^1.0.0', true); + testIsValidVersion('1.0.0', '^2.0.0', false); + testIsValidVersion('1.0.0', '*', false); // fails due to lack of specificity - // testIsValidVersion('1.0.100', 'x.x.x', false); // fails due to lack of specificity - // testIsValidVersion('1.0.100', '0.x.x', false); // fails due to lack of specificity - // testIsValidVersion('1.0.100', '0.10.0', false); - // testIsValidVersion('1.0.100', '0.10.2', false); - // testIsValidVersion('1.0.100', '^0.10.2', true); - // testIsValidVersion('1.0.100', '0.10.x', true); - // testIsValidVersion('1.0.100', '^0.10.0', true); - // testIsValidVersion('1.0.100', '1.0.0', false); - // testIsValidVersion('1.0.100', '^1.0.0', true); - // testIsValidVersion('1.0.100', '^1.0.1', true); - // testIsValidVersion('1.0.100', '^2.0.0', false); - // testIsValidVersion('1.0.100', '*', false); // fails due to lack of specificity + testIsValidVersion('1.0.100', 'x.x.x', false); // fails due to lack of specificity + testIsValidVersion('1.0.100', '0.x.x', false); // fails due to lack of specificity + testIsValidVersion('1.0.100', '0.10.0', false); + testIsValidVersion('1.0.100', '0.10.2', false); + testIsValidVersion('1.0.100', '^0.10.2', true); + testIsValidVersion('1.0.100', '0.10.x', true); + testIsValidVersion('1.0.100', '^0.10.0', true); + testIsValidVersion('1.0.100', '1.0.0', false); + testIsValidVersion('1.0.100', '^1.0.0', true); + testIsValidVersion('1.0.100', '^1.0.1', true); + testIsValidVersion('1.0.100', '^2.0.0', false); + testIsValidVersion('1.0.100', '*', false); // fails due to lack of specificity - // testIsValidVersion('1.100.0', 'x.x.x', false); // fails due to lack of specificity - // testIsValidVersion('1.100.0', '0.x.x', false); // fails due to lack of specificity - // testIsValidVersion('1.100.0', '0.10.0', false); - // testIsValidVersion('1.100.0', '0.10.2', false); - // testIsValidVersion('1.100.0', '^0.10.2', true); - // testIsValidVersion('1.100.0', '0.10.x', true); - // testIsValidVersion('1.100.0', '^0.10.0', true); - // testIsValidVersion('1.100.0', '1.0.0', false); - // testIsValidVersion('1.100.0', '^1.0.0', true); - // testIsValidVersion('1.100.0', '^1.1.0', true); - // testIsValidVersion('1.100.0', '^1.100.0', true); - // testIsValidVersion('1.100.0', '^2.0.0', false); - // testIsValidVersion('1.100.0', '*', false); // fails due to lack of specificity + testIsValidVersion('1.100.0', 'x.x.x', false); // fails due to lack of specificity + testIsValidVersion('1.100.0', '0.x.x', false); // fails due to lack of specificity + testIsValidVersion('1.100.0', '0.10.0', false); + testIsValidVersion('1.100.0', '0.10.2', false); + testIsValidVersion('1.100.0', '^0.10.2', true); + testIsValidVersion('1.100.0', '0.10.x', true); + testIsValidVersion('1.100.0', '^0.10.0', true); + testIsValidVersion('1.100.0', '1.0.0', false); + testIsValidVersion('1.100.0', '^1.0.0', true); + testIsValidVersion('1.100.0', '^1.1.0', true); + testIsValidVersion('1.100.0', '^1.100.0', true); + testIsValidVersion('1.100.0', '^2.0.0', false); + testIsValidVersion('1.100.0', '*', false); // fails due to lack of specificity - // testIsValidVersion('2.0.0', 'x.x.x', false); // fails due to lack of specificity - // testIsValidVersion('2.0.0', '0.x.x', false); // fails due to lack of specificity - // testIsValidVersion('2.0.0', '0.10.0', false); - // testIsValidVersion('2.0.0', '0.10.2', false); - // testIsValidVersion('2.0.0', '^0.10.2', false); - // testIsValidVersion('2.0.0', '0.10.x', false); - // testIsValidVersion('2.0.0', '^0.10.0', false); - // testIsValidVersion('2.0.0', '1.0.0', false); - // testIsValidVersion('2.0.0', '^1.0.0', false); - // testIsValidVersion('2.0.0', '^1.1.0', false); - // testIsValidVersion('2.0.0', '^1.100.0', false); - // testIsValidVersion('2.0.0', '^2.0.0', true); - // testIsValidVersion('2.0.0', '*', false); // fails due to lack of specificity - // }); -}); \ No newline at end of file + testIsValidVersion('2.0.0', 'x.x.x', false); // fails due to lack of specificity + testIsValidVersion('2.0.0', '0.x.x', false); // fails due to lack of specificity + testIsValidVersion('2.0.0', '0.10.0', false); + testIsValidVersion('2.0.0', '0.10.2', false); + testIsValidVersion('2.0.0', '^0.10.2', false); + testIsValidVersion('2.0.0', '0.10.x', false); + testIsValidVersion('2.0.0', '^0.10.0', false); + testIsValidVersion('2.0.0', '1.0.0', false); + testIsValidVersion('2.0.0', '^1.0.0', false); + testIsValidVersion('2.0.0', '^1.1.0', false); + testIsValidVersion('2.0.0', '^1.100.0', false); + testIsValidVersion('2.0.0', '^2.0.0', true); + testIsValidVersion('2.0.0', '*', false); // fails due to lack of specificity + }); +}); diff --git a/src/vs/platform/telemetry/test/electron-browser/commonProperties.test.ts b/src/vs/platform/telemetry/test/electron-browser/commonProperties.test.ts index 3767c234ac..dc9e84fe4a 100644 --- a/src/vs/platform/telemetry/test/electron-browser/commonProperties.test.ts +++ b/src/vs/platform/telemetry/test/electron-browser/commonProperties.test.ts @@ -28,46 +28,45 @@ suite('Telemetry - common properties', function () { rimraf(parentDir, RimRafMode.MOVE).then(done, done); }); - // {{SQL CARBON EDIT}} - // test('default', async function () { - // await mkdirp(parentDir); - // fs.writeFileSync(installSource, 'my.install.source'); - // const props = await resolveWorkbenchCommonProperties(testStorageService, commit, version, 'someMachineId', installSource); - // assert.ok('commitHash' in props); - // assert.ok('sessionID' in props); - // assert.ok('timestamp' in props); - // assert.ok('common.platform' in props); - // assert.ok('common.nodePlatform' in props); - // assert.ok('common.nodeArch' in props); - // assert.ok('common.timesincesessionstart' in props); - // assert.ok('common.sequence' in props); - // // assert.ok('common.version.shell' in first.data); // only when running on electron - // // assert.ok('common.version.renderer' in first.data); - // assert.ok('common.platformVersion' in props, 'platformVersion'); - // assert.ok('version' in props); - // assert.equal(props['common.source'], 'my.install.source'); - // assert.ok('common.firstSessionDate' in props, 'firstSessionDate'); - // assert.ok('common.lastSessionDate' in props, 'lastSessionDate'); // conditional, see below, 'lastSessionDate'ow - // assert.ok('common.isNewSession' in props, 'isNewSession'); - // // machine id et al - // assert.ok('common.instanceId' in props, 'instanceId'); - // assert.ok('common.machineId' in props, 'machineId'); - // fs.unlinkSync(installSource); - // const props_1 = await resolveWorkbenchCommonProperties(testStorageService, commit, version, 'someMachineId', installSource); - // assert.ok(!('common.source' in props_1)); - // }); + test.skip('default', async function () { // {{SQL CARBON EDIT}} skip test + await mkdirp(parentDir); + fs.writeFileSync(installSource, 'my.install.source'); + const props = await resolveWorkbenchCommonProperties(testStorageService, commit, version, 'someMachineId', installSource); + assert.ok('commitHash' in props); + assert.ok('sessionID' in props); + assert.ok('timestamp' in props); + assert.ok('common.platform' in props); + assert.ok('common.nodePlatform' in props); + assert.ok('common.nodeArch' in props); + assert.ok('common.timesincesessionstart' in props); + assert.ok('common.sequence' in props); + // assert.ok('common.version.shell' in first.data); // only when running on electron + // assert.ok('common.version.renderer' in first.data); + assert.ok('common.platformVersion' in props, 'platformVersion'); + assert.ok('version' in props); + assert.equal(props['common.source'], 'my.install.source'); + assert.ok('common.firstSessionDate' in props, 'firstSessionDate'); + assert.ok('common.lastSessionDate' in props, 'lastSessionDate'); // conditional, see below, 'lastSessionDate'ow + assert.ok('common.isNewSession' in props, 'isNewSession'); + // machine id et al + assert.ok('common.instanceId' in props, 'instanceId'); + assert.ok('common.machineId' in props, 'machineId'); + fs.unlinkSync(installSource); + const props_1 = await resolveWorkbenchCommonProperties(testStorageService, commit, version, 'someMachineId', installSource); + assert.ok(!('common.source' in props_1)); + }); - // test('lastSessionDate when aviablale', async function () { + test.skip('lastSessionDate when aviablale', async function () { // {{SQL CARBON EDIT}} skip test - // testStorageService.store('telemetry.lastSessionDate', new Date().toUTCString(), StorageScope.GLOBAL); + testStorageService.store('telemetry.lastSessionDate', new Date().toUTCString(), StorageScope.GLOBAL); - // const props = await resolveWorkbenchCommonProperties(testStorageService, commit, version, 'someMachineId', installSource); - // assert.ok('common.lastSessionDate' in props); // conditional, see below - // assert.ok('common.isNewSession' in props); - // assert.equal(props['common.isNewSession'], 0); - // }); + const props = await resolveWorkbenchCommonProperties(testStorageService, commit, version, 'someMachineId', installSource); + assert.ok('common.lastSessionDate' in props); // conditional, see below + assert.ok('common.isNewSession' in props); + assert.equal(props['common.isNewSession'], 0); + }); - test('values chance on ask', async function () { + test.skip('values chance on ask', async function () { // {{SQL CARBON EDIT}} skip test const props = await resolveWorkbenchCommonProperties(testStorageService, commit, version, 'someMachineId', installSource); let value1 = props['common.sequence']; let value2 = props['common.sequence']; diff --git a/src/vs/platform/telemetry/test/electron-browser/telemetryService.test.ts b/src/vs/platform/telemetry/test/electron-browser/telemetryService.test.ts index cf4a45607f..60202b94c3 100644 --- a/src/vs/platform/telemetry/test/electron-browser/telemetryService.test.ts +++ b/src/vs/platform/telemetry/test/electron-browser/telemetryService.test.ts @@ -219,38 +219,37 @@ suite('TelemetryService', () => { } } - // {{SQL CARBON EDIT}} - // test('Error events', sinon.test(async function (this: any) { + test.skip('Error events', sinon.test(async function (this: any) { // {{SQL CARBON EIDT}} skip test - // let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler(); - // Errors.setUnexpectedErrorHandler(() => { }); + let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler(); + Errors.setUnexpectedErrorHandler(() => { }); - // try { - // let testAppender = new TestTelemetryAppender(); - // let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); - // const errorTelemetry = new ErrorTelemetry(service); + try { + let testAppender = new TestTelemetryAppender(); + let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); + const errorTelemetry = new ErrorTelemetry(service); - // let e: any = new Error('This is a test.'); - // // for Phantom - // if (!e.stack) { - // e.stack = 'blah'; - // } + let e: any = new Error('This is a test.'); + // for Phantom + if (!e.stack) { + e.stack = 'blah'; + } - // Errors.onUnexpectedError(e); - // this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); - // await service.join(); + Errors.onUnexpectedError(e); + this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); + await service.join(); - // assert.equal(testAppender.getEventsCount(), 1); - // assert.equal(testAppender.events[0].eventName, 'UnhandledError'); - // assert.equal(testAppender.events[0].data.msg, 'This is a test.'); + assert.equal(testAppender.getEventsCount(), 1); + assert.equal(testAppender.events[0].eventName, 'UnhandledError'); + assert.equal(testAppender.events[0].data.msg, 'This is a test.'); - // errorTelemetry.dispose(); - // service.dispose(); - // } finally { - // Errors.setUnexpectedErrorHandler(origErrorHandler); - // } - // })); + errorTelemetry.dispose(); + service.dispose(); + } finally { + Errors.setUnexpectedErrorHandler(origErrorHandler); + } + })); // test('Unhandled Promise Error events', sinon.test(function() { // @@ -281,474 +280,436 @@ suite('TelemetryService', () => { // } // })); - // test('Handle global errors', sinon.test(async function (this: any) { - // let errorStub = sinon.stub(); - // window.onerror = errorStub; - - // let testAppender = new TestTelemetryAppender(); - // let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); - // const errorTelemetry = new ErrorTelemetry(service); - - // let testError = new Error('test'); - // (window.onerror)('Error Message', 'file.js', 2, 42, testError); - // this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); - // await service.join(); - - // assert.equal(errorStub.alwaysCalledWithExactly('Error Message', 'file.js', 2, 42, testError), true); - // assert.equal(errorStub.callCount, 1); - - // assert.equal(testAppender.getEventsCount(), 1); - // assert.equal(testAppender.events[0].eventName, 'UnhandledError'); - // assert.equal(testAppender.events[0].data.msg, 'Error Message'); - // assert.equal(testAppender.events[0].data.file, 'file.js'); - // assert.equal(testAppender.events[0].data.line, 2); - // assert.equal(testAppender.events[0].data.column, 42); - // assert.equal(testAppender.events[0].data.uncaught_error_msg, 'test'); - - // errorTelemetry.dispose(); - // service.dispose(); - // })); - - // test('Error Telemetry removes PII from filename with spaces', sinon.test(async function (this: any) { - // let errorStub = sinon.stub(); - // window.onerror = errorStub; - // let settings = new ErrorTestingSettings(); - // let testAppender = new TestTelemetryAppender(); - // let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); - // const errorTelemetry = new ErrorTelemetry(service); - - // let personInfoWithSpaces = settings.personalInfo.slice(0, 2) + ' ' + settings.personalInfo.slice(2); - // let dangerousFilenameError: any = new Error('dangerousFilename'); - // dangerousFilenameError.stack = settings.stack; - // (window.onerror)('dangerousFilename', settings.dangerousPathWithImportantInfo.replace(settings.personalInfo, personInfoWithSpaces) + '/test.js', 2, 42, dangerousFilenameError); - // this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); - // await service.join(); - - // assert.equal(errorStub.callCount, 1); - // assert.equal(testAppender.events[0].data.file.indexOf(settings.dangerousPathWithImportantInfo.replace(settings.personalInfo, personInfoWithSpaces)), -1); - // assert.equal(testAppender.events[0].data.file, settings.importantInfo + '/test.js'); - - // errorTelemetry.dispose(); - // service.dispose(); - // })); - - // test('Uncaught Error Telemetry removes PII from filename', sinon.test(function (this: any) { - // let clock = this.clock; - // let errorStub = sinon.stub(); - // window.onerror = errorStub; - // let settings = new ErrorTestingSettings(); - // let testAppender = new TestTelemetryAppender(); - // let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); - // const errorTelemetry = new ErrorTelemetry(service); - - // let dangerousFilenameError: any = new Error('dangerousFilename'); - // dangerousFilenameError.stack = settings.stack; - // (window.onerror)('dangerousFilename', settings.dangerousPathWithImportantInfo + '/test.js', 2, 42, dangerousFilenameError); - // clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); - // return service.join().then(() => { - // assert.equal(errorStub.callCount, 1); - // assert.equal(testAppender.events[0].data.file.indexOf(settings.dangerousPathWithImportantInfo), -1); - - // dangerousFilenameError = new Error('dangerousFilename'); - // dangerousFilenameError.stack = settings.stack; - // (window.onerror)('dangerousFilename', settings.dangerousPathWithImportantInfo + '/test.js', 2, 42, dangerousFilenameError); - // clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); - // return service.join(); - // }).then(() => { - // assert.equal(errorStub.callCount, 2); - // assert.equal(testAppender.events[0].data.file.indexOf(settings.dangerousPathWithImportantInfo), -1); - // assert.equal(testAppender.events[0].data.file, settings.importantInfo + '/test.js'); - - // errorTelemetry.dispose(); - // service.dispose(); - // }); - // })); - - // test('Unexpected Error Telemetry removes PII', sinon.test(async function (this: any) { - // let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler(); - // Errors.setUnexpectedErrorHandler(() => { }); - // try { - // let settings = new ErrorTestingSettings(); - // let testAppender = new TestTelemetryAppender(); - // let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); - // const errorTelemetry = new ErrorTelemetry(service); - - // let dangerousPathWithoutImportantInfoError: any = new Error(settings.dangerousPathWithoutImportantInfo); - // dangerousPathWithoutImportantInfoError.stack = settings.stack; - // Errors.onUnexpectedError(dangerousPathWithoutImportantInfoError); - // this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); - // await service.join(); - - // assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); - // assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); - - // assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); - // assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); - // assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); - // assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); - - // errorTelemetry.dispose(); - // service.dispose(); - // } - // finally { - // Errors.setUnexpectedErrorHandler(origErrorHandler); - // } - // })); - - // test('Uncaught Error Telemetry removes PII', sinon.test(async function (this: any) { - // let errorStub = sinon.stub(); - // window.onerror = errorStub; - // let settings = new ErrorTestingSettings(); - // let testAppender = new TestTelemetryAppender(); - // let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); - // const errorTelemetry = new ErrorTelemetry(service); - - // let dangerousPathWithoutImportantInfoError: any = new Error('dangerousPathWithoutImportantInfo'); - // dangerousPathWithoutImportantInfoError.stack = settings.stack; - // (window.onerror)(settings.dangerousPathWithoutImportantInfo, 'test.js', 2, 42, dangerousPathWithoutImportantInfoError); - // this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); - // await service.join(); - - // assert.equal(errorStub.callCount, 1); - // // Test that no file information remains, esp. personal info - // assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); - // assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); - // assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); - // assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); - // assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); - // assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); - - // errorTelemetry.dispose(); - // service.dispose(); - // })); - - // test('Unexpected Error Telemetry removes PII but preserves Code file path', sinon.test(async function (this: any) { - - // let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler(); - // Errors.setUnexpectedErrorHandler(() => { }); - - // try { - // let settings = new ErrorTestingSettings(); - // let testAppender = new TestTelemetryAppender(); - // let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); - // const errorTelemetry = new ErrorTelemetry(service); - - // let dangerousPathWithImportantInfoError: any = new Error(settings.dangerousPathWithImportantInfo); - // dangerousPathWithImportantInfoError.stack = settings.stack; - - // // Test that important information remains but personal info does not - // Errors.onUnexpectedError(dangerousPathWithImportantInfoError); - // this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); - // await service.join(); - - // assert.notEqual(testAppender.events[0].data.msg.indexOf(settings.importantInfo), -1); - // assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); - // assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); - // assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.importantInfo), -1); - // assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); - // assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); - // assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); - // assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); - - // errorTelemetry.dispose(); - // service.dispose(); - // } - // finally { - // Errors.setUnexpectedErrorHandler(origErrorHandler); - // } - // })); - - // test('Uncaught Error Telemetry removes PII but preserves Code file path', sinon.test(async function (this: any) { - // let errorStub = sinon.stub(); - // window.onerror = errorStub; - // let settings = new ErrorTestingSettings(); - // let testAppender = new TestTelemetryAppender(); - // let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); - // const errorTelemetry = new ErrorTelemetry(service); - - // let dangerousPathWithImportantInfoError: any = new Error('dangerousPathWithImportantInfo'); - // dangerousPathWithImportantInfoError.stack = settings.stack; - // (window.onerror)(settings.dangerousPathWithImportantInfo, 'test.js', 2, 42, dangerousPathWithImportantInfoError); - // this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); - // await service.join(); - - // assert.equal(errorStub.callCount, 1); - // // Test that important information remains but personal info does not - // assert.notEqual(testAppender.events[0].data.msg.indexOf(settings.importantInfo), -1); - // assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); - // assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); - // assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.importantInfo), -1); - // assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); - // assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); - // assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); - // assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); - - // errorTelemetry.dispose(); - // service.dispose(); - // })); - - // test('Unexpected Error Telemetry removes PII but preserves Code file path with node modules', sinon.test(async function (this: any) { - - // let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler(); - // Errors.setUnexpectedErrorHandler(() => { }); - - // try { - // let settings = new ErrorTestingSettings(); - // let testAppender = new TestTelemetryAppender(); - // let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); - // const errorTelemetry = new ErrorTelemetry(service); - - // let dangerousPathWithImportantInfoError: any = new Error(settings.dangerousPathWithImportantInfo); - // dangerousPathWithImportantInfoError.stack = settings.stack; - - - // Errors.onUnexpectedError(dangerousPathWithImportantInfoError); - // this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); - // await service.join(); - - // assert.notEqual(testAppender.events[0].data.callstack.indexOf('(' + settings.nodeModuleAsarPathToRetain), -1); - // assert.notEqual(testAppender.events[0].data.callstack.indexOf('(' + settings.nodeModulePathToRetain), -1); - // assert.notEqual(testAppender.events[0].data.callstack.indexOf('(/' + settings.nodeModuleAsarPathToRetain), -1); - // assert.notEqual(testAppender.events[0].data.callstack.indexOf('(/' + settings.nodeModulePathToRetain), -1); - - // errorTelemetry.dispose(); - // service.dispose(); - // } - // finally { - // Errors.setUnexpectedErrorHandler(origErrorHandler); - // } - // })); - - // test('Uncaught Error Telemetry removes PII but preserves Code file path', sinon.test(async function (this: any) { - // let errorStub = sinon.stub(); - // window.onerror = errorStub; - // let settings = new ErrorTestingSettings(); - // let testAppender = new TestTelemetryAppender(); - // let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); - // const errorTelemetry = new ErrorTelemetry(service); - - // let dangerousPathWithImportantInfoError: any = new Error('dangerousPathWithImportantInfo'); - // dangerousPathWithImportantInfoError.stack = settings.stack; - // (window.onerror)(settings.dangerousPathWithImportantInfo, 'test.js', 2, 42, dangerousPathWithImportantInfoError); - // this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); - // await service.join(); - - // assert.equal(errorStub.callCount, 1); - - // assert.notEqual(testAppender.events[0].data.callstack.indexOf('(' + settings.nodeModuleAsarPathToRetain), -1); - // assert.notEqual(testAppender.events[0].data.callstack.indexOf('(' + settings.nodeModulePathToRetain), -1); - // assert.notEqual(testAppender.events[0].data.callstack.indexOf('(/' + settings.nodeModuleAsarPathToRetain), -1); - // assert.notEqual(testAppender.events[0].data.callstack.indexOf('(/' + settings.nodeModulePathToRetain), -1); - - // errorTelemetry.dispose(); - // service.dispose(); - // })); - - - // test('Unexpected Error Telemetry removes PII but preserves Code file path when PIIPath is configured', sinon.test(async function (this: any) { - - // let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler(); - // Errors.setUnexpectedErrorHandler(() => { }); - - // try { - // let settings = new ErrorTestingSettings(); - // let testAppender = new TestTelemetryAppender(); - // let service = new JoinableTelemetryService({ appender: testAppender, piiPaths: [settings.personalInfo + '/resources/app/'] }, undefined!); - // const errorTelemetry = new ErrorTelemetry(service); - - // let dangerousPathWithImportantInfoError: any = new Error(settings.dangerousPathWithImportantInfo); - // dangerousPathWithImportantInfoError.stack = settings.stack; - - // // Test that important information remains but personal info does not - // Errors.onUnexpectedError(dangerousPathWithImportantInfoError); - // this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); - // await service.join(); - - // assert.notEqual(testAppender.events[0].data.msg.indexOf(settings.importantInfo), -1); - // assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); - // assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); - // assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.importantInfo), -1); - // assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); - // assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); - // assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); - // assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); - - // errorTelemetry.dispose(); - // service.dispose(); - // } - // finally { - // Errors.setUnexpectedErrorHandler(origErrorHandler); - // } - // })); - - // test('Uncaught Error Telemetry removes PII but preserves Code file path when PIIPath is configured', sinon.test(async function (this: any) { - // let errorStub = sinon.stub(); - // window.onerror = errorStub; - // let settings = new ErrorTestingSettings(); - // let testAppender = new TestTelemetryAppender(); - // let service = new JoinableTelemetryService({ appender: testAppender, piiPaths: [settings.personalInfo + '/resources/app/'] }, undefined!); - // const errorTelemetry = new ErrorTelemetry(service); - - // let dangerousPathWithImportantInfoError: any = new Error('dangerousPathWithImportantInfo'); - // dangerousPathWithImportantInfoError.stack = settings.stack; - // (window.onerror)(settings.dangerousPathWithImportantInfo, 'test.js', 2, 42, dangerousPathWithImportantInfoError); - // this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); - // await service.join(); - - // assert.equal(errorStub.callCount, 1); - // // Test that important information remains but personal info does not - // assert.notEqual(testAppender.events[0].data.msg.indexOf(settings.importantInfo), -1); - // assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); - // assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); - // assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.importantInfo), -1); - // assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); - // assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); - // assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); - // assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); - - // errorTelemetry.dispose(); - // service.dispose(); - // })); - - // test('Unexpected Error Telemetry removes PII but preserves Missing Model error message', sinon.test(async function (this: any) { - - // let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler(); - // Errors.setUnexpectedErrorHandler(() => { }); - - // try { - // let settings = new ErrorTestingSettings(); - // let testAppender = new TestTelemetryAppender(); - // let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); - // const errorTelemetry = new ErrorTelemetry(service); - - // let missingModelError: any = new Error(settings.missingModelMessage); - // missingModelError.stack = settings.stack; - - // // Test that no file information remains, but this particular - // // error message does (Received model events for missing model) - // Errors.onUnexpectedError(missingModelError); - // this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); - // await service.join(); - - // assert.notEqual(testAppender.events[0].data.msg.indexOf(settings.missingModelPrefix), -1); - // assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); - // assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); - // assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.missingModelPrefix), -1); - // assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); - // assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); - // assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); - // assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); - - // errorTelemetry.dispose(); - // service.dispose(); - // } finally { - // Errors.setUnexpectedErrorHandler(origErrorHandler); - // } - // })); - - // test('Uncaught Error Telemetry removes PII but preserves Missing Model error message', sinon.test(async function (this: any) { - // let errorStub = sinon.stub(); - // window.onerror = errorStub; - // let settings = new ErrorTestingSettings(); - // let testAppender = new TestTelemetryAppender(); - // let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); - // const errorTelemetry = new ErrorTelemetry(service); - - // let missingModelError: any = new Error('missingModelMessage'); - // missingModelError.stack = settings.stack; - // (window.onerror)(settings.missingModelMessage, 'test.js', 2, 42, missingModelError); - // this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); - // await service.join(); - - // assert.equal(errorStub.callCount, 1); - // // Test that no file information remains, but this particular - // // error message does (Received model events for missing model) - // assert.notEqual(testAppender.events[0].data.msg.indexOf(settings.missingModelPrefix), -1); - // assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); - // assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); - // assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.missingModelPrefix), -1); - // assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); - // assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); - // assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); - // assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); - - // errorTelemetry.dispose(); - // service.dispose(); - // })); - - // test('Unexpected Error Telemetry removes PII but preserves No Such File error message', sinon.test(async function (this: any) { - - // let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler(); - // Errors.setUnexpectedErrorHandler(() => { }); - - // try { - // let settings = new ErrorTestingSettings(); - // let testAppender = new TestTelemetryAppender(); - // let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); - // const errorTelemetry = new ErrorTelemetry(service); - - // let noSuchFileError: any = new Error(settings.noSuchFileMessage); - // noSuchFileError.stack = settings.stack; - - // // Test that no file information remains, but this particular - // // error message does (ENOENT: no such file or directory) - // Errors.onUnexpectedError(noSuchFileError); - // this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); - // await service.join(); - - // assert.notEqual(testAppender.events[0].data.msg.indexOf(settings.noSuchFilePrefix), -1); - // assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); - // assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); - // assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.noSuchFilePrefix), -1); - // assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); - // assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); - // assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); - // assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); - - // errorTelemetry.dispose(); - // service.dispose(); - // } finally { - // Errors.setUnexpectedErrorHandler(origErrorHandler); - // } - // })); - - // test('Uncaught Error Telemetry removes PII but preserves No Such File error message', sinon.test(async function (this: any) { - // let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler(); - // Errors.setUnexpectedErrorHandler(() => { }); - - // try { - // let errorStub = sinon.stub(); - // window.onerror = errorStub; - // let settings = new ErrorTestingSettings(); - // let testAppender = new TestTelemetryAppender(); - // let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); - // const errorTelemetry = new ErrorTelemetry(service); - - // let noSuchFileError: any = new Error('noSuchFileMessage'); - // noSuchFileError.stack = settings.stack; - // (window.onerror)(settings.noSuchFileMessage, 'test.js', 2, 42, noSuchFileError); - // this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); - // await service.join(); - - // assert.equal(errorStub.callCount, 1); - // // Test that no file information remains, but this particular - // // error message does (ENOENT: no such file or directory) - // Errors.onUnexpectedError(noSuchFileError); - // assert.notEqual(testAppender.events[0].data.msg.indexOf(settings.noSuchFilePrefix), -1); - // assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); - // assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); - // assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.noSuchFilePrefix), -1); - // assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); - // assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); - // assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); - // assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); - - // errorTelemetry.dispose(); - // service.dispose(); - // } finally { - // Errors.setUnexpectedErrorHandler(origErrorHandler); - // } - // })); + test.skip('Handle global errors', sinon.test(async function (this: any) { // {{SQL CARBON EIDT}} skip test + let errorStub = sinon.stub(); + window.onerror = errorStub; + + let testAppender = new TestTelemetryAppender(); + let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); + const errorTelemetry = new ErrorTelemetry(service); + + let testError = new Error('test'); + (window.onerror)('Error Message', 'file.js', 2, 42, testError); + this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); + await service.join(); + + assert.equal(errorStub.alwaysCalledWithExactly('Error Message', 'file.js', 2, 42, testError), true); + assert.equal(errorStub.callCount, 1); + + assert.equal(testAppender.getEventsCount(), 1); + assert.equal(testAppender.events[0].eventName, 'UnhandledError'); + assert.equal(testAppender.events[0].data.msg, 'Error Message'); + assert.equal(testAppender.events[0].data.file, 'file.js'); + assert.equal(testAppender.events[0].data.line, 2); + assert.equal(testAppender.events[0].data.column, 42); + assert.equal(testAppender.events[0].data.uncaught_error_msg, 'test'); + + errorTelemetry.dispose(); + service.dispose(); + })); + + test.skip('Error Telemetry removes PII from filename with spaces', sinon.test(async function (this: any) { // {{SQL CARBON EIDT}} skip test + let errorStub = sinon.stub(); + window.onerror = errorStub; + let settings = new ErrorTestingSettings(); + let testAppender = new TestTelemetryAppender(); + let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); + const errorTelemetry = new ErrorTelemetry(service); + + let personInfoWithSpaces = settings.personalInfo.slice(0, 2) + ' ' + settings.personalInfo.slice(2); + let dangerousFilenameError: any = new Error('dangerousFilename'); + dangerousFilenameError.stack = settings.stack; + (window.onerror)('dangerousFilename', settings.dangerousPathWithImportantInfo.replace(settings.personalInfo, personInfoWithSpaces) + '/test.js', 2, 42, dangerousFilenameError); + this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); + await service.join(); + + assert.equal(errorStub.callCount, 1); + assert.equal(testAppender.events[0].data.file.indexOf(settings.dangerousPathWithImportantInfo.replace(settings.personalInfo, personInfoWithSpaces)), -1); + assert.equal(testAppender.events[0].data.file, settings.importantInfo + '/test.js'); + + errorTelemetry.dispose(); + service.dispose(); + })); + + test.skip('Uncaught Error Telemetry removes PII from filename', sinon.test(function (this: any) { // {{SQL CARBON EIDT}} skip test + let clock = this.clock; + let errorStub = sinon.stub(); + window.onerror = errorStub; + let settings = new ErrorTestingSettings(); + let testAppender = new TestTelemetryAppender(); + let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); + const errorTelemetry = new ErrorTelemetry(service); + + let dangerousFilenameError: any = new Error('dangerousFilename'); + dangerousFilenameError.stack = settings.stack; + (window.onerror)('dangerousFilename', settings.dangerousPathWithImportantInfo + '/test.js', 2, 42, dangerousFilenameError); + clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); + return service.join().then(() => { + assert.equal(errorStub.callCount, 1); + assert.equal(testAppender.events[0].data.file.indexOf(settings.dangerousPathWithImportantInfo), -1); + + dangerousFilenameError = new Error('dangerousFilename'); + dangerousFilenameError.stack = settings.stack; + (window.onerror)('dangerousFilename', settings.dangerousPathWithImportantInfo + '/test.js', 2, 42, dangerousFilenameError); + clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); + return service.join(); + }).then(() => { + assert.equal(errorStub.callCount, 2); + assert.equal(testAppender.events[0].data.file.indexOf(settings.dangerousPathWithImportantInfo), -1); + assert.equal(testAppender.events[0].data.file, settings.importantInfo + '/test.js'); + + errorTelemetry.dispose(); + service.dispose(); + }); + })); + + test.skip('Unexpected Error Telemetry removes PII', sinon.test(async function (this: any) { // {{SQL CARBON EIDT}} skip test + let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler(); + Errors.setUnexpectedErrorHandler(() => { }); + try { + let settings = new ErrorTestingSettings(); + let testAppender = new TestTelemetryAppender(); + let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); + const errorTelemetry = new ErrorTelemetry(service); + + let dangerousPathWithoutImportantInfoError: any = new Error(settings.dangerousPathWithoutImportantInfo); + dangerousPathWithoutImportantInfoError.stack = settings.stack; + Errors.onUnexpectedError(dangerousPathWithoutImportantInfoError); + this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); + await service.join(); + + assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); + + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); + assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); + + errorTelemetry.dispose(); + service.dispose(); + } + finally { + Errors.setUnexpectedErrorHandler(origErrorHandler); + } + })); + + test.skip('Uncaught Error Telemetry removes PII', sinon.test(async function (this: any) { // {{SQL CARBON EIDT}} skip test + let errorStub = sinon.stub(); + window.onerror = errorStub; + let settings = new ErrorTestingSettings(); + let testAppender = new TestTelemetryAppender(); + let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); + const errorTelemetry = new ErrorTelemetry(service); + + let dangerousPathWithoutImportantInfoError: any = new Error('dangerousPathWithoutImportantInfo'); + dangerousPathWithoutImportantInfoError.stack = settings.stack; + (window.onerror)(settings.dangerousPathWithoutImportantInfo, 'test.js', 2, 42, dangerousPathWithoutImportantInfoError); + this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); + await service.join(); + + assert.equal(errorStub.callCount, 1); + // Test that no file information remains, esp. personal info + assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); + assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); + + errorTelemetry.dispose(); + service.dispose(); + })); + + test.skip('Unexpected Error Telemetry removes PII but preserves Code file path', sinon.test(async function (this: any) { // {{SQL CARBON EIDT}} skip test + + let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler(); + Errors.setUnexpectedErrorHandler(() => { }); + + try { + let settings = new ErrorTestingSettings(); + let testAppender = new TestTelemetryAppender(); + let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); + const errorTelemetry = new ErrorTelemetry(service); + + let dangerousPathWithImportantInfoError: any = new Error(settings.dangerousPathWithImportantInfo); + dangerousPathWithImportantInfoError.stack = settings.stack; + + // Test that important information remains but personal info does not + Errors.onUnexpectedError(dangerousPathWithImportantInfoError); + this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); + await service.join(); + + assert.notEqual(testAppender.events[0].data.msg.indexOf(settings.importantInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.importantInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); + assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); + + errorTelemetry.dispose(); + service.dispose(); + } + finally { + Errors.setUnexpectedErrorHandler(origErrorHandler); + } + })); + + test.skip('Uncaught Error Telemetry removes PII but preserves Code file path', sinon.test(async function (this: any) { // {{SQL CARBON EIDT}} skip test + let errorStub = sinon.stub(); + window.onerror = errorStub; + let settings = new ErrorTestingSettings(); + let testAppender = new TestTelemetryAppender(); + let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); + const errorTelemetry = new ErrorTelemetry(service); + + let dangerousPathWithImportantInfoError: any = new Error('dangerousPathWithImportantInfo'); + dangerousPathWithImportantInfoError.stack = settings.stack; + (window.onerror)(settings.dangerousPathWithImportantInfo, 'test.js', 2, 42, dangerousPathWithImportantInfoError); + this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); + await service.join(); + + assert.equal(errorStub.callCount, 1); + // Test that important information remains but personal info does not + assert.notEqual(testAppender.events[0].data.msg.indexOf(settings.importantInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.importantInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); + assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); + + errorTelemetry.dispose(); + service.dispose(); + })); + + test.skip('Unexpected Error Telemetry removes PII but preserves Code file path with node modules', sinon.test(async function (this: any) { // {{SQL CARBON EIDT}} skip test + + let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler(); + Errors.setUnexpectedErrorHandler(() => { }); + + try { + let settings = new ErrorTestingSettings(); + let testAppender = new TestTelemetryAppender(); + let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); + const errorTelemetry = new ErrorTelemetry(service); + + let dangerousPathWithImportantInfoError: any = new Error(settings.dangerousPathWithImportantInfo); + dangerousPathWithImportantInfoError.stack = settings.stack; + + + Errors.onUnexpectedError(dangerousPathWithImportantInfoError); + this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); + await service.join(); + + assert.notEqual(testAppender.events[0].data.callstack.indexOf('(' + settings.nodeModuleAsarPathToRetain), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf('(' + settings.nodeModulePathToRetain), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf('(/' + settings.nodeModuleAsarPathToRetain), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf('(/' + settings.nodeModulePathToRetain), -1); + + errorTelemetry.dispose(); + service.dispose(); + } + finally { + Errors.setUnexpectedErrorHandler(origErrorHandler); + } + })); + + test.skip('Uncaught Error Telemetry removes PII but preserves Code file path', sinon.test(async function (this: any) { // {{SQL CARBON EIDT}} skip test + let errorStub = sinon.stub(); + window.onerror = errorStub; + let settings = new ErrorTestingSettings(); + let testAppender = new TestTelemetryAppender(); + let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); + const errorTelemetry = new ErrorTelemetry(service); + + let dangerousPathWithImportantInfoError: any = new Error('dangerousPathWithImportantInfo'); + dangerousPathWithImportantInfoError.stack = settings.stack; + (window.onerror)(settings.dangerousPathWithImportantInfo, 'test.js', 2, 42, dangerousPathWithImportantInfoError); + this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); + await service.join(); + + assert.equal(errorStub.callCount, 1); + + assert.notEqual(testAppender.events[0].data.callstack.indexOf('(' + settings.nodeModuleAsarPathToRetain), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf('(' + settings.nodeModulePathToRetain), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf('(/' + settings.nodeModuleAsarPathToRetain), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf('(/' + settings.nodeModulePathToRetain), -1); + + errorTelemetry.dispose(); + service.dispose(); + })); + + + test.skip('Unexpected Error Telemetry removes PII but preserves Code file path when PIIPath is configured', sinon.test(async function (this: any) { // {{SQL CARBON EIDT}} skip test + + let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler(); + Errors.setUnexpectedErrorHandler(() => { }); + + try { + let settings = new ErrorTestingSettings(); + let testAppender = new TestTelemetryAppender(); + let service = new JoinableTelemetryService({ appender: testAppender, piiPaths: [settings.personalInfo + '/resources/app/'] }, undefined!); + const errorTelemetry = new ErrorTelemetry(service); + + let dangerousPathWithImportantInfoError: any = new Error(settings.dangerousPathWithImportantInfo); + dangerousPathWithImportantInfoError.stack = settings.stack; + + // Test that important information remains but personal info does not + Errors.onUnexpectedError(dangerousPathWithImportantInfoError); + this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); + await service.join(); + + assert.notEqual(testAppender.events[0].data.msg.indexOf(settings.importantInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.importantInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); + assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); + + errorTelemetry.dispose(); + service.dispose(); + } + finally { + Errors.setUnexpectedErrorHandler(origErrorHandler); + } + })); + + test.skip('Uncaught Error Telemetry removes PII but preserves Code file path when PIIPath is configured', sinon.test(async function (this: any) { // {{SQL CARBON EIDT}} skip test + let errorStub = sinon.stub(); + window.onerror = errorStub; + let settings = new ErrorTestingSettings(); + let testAppender = new TestTelemetryAppender(); + let service = new JoinableTelemetryService({ appender: testAppender, piiPaths: [settings.personalInfo + '/resources/app/'] }, undefined!); + const errorTelemetry = new ErrorTelemetry(service); + + let dangerousPathWithImportantInfoError: any = new Error('dangerousPathWithImportantInfo'); + dangerousPathWithImportantInfoError.stack = settings.stack; + (window.onerror)(settings.dangerousPathWithImportantInfo, 'test.js', 2, 42, dangerousPathWithImportantInfoError); + this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); + await service.join(); + + assert.equal(errorStub.callCount, 1); + // Test that important information remains but personal info does not + assert.notEqual(testAppender.events[0].data.msg.indexOf(settings.importantInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.importantInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); + assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); + + errorTelemetry.dispose(); + service.dispose(); + })); + + test.skip('Unexpected Error Telemetry removes PII but preserves Missing Model error message', sinon.test(async function (this: any) { // {{SQL CARBON EIDT}} skip test + + let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler(); + Errors.setUnexpectedErrorHandler(() => { }); + + try { + let settings = new ErrorTestingSettings(); + let testAppender = new TestTelemetryAppender(); + let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); + const errorTelemetry = new ErrorTelemetry(service); + + let missingModelError: any = new Error(settings.missingModelMessage); + missingModelError.stack = settings.stack; + + // Test that no file information remains, but this particular + // error message does (Received model events for missing model) + Errors.onUnexpectedError(missingModelError); + this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); + await service.join(); + + assert.notEqual(testAppender.events[0].data.msg.indexOf(settings.missingModelPrefix), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.missingModelPrefix), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); + assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); + + errorTelemetry.dispose(); + service.dispose(); + } finally { + Errors.setUnexpectedErrorHandler(origErrorHandler); + } + })); + + test.skip('Uncaught Error Telemetry removes PII but preserves Missing Model error message', sinon.test(async function (this: any) { // {{SQL CARBON EIDT}} skip test + let errorStub = sinon.stub(); + window.onerror = errorStub; + let settings = new ErrorTestingSettings(); + let testAppender = new TestTelemetryAppender(); + let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); + const errorTelemetry = new ErrorTelemetry(service); + + let missingModelError: any = new Error('missingModelMessage'); + missingModelError.stack = settings.stack; + (window.onerror)(settings.missingModelMessage, 'test.js', 2, 42, missingModelError); + this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); + await service.join(); + + assert.equal(errorStub.callCount, 1); + // Test that no file information remains, but this particular + // error message does (Received model events for missing model) + assert.notEqual(testAppender.events[0].data.msg.indexOf(settings.missingModelPrefix), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.missingModelPrefix), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); + assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); + + errorTelemetry.dispose(); + service.dispose(); + })); + + test.skip('Unexpected Error Telemetry removes PII but preserves No Such File error message', sinon.test(async function (this: any) { // {{SQL CARBON EIDT}} skip test + + let origErrorHandler = Errors.errorHandler.getUnexpectedErrorHandler(); + Errors.setUnexpectedErrorHandler(() => { }); + + try { + let settings = new ErrorTestingSettings(); + let testAppender = new TestTelemetryAppender(); + let service = new JoinableTelemetryService({ appender: testAppender }, undefined!); + const errorTelemetry = new ErrorTelemetry(service); + + let noSuchFileError: any = new Error(settings.noSuchFileMessage); + noSuchFileError.stack = settings.stack; + + // Test that no file information remains, but this particular + // error message does (ENOENT: no such file or directory) + Errors.onUnexpectedError(noSuchFileError); + this.clock.tick(ErrorTelemetry.ERROR_FLUSH_TIMEOUT); + await service.join(); + + assert.notEqual(testAppender.events[0].data.msg.indexOf(settings.noSuchFilePrefix), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.msg.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.noSuchFilePrefix), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.personalInfo), -1); + assert.equal(testAppender.events[0].data.callstack.indexOf(settings.filePrefix), -1); + assert.notEqual(testAppender.events[0].data.callstack.indexOf(settings.stack[4].replace(settings.randomUserFile, settings.anonymizedRandomUserFile)), -1); + assert.equal(testAppender.events[0].data.callstack.split('\n').length, settings.stack.length); + + errorTelemetry.dispose(); + service.dispose(); + } finally { + Errors.setUnexpectedErrorHandler(origErrorHandler); + } + })); test('Telemetry Service sends events when enableTelemetry is on', sinon.test(function () { let testAppender = new TestTelemetryAppender(); diff --git a/src/vs/workbench/contrib/debug/test/browser/baseDebugView.test.ts b/src/vs/workbench/contrib/debug/test/browser/baseDebugView.test.ts index ff7df6f28f..7a72180075 100644 --- a/src/vs/workbench/contrib/debug/test/browser/baseDebugView.test.ts +++ b/src/vs/workbench/contrib/debug/test/browser/baseDebugView.test.ts @@ -6,6 +6,7 @@ import * as assert from 'assert'; import { replaceWhitespace, renderExpressionValue, renderVariable } from 'vs/workbench/contrib/debug/browser/baseDebugView'; import * as dom from 'vs/base/browser/dom'; +import { Expression, Variable, Scope, StackFrame, Thread } from 'vs/workbench/contrib/debug/common/debugModel'; import { MockSession } from 'vs/workbench/contrib/debug/test/common/mockDebug'; import { HighlightedLabel } from 'vs/base/browser/ui/highlightedlabel/highlightedLabel'; const $ = dom.$; @@ -19,7 +20,72 @@ suite('Debug - Base Debug View', () => { assert.equal(replaceWhitespace('hey \r\t\n\t\t\n there'), 'hey \\r\\t\\n\\t\\t\\n there'); }); - test('render variable', () => { - // {{SQL CARBON EDIT}} - Disable test + test.skip('render expression value', () => { // {{SQL CARBON EDIT}} skip test + let container = $('.container'); + renderExpressionValue('render \n me', container, { showHover: true, preserveWhitespace: true }); + assert.equal(container.className, 'value'); + assert.equal(container.title, 'render \n me'); + assert.equal(container.textContent, 'render \n me'); + + const expression = new Expression('console'); + expression.value = 'Object'; + container = $('.container'); + renderExpressionValue(expression, container, { colorize: true }); + assert.equal(container.className, 'value unavailable error'); + + expression.available = true; + expression.value = '"string value"'; + container = $('.container'); + renderExpressionValue(expression, container, { colorize: true }); + assert.equal(container.className, 'value string'); + assert.equal(container.textContent, '"string value"'); + + expression.type = 'boolean'; + container = $('.container'); + renderExpressionValue(expression, container, { colorize: true }); + assert.equal(container.className, 'value boolean'); + assert.equal(container.textContent, expression.value); + + expression.value = 'this is a long string'; + container = $('.container'); + renderExpressionValue(expression, container, { colorize: true, maxValueLength: 4 }); + assert.equal(container.textContent, 'this...'); + }); + + test.skip('render variable', () => { // {{SQL CARBON EDIT}} skip test + const session = new MockSession(); + const thread = new Thread(session, 'mockthread', 1); + const stackFrame = new StackFrame(thread, 1, null!, 'app.js', 'normal', { startLineNumber: 1, startColumn: 1, endLineNumber: undefined!, endColumn: undefined! }, 0); + const scope = new Scope(stackFrame, 1, 'local', 1, false, 10, 10); + + let variable = new Variable(session, scope, 2, 'foo', 'bar.foo', undefined!, 0, 0, {}, 'string'); + let expression = $('.'); + let name = $('.'); + let value = $('.'); + let label = new HighlightedLabel(name, false); + renderVariable(variable, { expression, name, value, label }, false, []); + + assert.equal(label.element.textContent, 'foo'); + assert.equal(value.textContent, ''); + assert.equal(value.title, ''); + + variable.value = 'hey'; + expression = $('.'); + name = $('.'); + value = $('.'); + renderVariable(variable, { expression, name, value, label }, false, []); + assert.equal(value.textContent, 'hey'); + assert.equal(label.element.textContent, 'foo:'); + assert.equal(label.element.title, 'string'); + + variable = new Variable(session, scope, 2, 'console', 'console', '5', 0, 0, { kind: 'virtual' }); + expression = $('.'); + name = $('.'); + value = $('.'); + renderVariable(variable, { expression, name, value, label }, false, []); + assert.equal(name.className, 'virtual'); + assert.equal(label.element.textContent, 'console:'); + assert.equal(label.element.title, 'console'); + assert.equal(value.className, 'value number'); }); }); diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsTipsService.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsTipsService.test.ts index a327d6183d..7386f8cffe 100644 --- a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsTipsService.test.ts +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsTipsService.test.ts @@ -167,8 +167,390 @@ function aGalleryExtension(name: string, properties: any = {}, galleryExtensionP return galleryExtension; } -// {{SQL CARBON EDIT}} disable broken tests -suite('ExtensionsTipsService Test', () => { +suite.skip('ExtensionsTipsService Test', () => { // {{SQL CARBON EDIT}} skip suite + let workspaceService: IWorkspaceContextService; + let instantiationService: TestInstantiationService; + let testConfigurationService: TestConfigurationService; + let testObject: ExtensionTipsService; + let parentResource: string; + let installEvent: Emitter, + didInstallEvent: Emitter, + uninstallEvent: Emitter, + didUninstallEvent: Emitter; + let prompted: boolean; + let onModelAddedEvent: Emitter; + let experimentService: TestExperimentService; + + suiteSetup(() => { + instantiationService = new TestInstantiationService(); + installEvent = new Emitter(); + didInstallEvent = new Emitter(); + uninstallEvent = new Emitter(); + didUninstallEvent = new Emitter(); + instantiationService.stub(IExtensionGalleryService, ExtensionGalleryService); + instantiationService.stub(ISharedProcessService, TestSharedProcessService); + instantiationService.stub(ILifecycleService, new TestLifecycleService()); + testConfigurationService = new TestConfigurationService(); + instantiationService.stub(IConfigurationService, testConfigurationService); + instantiationService.stub(INotificationService, new TestNotificationService()); + instantiationService.stub(IExtensionManagementService, ExtensionManagementService); + instantiationService.stub(IExtensionManagementService, 'onInstallExtension', installEvent.event); + instantiationService.stub(IExtensionManagementService, 'onDidInstallExtension', didInstallEvent.event); + instantiationService.stub(IExtensionManagementService, 'onUninstallExtension', uninstallEvent.event); + instantiationService.stub(IExtensionManagementService, 'onDidUninstallExtension', didUninstallEvent.event); + instantiationService.stub(IExtensionEnablementService, new TestExtensionEnablementService(instantiationService)); + instantiationService.stub(ITelemetryService, NullTelemetryService); + instantiationService.stub(IURLService, URLService); + instantiationService.set(IProductService, { + ...productService, + ...{ + extensionTips: { + 'ms-vscode.csharp': '{**/*.cs,**/project.json,**/global.json,**/*.csproj,**/*.sln,**/appsettings.json}', + 'msjsdiag.debugger-for-chrome': '{**/*.ts,**/*.tsx**/*.js,**/*.jsx,**/*.es6,**/.babelrc}', + 'lukehoban.Go': '**/*.go' + }, + extensionImportantTips: { + 'ms-python.python': { + 'name': 'Python', + 'pattern': '{**/*.py}' + }, + 'ms-vscode.PowerShell': { + 'name': 'PowerShell', + 'pattern': '{**/*.ps,**/*.ps1}' + } + } + } + }); + + experimentService = instantiationService.createInstance(TestExperimentService); + instantiationService.stub(IExperimentService, experimentService); + + onModelAddedEvent = new Emitter(); + }); + + suiteTeardown(() => { + if (experimentService) { + experimentService.dispose(); + } + }); + + setup(() => { + instantiationService.stub(IEnvironmentService, >{ extensionDevelopmentPath: false }); + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', []); + instantiationService.stub(IExtensionGalleryService, 'isEnabled', true); + instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(...mockExtensionGallery)); + + prompted = false; + + class TestNotificationService2 extends TestNotificationService { + public prompt(severity: Severity, message: string, choices: IPromptChoice[], options?: IPromptOptions) { + prompted = true; + return null!; + } + } + + instantiationService.stub(INotificationService, new TestNotificationService2()); + + testConfigurationService.setUserConfiguration(ConfigurationKey, { ignoreRecommendations: false, showRecommendationsOnlyOnDemand: false }); + instantiationService.stub(IStorageService, >{ get: (a: string, b: StorageScope, c?: string) => c, getBoolean: (a: string, b: StorageScope, c: boolean) => c, store: () => { } }); + instantiationService.stub(IModelService, { + getModels(): any { return []; }, + onModelAdded: onModelAddedEvent.event + }); + }); + + teardown(done => { + (testObject).dispose(); + if (parentResource) { + rimraf(parentResource, RimRafMode.MOVE).then(done, done); + } else { + done(); + } + }); + + function setUpFolderWorkspace(folderName: string, recommendedExtensions: string[], ignoredRecommendations: string[] = []): Promise { + const id = uuid.generateUuid(); + parentResource = path.join(os.tmpdir(), 'vsctests', id); + return setUpFolder(folderName, parentResource, recommendedExtensions, ignoredRecommendations); + } + + async function setUpFolder(folderName: string, parentDir: string, recommendedExtensions: string[], ignoredRecommendations: string[] = []): Promise { + const folderDir = path.join(parentDir, folderName); + const workspaceSettingsDir = path.join(folderDir, '.vscode'); + await mkdirp(workspaceSettingsDir, 493); + const configPath = path.join(workspaceSettingsDir, 'extensions.json'); + fs.writeFileSync(configPath, JSON.stringify({ + 'recommendations': recommendedExtensions, + 'unwantedRecommendations': ignoredRecommendations, + }, null, '\t')); + + const myWorkspace = testWorkspace(URI.from({ scheme: 'file', path: folderDir })); + workspaceService = new TestContextService(myWorkspace); + instantiationService.stub(IWorkspaceContextService, workspaceService); + const fileService = new FileService(new NullLogService()); + fileService.registerProvider(Schemas.file, new DiskFileSystemProvider(new NullLogService())); + instantiationService.stub(IFileService, fileService); + } + + function testNoPromptForValidRecommendations(recommendations: string[]) { + return setUpFolderWorkspace('myFolder', recommendations).then(() => { + testObject = instantiationService.createInstance(ExtensionTipsService); + return testObject.loadWorkspaceConfigPromise.then(() => { + assert.equal(Object.keys(testObject.getAllRecommendationsWithReason()).length, recommendations.length); + assert.ok(!prompted); + }); + }); + } + + function testNoPromptOrRecommendationsForValidRecommendations(recommendations: string[]) { + return setUpFolderWorkspace('myFolder', mockTestData.validRecommendedExtensions).then(() => { + testObject = instantiationService.createInstance(ExtensionTipsService); + assert.equal(!testObject.loadWorkspaceConfigPromise, true); + assert.ok(!prompted); + + return testObject.getWorkspaceRecommendations().then(() => { + assert.equal(Object.keys(testObject.getAllRecommendationsWithReason()).length, 0); + assert.ok(!prompted); + }); + }); + } + test('ExtensionTipsService: No Prompt for valid workspace recommendations when galleryService is absent', () => { + const galleryQuerySpy = sinon.spy(); + instantiationService.stub(IExtensionGalleryService, { query: galleryQuerySpy, isEnabled: () => false }); + + return testNoPromptOrRecommendationsForValidRecommendations(mockTestData.validRecommendedExtensions) + .then(() => assert.ok(galleryQuerySpy.notCalled)); + }); + + test('ExtensionTipsService: No Prompt for valid workspace recommendations during extension development', () => { + instantiationService.stub(IEnvironmentService, { extensionDevelopmentLocationURI: [URI.file('/folder/file')] }); + return testNoPromptOrRecommendationsForValidRecommendations(mockTestData.validRecommendedExtensions); + }); + + test('ExtensionTipsService: No workspace recommendations or prompts when extensions.json has empty array', () => { + return testNoPromptForValidRecommendations([]); + }); + + test('ExtensionTipsService: Prompt for valid workspace recommendations', () => { + return setUpFolderWorkspace('myFolder', mockTestData.recommendedExtensions).then(() => { + testObject = instantiationService.createInstance(ExtensionTipsService); + return testObject.loadWorkspaceConfigPromise.then(() => { + const recommendations = Object.keys(testObject.getAllRecommendationsWithReason()); + + assert.equal(recommendations.length, mockTestData.validRecommendedExtensions.length); + mockTestData.validRecommendedExtensions.forEach(x => { + assert.equal(recommendations.indexOf(x.toLowerCase()) > -1, true); + }); + + assert.ok(prompted); + }); + }); + }); + + test('ExtensionTipsService: No Prompt for valid workspace recommendations if they are already installed', () => { + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', mockExtensionLocal); + return testNoPromptForValidRecommendations(mockTestData.validRecommendedExtensions); + }); + + test('ExtensionTipsService: No Prompt for valid workspace recommendations with casing mismatch if they are already installed', () => { + instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', mockExtensionLocal); + return testNoPromptForValidRecommendations(mockTestData.validRecommendedExtensions.map(x => x.toUpperCase())); + }); + + test('ExtensionTipsService: No Prompt for valid workspace recommendations if ignoreRecommendations is set', () => { + testConfigurationService.setUserConfiguration(ConfigurationKey, { ignoreRecommendations: true }); + return testNoPromptForValidRecommendations(mockTestData.validRecommendedExtensions); + }); + + test('ExtensionTipsService: No Prompt for valid workspace recommendations if showRecommendationsOnlyOnDemand is set', () => { + testConfigurationService.setUserConfiguration(ConfigurationKey, { showRecommendationsOnlyOnDemand: true }); + return setUpFolderWorkspace('myFolder', mockTestData.validRecommendedExtensions).then(() => { + testObject = instantiationService.createInstance(ExtensionTipsService); + return testObject.loadWorkspaceConfigPromise.then(() => { + assert.equal(Object.keys(testObject.getAllRecommendationsWithReason()).length, 0); + assert.ok(!prompted); + }); + }); + }); + + test('ExtensionTipsService: No Prompt for valid workspace recommendations if ignoreRecommendations is set for current workspace', () => { + instantiationService.stub(IStorageService, >{ get: (a: string, b: StorageScope, c?: string) => c, getBoolean: (a: string, b: StorageScope, c?: boolean) => a === 'extensionsAssistant/workspaceRecommendationsIgnore' || c }); + return testNoPromptForValidRecommendations(mockTestData.validRecommendedExtensions); + }); + + test('ExtensionTipsService: No Recommendations of globally ignored recommendations', () => { + const storageGetterStub = (a: string, _: StorageScope, c?: string) => { + const storedRecommendations = '["ms-vscode.csharp", "ms-python.python", "ms-vscode.vscode-typescript-tslint-plugin"]'; + const ignoredRecommendations = '["ms-vscode.csharp", "mockpublisher2.mockextension2"]'; // ignore a stored recommendation and a workspace recommendation. + if (a === 'extensionsAssistant/recommendations') { return storedRecommendations; } + if (a === 'extensionsAssistant/ignored_recommendations') { return ignoredRecommendations; } + return c; + }; + + instantiationService.stub(IStorageService, >{ + get: storageGetterStub, + getBoolean: (a: string, _: StorageScope, c?: boolean) => a === 'extensionsAssistant/workspaceRecommendationsIgnore' || c + }); + + return setUpFolderWorkspace('myFolder', mockTestData.validRecommendedExtensions).then(() => { + testObject = instantiationService.createInstance(ExtensionTipsService); + return testObject.loadWorkspaceConfigPromise.then(() => { + const recommendations = testObject.getAllRecommendationsWithReason(); + assert.ok(!recommendations['ms-vscode.csharp']); // stored recommendation that has been globally ignored + assert.ok(recommendations['ms-python.python']); // stored recommendation + assert.ok(recommendations['mockpublisher1.mockextension1']); // workspace recommendation + assert.ok(!recommendations['mockpublisher2.mockextension2']); // workspace recommendation that has been globally ignored + }); + }); + }); + + test('ExtensionTipsService: No Recommendations of workspace ignored recommendations', () => { + const ignoredRecommendations = ['ms-vscode.csharp', 'mockpublisher2.mockextension2']; // ignore a stored recommendation and a workspace recommendation. + const storedRecommendations = '["ms-vscode.csharp", "ms-python.python"]'; + instantiationService.stub(IStorageService, >{ + get: (a: string, b: StorageScope, c?: string) => a === 'extensionsAssistant/recommendations' ? storedRecommendations : c, + getBoolean: (a: string, _: StorageScope, c?: boolean) => a === 'extensionsAssistant/workspaceRecommendationsIgnore' || c + }); + + return setUpFolderWorkspace('myFolder', mockTestData.validRecommendedExtensions, ignoredRecommendations).then(() => { + testObject = instantiationService.createInstance(ExtensionTipsService); + return testObject.loadWorkspaceConfigPromise.then(() => { + const recommendations = testObject.getAllRecommendationsWithReason(); + assert.ok(!recommendations['ms-vscode.csharp']); // stored recommendation that has been workspace ignored + assert.ok(recommendations['ms-python.python']); // stored recommendation + assert.ok(recommendations['mockpublisher1.mockextension1']); // workspace recommendation + assert.ok(!recommendations['mockpublisher2.mockextension2']); // workspace recommendation that has been workspace ignored + }); + }); + }); + + test('ExtensionTipsService: Able to retrieve collection of all ignored recommendations', () => { + + const storageGetterStub = (a: string, _: StorageScope, c?: string) => { + const storedRecommendations = '["ms-vscode.csharp", "ms-python.python"]'; + const globallyIgnoredRecommendations = '["mockpublisher2.mockextension2"]'; // ignore a workspace recommendation. + if (a === 'extensionsAssistant/recommendations') { return storedRecommendations; } + if (a === 'extensionsAssistant/ignored_recommendations') { return globallyIgnoredRecommendations; } + return c; + }; + + const workspaceIgnoredRecommendations = ['ms-vscode.csharp']; // ignore a stored recommendation and a workspace recommendation. + instantiationService.stub(IStorageService, >{ + get: storageGetterStub, + getBoolean: (a: string, _: StorageScope, c?: boolean) => a === 'extensionsAssistant/workspaceRecommendationsIgnore' || c + }); + + return setUpFolderWorkspace('myFolder', mockTestData.validRecommendedExtensions, workspaceIgnoredRecommendations).then(() => { + testObject = instantiationService.createInstance(ExtensionTipsService); + return testObject.loadWorkspaceConfigPromise.then(() => { + const recommendations = testObject.getAllRecommendationsWithReason(); + assert.ok(recommendations['ms-python.python']); + + assert.ok(!recommendations['mockpublisher2.mockextension2']); + assert.ok(!recommendations['ms-vscode.csharp']); + }); + }); + }); + + test('ExtensionTipsService: Able to dynamically ignore/unignore global recommendations', () => { + const storageGetterStub = (a: string, _: StorageScope, c?: string) => { + const storedRecommendations = '["ms-vscode.csharp", "ms-python.python"]'; + const globallyIgnoredRecommendations = '["mockpublisher2.mockextension2"]'; // ignore a workspace recommendation. + if (a === 'extensionsAssistant/recommendations') { return storedRecommendations; } + if (a === 'extensionsAssistant/ignored_recommendations') { return globallyIgnoredRecommendations; } + return c; + }; + + instantiationService.stub(IStorageService, >{ + get: storageGetterStub, + store: () => { }, + getBoolean: (a: string, _: StorageScope, c?: boolean) => a === 'extensionsAssistant/workspaceRecommendationsIgnore' || c + }); + + return setUpFolderWorkspace('myFolder', mockTestData.validRecommendedExtensions).then(() => { + testObject = instantiationService.createInstance(ExtensionTipsService); + return testObject.loadWorkspaceConfigPromise.then(() => { + const recommendations = testObject.getAllRecommendationsWithReason(); + assert.ok(recommendations['ms-python.python']); + assert.ok(recommendations['mockpublisher1.mockextension1']); + + assert.ok(!recommendations['mockpublisher2.mockextension2']); + + return testObject.toggleIgnoredRecommendation('mockpublisher1.mockextension1', true); + }).then(() => { + const recommendations = testObject.getAllRecommendationsWithReason(); + assert.ok(recommendations['ms-python.python']); + + assert.ok(!recommendations['mockpublisher1.mockextension1']); + assert.ok(!recommendations['mockpublisher2.mockextension2']); + + return testObject.toggleIgnoredRecommendation('mockpublisher1.mockextension1', false); + }).then(() => { + const recommendations = testObject.getAllRecommendationsWithReason(); + assert.ok(recommendations['ms-python.python']); + + assert.ok(recommendations['mockpublisher1.mockextension1']); + assert.ok(!recommendations['mockpublisher2.mockextension2']); + }); + }); + }); + + test('test global extensions are modified and recommendation change event is fired when an extension is ignored', () => { + const storageSetterTarget = sinon.spy(); + const changeHandlerTarget = sinon.spy(); + const ignoredExtensionId = 'Some.Extension'; + instantiationService.stub(IStorageService, { // {{SQL CARBON EDIT}} strict-null-checks? + get: (a: string, b: StorageScope, c?: boolean) => a === 'extensionsAssistant/ignored_recommendations' ? '["ms-vscode.vscode"]' : c, + store: (...args: any[]) => { + storageSetterTarget(...args); + } + }); + + return setUpFolderWorkspace('myFolder', []).then(() => { + testObject = instantiationService.createInstance(ExtensionTipsService); + testObject.onRecommendationChange(changeHandlerTarget); + testObject.toggleIgnoredRecommendation(ignoredExtensionId, true); + + assert.ok(changeHandlerTarget.calledOnce); + assert.ok(changeHandlerTarget.getCall(0).calledWithMatch({ extensionId: 'Some.Extension', isRecommended: false })); + assert.ok(storageSetterTarget.calledWithExactly('extensionsAssistant/ignored_recommendations', `["ms-vscode.vscode","${ignoredExtensionId.toLowerCase()}"]`, StorageScope.GLOBAL)); + }); + }); + + test('ExtensionTipsService: Get file based recommendations from storage (old format)', () => { + const storedRecommendations = '["ms-vscode.csharp", "ms-python.python", "ms-vscode.vscode-typescript-tslint-plugin"]'; + instantiationService.stub(IStorageService, >{ get: (a: string, b: StorageScope, c?: string) => a === 'extensionsAssistant/recommendations' ? storedRecommendations : c }); + + return setUpFolderWorkspace('myFolder', []).then(() => { + testObject = instantiationService.createInstance(ExtensionTipsService); + return testObject.loadWorkspaceConfigPromise.then(() => { + const recommendations = testObject.getFileBasedRecommendations(); + assert.equal(recommendations.length, 2); + assert.ok(recommendations.some(({ extensionId }) => extensionId === 'ms-vscode.csharp')); // stored recommendation that exists in product.extensionTips + assert.ok(recommendations.some(({ extensionId }) => extensionId === 'ms-python.python')); // stored recommendation that exists in product.extensionImportantTips + assert.ok(recommendations.every(({ extensionId }) => extensionId !== 'ms-vscode.vscode-typescript-tslint-plugin')); // stored recommendation that is no longer in neither product.extensionTips nor product.extensionImportantTips + }); + }); + }); + + test('ExtensionTipsService: Get file based recommendations from storage (new format)', () => { + const milliSecondsInADay = 1000 * 60 * 60 * 24; + const now = Date.now(); + const tenDaysOld = 10 * milliSecondsInADay; + const storedRecommendations = `{"ms-vscode.csharp": ${now}, "ms-python.python": ${now}, "ms-vscode.vscode-typescript-tslint-plugin": ${now}, "lukehoban.Go": ${tenDaysOld}}`; + instantiationService.stub(IStorageService, >{ get: (a: string, b: StorageScope, c?: string) => a === 'extensionsAssistant/recommendations' ? storedRecommendations : c }); + + return setUpFolderWorkspace('myFolder', []).then(() => { + testObject = instantiationService.createInstance(ExtensionTipsService); + return testObject.loadWorkspaceConfigPromise.then(() => { + const recommendations = testObject.getFileBasedRecommendations(); + assert.equal(recommendations.length, 2); + assert.ok(recommendations.some(({ extensionId }) => extensionId === 'ms-vscode.csharp')); // stored recommendation that exists in product.extensionTips + assert.ok(recommendations.some(({ extensionId }) => extensionId === 'ms-python.python')); // stored recommendation that exists in product.extensionImportantTips + assert.ok(recommendations.every(({ extensionId }) => extensionId !== 'ms-vscode.vscode-typescript-tslint-plugin')); // stored recommendation that is no longer in neither product.extensionTips nor product.extensionImportantTips + assert.ok(recommendations.every(({ extensionId }) => extensionId !== 'lukehoban.Go')); //stored recommendation that is older than a week + }); + }); }); }); diff --git a/src/vs/workbench/contrib/terminal/test/electron-browser/terminalConfigHelper.test.ts b/src/vs/workbench/contrib/terminal/test/electron-browser/terminalConfigHelper.test.ts index 7d9061a004..5d9b71d498 100644 --- a/src/vs/workbench/contrib/terminal/test/electron-browser/terminalConfigHelper.test.ts +++ b/src/vs/workbench/contrib/terminal/test/electron-browser/terminalConfigHelper.test.ts @@ -9,8 +9,228 @@ import { EDITOR_FONT_DEFAULTS } from 'vs/editor/common/config/editorOptions'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { LinuxDistro } from 'vs/workbench/contrib/terminal/common/terminal'; -suite('Workbench - TerminalConfigHelper', () => { - test('TerminalConfigHelper - getFont fontFamily', function () { - // {{SQL CARBON EDIT}} - Remove tests +suite.skip('Workbench - TerminalConfigHelper', () => { // {{SQL CARBON EDIT}} skip suite + let fixture: HTMLElement; + + setup(() => { + fixture = document.body; + }); + + // test('TerminalConfigHelper - getFont fontFamily', function () { + // const configurationService = new TestConfigurationService(); + // configurationService.setUserConfiguration('editor', { fontFamily: 'foo' }); + // configurationService.setUserConfiguration('terminal', { integrated: { fontFamily: 'bar' } }); + // const configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); + // configHelper.panelContainer = fixture; + // assert.equal(configHelper.getFont().fontFamily, 'bar', 'terminal.integrated.fontFamily should be selected over editor.fontFamily'); + // }); + + test('TerminalConfigHelper - getFont fontFamily (Linux Fedora)', function () { + const configurationService = new TestConfigurationService(); + configurationService.setUserConfiguration('editor', { fontFamily: 'foo' }); + configurationService.setUserConfiguration('terminal', { integrated: { fontFamily: null } }); + const configHelper = new TerminalConfigHelper(LinuxDistro.Fedora, configurationService, null!, null!, null!); + configHelper.panelContainer = fixture; + assert.equal(configHelper.getFont().fontFamily, '\'DejaVu Sans Mono\', monospace', 'Fedora should have its font overridden when terminal.integrated.fontFamily not set'); + }); + + test('TerminalConfigHelper - getFont fontFamily (Linux Ubuntu)', function () { + const configurationService = new TestConfigurationService(); + configurationService.setUserConfiguration('editor', { fontFamily: 'foo' }); + configurationService.setUserConfiguration('terminal', { integrated: { fontFamily: null } }); + const configHelper = new TerminalConfigHelper(LinuxDistro.Ubuntu, configurationService, null!, null!, null!); + configHelper.panelContainer = fixture; + assert.equal(configHelper.getFont().fontFamily, '\'Ubuntu Mono\', monospace', 'Ubuntu should have its font overridden when terminal.integrated.fontFamily not set'); + }); + + test('TerminalConfigHelper - getFont fontFamily (Linux Unknown)', function () { + const configurationService = new TestConfigurationService(); + configurationService.setUserConfiguration('editor', { fontFamily: 'foo' }); + configurationService.setUserConfiguration('terminal', { integrated: { fontFamily: null } }); + const configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); + configHelper.panelContainer = fixture; + assert.equal(configHelper.getFont().fontFamily, 'foo', 'editor.fontFamily should be the fallback when terminal.integrated.fontFamily not set'); + }); + + test('TerminalConfigHelper - getFont fontSize', function () { + const configurationService = new TestConfigurationService(); + + configurationService.setUserConfiguration('editor', { + fontFamily: 'foo', + fontSize: 9 + }); + configurationService.setUserConfiguration('terminal', { + integrated: { + fontFamily: 'bar', + fontSize: 10 + } + }); + let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); + configHelper.panelContainer = fixture; + assert.equal(configHelper.getFont().fontSize, 10, 'terminal.integrated.fontSize should be selected over editor.fontSize'); + + configurationService.setUserConfiguration('editor', { + fontFamily: 'foo' + }); + configurationService.setUserConfiguration('terminal', { + integrated: { + fontFamily: null, + fontSize: 0 + } + }); + configHelper = new TerminalConfigHelper(LinuxDistro.Ubuntu, configurationService, null!, null!, null!); + configHelper.panelContainer = fixture; + assert.equal(configHelper.getFont().fontSize, 8, 'The minimum terminal font size (with adjustment) should be used when terminal.integrated.fontSize less than it'); + + configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); + configHelper.panelContainer = fixture; + assert.equal(configHelper.getFont().fontSize, 6, 'The minimum terminal font size should be used when terminal.integrated.fontSize less than it'); + + configurationService.setUserConfiguration('editor', { + fontFamily: 'foo' + }); + configurationService.setUserConfiguration('terminal', { + integrated: { + fontFamily: 0, + fontSize: 1500 + } + }); + configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); + configHelper.panelContainer = fixture; + assert.equal(configHelper.getFont().fontSize, 25, 'The maximum terminal font size should be used when terminal.integrated.fontSize more than it'); + + configurationService.setUserConfiguration('editor', { + fontFamily: 'foo' + }); + configurationService.setUserConfiguration('terminal', { + integrated: { + fontFamily: 0, + fontSize: null + } + }); + configHelper = new TerminalConfigHelper(LinuxDistro.Ubuntu, configurationService, null!, null!, null!); + configHelper.panelContainer = fixture; + assert.equal(configHelper.getFont().fontSize, EDITOR_FONT_DEFAULTS.fontSize + 2, 'The default editor font size (with adjustment) should be used when terminal.integrated.fontSize is not set'); + + configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); + configHelper.panelContainer = fixture; + assert.equal(configHelper.getFont().fontSize, EDITOR_FONT_DEFAULTS.fontSize, 'The default editor font size should be used when terminal.integrated.fontSize is not set'); + }); + + test('TerminalConfigHelper - getFont lineHeight', function () { + const configurationService = new TestConfigurationService(); + + configurationService.setUserConfiguration('editor', { + fontFamily: 'foo', + lineHeight: 1 + }); + configurationService.setUserConfiguration('terminal', { + integrated: { + fontFamily: 0, + lineHeight: 2 + } + }); + let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); + configHelper.panelContainer = fixture; + assert.equal(configHelper.getFont().lineHeight, 2, 'terminal.integrated.lineHeight should be selected over editor.lineHeight'); + + configurationService.setUserConfiguration('editor', { + fontFamily: 'foo', + lineHeight: 1 + }); + configurationService.setUserConfiguration('terminal', { + integrated: { + fontFamily: 0, + lineHeight: 0 + } + }); + configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); + configHelper.panelContainer = fixture; + assert.equal(configHelper.getFont().lineHeight, 1, 'editor.lineHeight should be 1 when terminal.integrated.lineHeight not set'); + }); + + test('TerminalConfigHelper - isMonospace monospace', function () { + const configurationService = new TestConfigurationService(); + configurationService.setUserConfiguration('terminal', { + integrated: { + fontFamily: 'monospace' + } + }); + + let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); + configHelper.panelContainer = fixture; + assert.equal(configHelper.configFontIsMonospace(), true, 'monospace is monospaced'); + }); + + test('TerminalConfigHelper - isMonospace sans-serif', function () { + const configurationService = new TestConfigurationService(); + configurationService.setUserConfiguration('terminal', { + integrated: { + fontFamily: 'sans-serif' + } + }); + let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); + configHelper.panelContainer = fixture; + assert.equal(configHelper.configFontIsMonospace(), false, 'sans-serif is not monospaced'); + }); + + test('TerminalConfigHelper - isMonospace serif', function () { + const configurationService = new TestConfigurationService(); + configurationService.setUserConfiguration('terminal', { + integrated: { + fontFamily: 'serif' + } + }); + let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); + configHelper.panelContainer = fixture; + assert.equal(configHelper.configFontIsMonospace(), false, 'serif is not monospaced'); + }); + + test('TerminalConfigHelper - isMonospace monospace falls back to editor.fontFamily', function () { + const configurationService = new TestConfigurationService(); + configurationService.setUserConfiguration('editor', { + fontFamily: 'monospace' + }); + configurationService.setUserConfiguration('terminal', { + integrated: { + fontFamily: null + } + }); + + let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); + configHelper.panelContainer = fixture; + assert.equal(configHelper.configFontIsMonospace(), true, 'monospace is monospaced'); + }); + + test('TerminalConfigHelper - isMonospace sans-serif falls back to editor.fontFamily', function () { + const configurationService = new TestConfigurationService(); + configurationService.setUserConfiguration('editor', { + fontFamily: 'sans-serif' + }); + configurationService.setUserConfiguration('terminal', { + integrated: { + fontFamily: null + } + }); + + let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); + configHelper.panelContainer = fixture; + assert.equal(configHelper.configFontIsMonospace(), false, 'sans-serif is not monospaced'); + }); + + test('TerminalConfigHelper - isMonospace serif falls back to editor.fontFamily', function () { + const configurationService = new TestConfigurationService(); + configurationService.setUserConfiguration('editor', { + fontFamily: 'serif' + }); + configurationService.setUserConfiguration('terminal', { + integrated: { + fontFamily: null + } + }); + + let configHelper = new TerminalConfigHelper(LinuxDistro.Unknown, configurationService, null!, null!, null!); + configHelper.panelContainer = fixture; + assert.equal(configHelper.configFontIsMonospace(), false, 'serif is not monospaced'); }); }); diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts index bd644021b1..65f70f5f5e 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts @@ -66,8 +66,7 @@ function setUpFolderWorkspace(folderName: string): Promise<{ parentDir: string, function setUpFolder(folderName: string, parentDir: string): Promise { const folderDir = path.join(parentDir, folderName); - // {{SQL CARBON EDIT}} - const workspaceSettingsDir = path.join(folderDir, '.azuredatastudio'); + const workspaceSettingsDir = path.join(folderDir, '.azuredatastudio'); // {{SQL CARBON EDIT}} .vscode to .azuredatastudio return Promise.resolve(pfs.mkdirp(workspaceSettingsDir, 493).then(() => folderDir)); } @@ -96,23 +95,1353 @@ function setUpWorkspace(folders: string[]): Promise<{ parentDir: string, configP } -suite('WorkspaceContextService - Folder', () => { +suite.skip('WorkspaceContextService - Folder', () => { // {{SQL CARBON EDIT}} skip suite + + let workspaceName = `testWorkspace${uuid.generateUuid()}`, parentResource: string, workspaceResource: string, workspaceContextService: IWorkspaceContextService; + setup(() => { - // {{SQL CARBON EDIT}} - Remove tests + return setUpFolderWorkspace(workspaceName) + .then(({ parentDir, folderDir }) => { + parentResource = parentDir; + workspaceResource = folderDir; + const environmentService = new TestEnvironmentService(URI.file(parentDir)); + const fileService = new FileService(new NullLogService()); + const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService()); + fileService.registerProvider(Schemas.file, diskFileSystemProvider); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, new DiskFileSystemProvider(new NullLogService()), environmentService)); + workspaceContextService = new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, new RemoteAgentService({}, environmentService, new RemoteAuthorityResolverService(), new SignService(undefined), new NullLogService())); + return (workspaceContextService).initialize(convertToWorkspacePayload(URI.file(folderDir))); + }); }); teardown(() => { - // {{SQL CARBON EDIT}} - Remove tests + if (workspaceContextService) { + (workspaceContextService).dispose(); + } + if (parentResource) { + return pfs.rimraf(parentResource, pfs.RimRafMode.MOVE); + } + return undefined; }); test('getWorkspace()', () => { - // {{SQL CARBON EDIT}} - Remove tests - assert.equal(0, 0); + const actual = workspaceContextService.getWorkspace(); + + assert.equal(actual.folders.length, 1); + assert.equal(actual.folders[0].uri.fsPath, URI.file(workspaceResource).fsPath); + assert.equal(actual.folders[0].name, workspaceName); + assert.equal(actual.folders[0].index, 0); + assert.ok(!actual.configuration); + }); + + test('getWorkbenchState()', () => { + const actual = workspaceContextService.getWorkbenchState(); + + assert.equal(actual, WorkbenchState.FOLDER); + }); + + test('getWorkspaceFolder()', () => { + const actual = workspaceContextService.getWorkspaceFolder(URI.file(path.join(workspaceResource, 'a'))); + + assert.equal(actual, workspaceContextService.getWorkspace().folders[0]); + }); + + test('isCurrentWorkspace() => true', () => { + assert.ok(workspaceContextService.isCurrentWorkspace(URI.file(workspaceResource))); + }); + + test('isCurrentWorkspace() => false', () => { + assert.ok(!workspaceContextService.isCurrentWorkspace(URI.file(workspaceResource + 'abc'))); + }); + + test('workspace is complete', () => workspaceContextService.getCompleteWorkspace()); +}); + +suite.skip('WorkspaceContextService - Workspace', () => { // {{SQL CARBON EDIT}} skip suite + + let parentResource: string, testObject: WorkspaceService, instantiationService: TestInstantiationService; + + setup(() => { + return setUpWorkspace(['a', 'b']) + .then(({ parentDir, configPath }) => { + + parentResource = parentDir; + + instantiationService = workbenchInstantiationService(); + const environmentService = new TestEnvironmentService(URI.file(parentDir)); + const remoteAgentService = instantiationService.createInstance(RemoteAgentService, {}); + instantiationService.stub(IRemoteAgentService, remoteAgentService); + const fileService = new FileService(new NullLogService()); + const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService()); + fileService.registerProvider(Schemas.file, diskFileSystemProvider); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService)); + const workspaceService = new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, remoteAgentService); + + instantiationService.stub(IWorkspaceContextService, workspaceService); + instantiationService.stub(IConfigurationService, workspaceService); + instantiationService.stub(IEnvironmentService, environmentService); + + return workspaceService.initialize(getWorkspaceIdentifier(configPath)).then(() => { + workspaceService.acquireInstantiationService(instantiationService); + testObject = workspaceService; + }); + }); + }); + + teardown(() => { + if (testObject) { + (testObject).dispose(); + } + if (parentResource) { + return pfs.rimraf(parentResource, pfs.RimRafMode.MOVE); + } + return undefined; + }); + + test('workspace folders', () => { + const actual = testObject.getWorkspace().folders; + + assert.equal(actual.length, 2); + assert.equal(path.basename(actual[0].uri.fsPath), 'a'); + assert.equal(path.basename(actual[1].uri.fsPath), 'b'); + }); + + test('getWorkbenchState()', () => { + const actual = testObject.getWorkbenchState(); + + assert.equal(actual, WorkbenchState.WORKSPACE); + }); + + + test('workspace is complete', () => testObject.getCompleteWorkspace()); + +}); + +suite.skip('WorkspaceContextService - Workspace Editing', () => { // {{SQL CARBON EDIT}} skip suite + + let parentResource: string, testObject: WorkspaceService, instantiationService: TestInstantiationService; + + setup(() => { + return setUpWorkspace(['a', 'b']) + .then(({ parentDir, configPath }) => { + + parentResource = parentDir; + + instantiationService = workbenchInstantiationService(); + const environmentService = new TestEnvironmentService(URI.file(parentDir)); + const remoteAgentService = instantiationService.createInstance(RemoteAgentService, {}); + instantiationService.stub(IRemoteAgentService, remoteAgentService); + const fileService = new FileService(new NullLogService()); + const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService()); + fileService.registerProvider(Schemas.file, diskFileSystemProvider); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService)); + const workspaceService = new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, remoteAgentService); + + instantiationService.stub(IWorkspaceContextService, workspaceService); + instantiationService.stub(IConfigurationService, workspaceService); + instantiationService.stub(IEnvironmentService, environmentService); + + return workspaceService.initialize(getWorkspaceIdentifier(configPath)).then(() => { + instantiationService.stub(IFileService, fileService); + instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); + instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); + workspaceService.acquireInstantiationService(instantiationService); + + testObject = workspaceService; + }); + }); + }); + + teardown(() => { + if (testObject) { + (testObject).dispose(); + } + if (parentResource) { + return pfs.rimraf(parentResource, pfs.RimRafMode.MOVE); + } + return undefined; + }); + + test('add folders', () => { + const workspaceDir = path.dirname(testObject.getWorkspace().folders[0].uri.fsPath); + return testObject.addFolders([{ uri: URI.file(path.join(workspaceDir, 'd')) }, { uri: URI.file(path.join(workspaceDir, 'c')) }]) + .then(() => { + const actual = testObject.getWorkspace().folders; + + assert.equal(actual.length, 4); + assert.equal(path.basename(actual[0].uri.fsPath), 'a'); + assert.equal(path.basename(actual[1].uri.fsPath), 'b'); + assert.equal(path.basename(actual[2].uri.fsPath), 'd'); + assert.equal(path.basename(actual[3].uri.fsPath), 'c'); + }); + }); + + test('add folders (at specific index)', () => { + const workspaceDir = path.dirname(testObject.getWorkspace().folders[0].uri.fsPath); + return testObject.addFolders([{ uri: URI.file(path.join(workspaceDir, 'd')) }, { uri: URI.file(path.join(workspaceDir, 'c')) }], 0) + .then(() => { + const actual = testObject.getWorkspace().folders; + + assert.equal(actual.length, 4); + assert.equal(path.basename(actual[0].uri.fsPath), 'd'); + assert.equal(path.basename(actual[1].uri.fsPath), 'c'); + assert.equal(path.basename(actual[2].uri.fsPath), 'a'); + assert.equal(path.basename(actual[3].uri.fsPath), 'b'); + }); + }); + + test('add folders (at specific wrong index)', () => { + const workspaceDir = path.dirname(testObject.getWorkspace().folders[0].uri.fsPath); + return testObject.addFolders([{ uri: URI.file(path.join(workspaceDir, 'd')) }, { uri: URI.file(path.join(workspaceDir, 'c')) }], 10) + .then(() => { + const actual = testObject.getWorkspace().folders; + + assert.equal(actual.length, 4); + assert.equal(path.basename(actual[0].uri.fsPath), 'a'); + assert.equal(path.basename(actual[1].uri.fsPath), 'b'); + assert.equal(path.basename(actual[2].uri.fsPath), 'd'); + assert.equal(path.basename(actual[3].uri.fsPath), 'c'); + }); + }); + + test('add folders (with name)', () => { + const workspaceDir = path.dirname(testObject.getWorkspace().folders[0].uri.fsPath); + return testObject.addFolders([{ uri: URI.file(path.join(workspaceDir, 'd')), name: 'DDD' }, { uri: URI.file(path.join(workspaceDir, 'c')), name: 'CCC' }]) + .then(() => { + const actual = testObject.getWorkspace().folders; + + assert.equal(actual.length, 4); + assert.equal(path.basename(actual[0].uri.fsPath), 'a'); + assert.equal(path.basename(actual[1].uri.fsPath), 'b'); + assert.equal(path.basename(actual[2].uri.fsPath), 'd'); + assert.equal(path.basename(actual[3].uri.fsPath), 'c'); + assert.equal(actual[2].name, 'DDD'); + assert.equal(actual[3].name, 'CCC'); + }); + }); + + test('add folders triggers change event', () => { + const target = sinon.spy(); + testObject.onDidChangeWorkspaceFolders(target); + const workspaceDir = path.dirname(testObject.getWorkspace().folders[0].uri.fsPath); + const addedFolders = [{ uri: URI.file(path.join(workspaceDir, 'd')) }, { uri: URI.file(path.join(workspaceDir, 'c')) }]; + return testObject.addFolders(addedFolders) + .then(() => { + assert.equal(target.callCount, 1, `Should be called only once but called ${target.callCount} times`); + const actual = target.args[0][0]; + assert.deepEqual(actual.added.map(r => r.uri.toString()), addedFolders.map(a => a.uri.toString())); + assert.deepEqual(actual.removed, []); + assert.deepEqual(actual.changed, []); + }); + }); + + test('remove folders', () => { + return testObject.removeFolders([testObject.getWorkspace().folders[0].uri]) + .then(() => { + const actual = testObject.getWorkspace().folders; + assert.equal(actual.length, 1); + assert.equal(path.basename(actual[0].uri.fsPath), 'b'); + }); + }); + + test('remove folders triggers change event', () => { + const target = sinon.spy(); + testObject.onDidChangeWorkspaceFolders(target); + const removedFolder = testObject.getWorkspace().folders[0]; + return testObject.removeFolders([removedFolder.uri]) + .then(() => { + assert.equal(target.callCount, 1, `Should be called only once but called ${target.callCount} times`); + const actual = target.args[0][0]; + assert.deepEqual(actual.added, []); + assert.deepEqual(actual.removed.map(r => r.uri.toString()), [removedFolder.uri.toString()]); + assert.deepEqual(actual.changed.map(c => c.uri.toString()), [testObject.getWorkspace().folders[0].uri.toString()]); + }); + }); + + test('remove folders and add them back by writing into the file', async done => { + const folders = testObject.getWorkspace().folders; + await testObject.removeFolders([folders[0].uri]); + + testObject.onDidChangeWorkspaceFolders(actual => { + try { + assert.deepEqual(actual.added.map(r => r.uri.toString()), [folders[0].uri.toString()]); + done(); + } catch (error) { + done(error); + } + }); + + const workspace = { folders: [{ path: folders[0].uri.fsPath }, { path: folders[1].uri.fsPath }] }; + await instantiationService.get(ITextFileService).write(testObject.getWorkspace().configuration!, JSON.stringify(workspace, null, '\t')); + }); + + test('update folders (remove last and add to end)', () => { + const target = sinon.spy(); + testObject.onDidChangeWorkspaceFolders(target); + const workspaceDir = path.dirname(testObject.getWorkspace().folders[0].uri.fsPath); + const addedFolders = [{ uri: URI.file(path.join(workspaceDir, 'd')) }, { uri: URI.file(path.join(workspaceDir, 'c')) }]; + const removedFolders = [testObject.getWorkspace().folders[1]].map(f => f.uri); + return testObject.updateFolders(addedFolders, removedFolders) + .then(() => { + assert.equal(target.callCount, 1, `Should be called only once but called ${target.callCount} times`); + const actual = target.args[0][0]; + assert.deepEqual(actual.added.map(r => r.uri.toString()), addedFolders.map(a => a.uri.toString())); + assert.deepEqual(actual.removed.map(r => r.uri.toString()), removedFolders.map(a => a.toString())); + assert.deepEqual(actual.changed, []); + }); + }); + + test('update folders (rename first via add and remove)', () => { + const target = sinon.spy(); + testObject.onDidChangeWorkspaceFolders(target); + const workspaceDir = path.dirname(testObject.getWorkspace().folders[0].uri.fsPath); + const addedFolders = [{ uri: URI.file(path.join(workspaceDir, 'a')), name: 'The Folder' }]; + const removedFolders = [testObject.getWorkspace().folders[0]].map(f => f.uri); + return testObject.updateFolders(addedFolders, removedFolders, 0) + .then(() => { + assert.equal(target.callCount, 1, `Should be called only once but called ${target.callCount} times`); + const actual = target.args[0][0]; + assert.deepEqual(actual.added, []); + assert.deepEqual(actual.removed, []); + assert.deepEqual(actual.changed.map(r => r.uri.toString()), removedFolders.map(a => a.toString())); + }); + }); + + test('update folders (remove first and add to end)', () => { + const target = sinon.spy(); + testObject.onDidChangeWorkspaceFolders(target); + const workspaceDir = path.dirname(testObject.getWorkspace().folders[0].uri.fsPath); + const addedFolders = [{ uri: URI.file(path.join(workspaceDir, 'd')) }, { uri: URI.file(path.join(workspaceDir, 'c')) }]; + const removedFolders = [testObject.getWorkspace().folders[0]].map(f => f.uri); + const changedFolders = [testObject.getWorkspace().folders[1]].map(f => f.uri); + return testObject.updateFolders(addedFolders, removedFolders) + .then(() => { + assert.equal(target.callCount, 1, `Should be called only once but called ${target.callCount} times`); + const actual = target.args[0][0]; + assert.deepEqual(actual.added.map(r => r.uri.toString()), addedFolders.map(a => a.uri.toString())); + assert.deepEqual(actual.removed.map(r => r.uri.toString()), removedFolders.map(a => a.toString())); + assert.deepEqual(actual.changed.map(r => r.uri.toString()), changedFolders.map(a => a.toString())); + }); + }); + + test('reorder folders trigger change event', () => { + const target = sinon.spy(); + testObject.onDidChangeWorkspaceFolders(target); + const workspace = { folders: [{ path: testObject.getWorkspace().folders[1].uri.fsPath }, { path: testObject.getWorkspace().folders[0].uri.fsPath }] }; + fs.writeFileSync(testObject.getWorkspace().configuration!.fsPath, JSON.stringify(workspace, null, '\t')); + return testObject.reloadConfiguration() + .then(() => { + assert.equal(target.callCount, 1, `Should be called only once but called ${target.callCount} times`); + const actual = target.args[0][0]; + assert.deepEqual(actual.added, []); + assert.deepEqual(actual.removed, []); + assert.deepEqual(actual.changed.map(c => c.uri.toString()), testObject.getWorkspace().folders.map(f => f.uri.toString()).reverse()); + }); + }); + + test('rename folders trigger change event', () => { + const target = sinon.spy(); + testObject.onDidChangeWorkspaceFolders(target); + const workspace = { folders: [{ path: testObject.getWorkspace().folders[0].uri.fsPath, name: '1' }, { path: testObject.getWorkspace().folders[1].uri.fsPath }] }; + fs.writeFileSync(testObject.getWorkspace().configuration!.fsPath, JSON.stringify(workspace, null, '\t')); + return testObject.reloadConfiguration() + .then(() => { + assert.equal(target.callCount, 1, `Should be called only once but called ${target.callCount} times`); + const actual = target.args[0][0]; + assert.deepEqual(actual.added, []); + assert.deepEqual(actual.removed, []); + assert.deepEqual(actual.changed.map(c => c.uri.toString()), [testObject.getWorkspace().folders[0].uri.toString()]); + }); + }); + +}); + +suite.skip('WorkspaceService - Initialization', () => { // {{SQL CARBON EDIT}} skip suite + + let parentResource: string, workspaceConfigPath: URI, testObject: WorkspaceService, globalSettingsFile: string; + const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); + + suiteSetup(() => { + configurationRegistry.registerConfiguration({ + 'id': '_test', + 'type': 'object', + 'properties': { + 'initialization.testSetting1': { + 'type': 'string', + 'default': 'isSet', + scope: ConfigurationScope.RESOURCE + }, + 'initialization.testSetting2': { + 'type': 'string', + 'default': 'isSet', + scope: ConfigurationScope.RESOURCE + } + } + }); + }); + + setup(() => { + return setUpWorkspace(['1', '2']) + .then(({ parentDir, configPath }) => { + + parentResource = parentDir; + workspaceConfigPath = configPath; + globalSettingsFile = path.join(parentDir, 'settings.json'); + + const instantiationService = workbenchInstantiationService(); + const environmentService = new TestEnvironmentService(URI.file(parentDir)); + const remoteAgentService = instantiationService.createInstance(RemoteAgentService, {}); + instantiationService.stub(IRemoteAgentService, remoteAgentService); + const fileService = new FileService(new NullLogService()); + const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService()); + fileService.registerProvider(Schemas.file, diskFileSystemProvider); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService)); + const workspaceService = new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, remoteAgentService); + instantiationService.stub(IWorkspaceContextService, workspaceService); + instantiationService.stub(IConfigurationService, workspaceService); + instantiationService.stub(IEnvironmentService, environmentService); + + return workspaceService.initialize({ id: '' }).then(() => { + instantiationService.stub(IFileService, fileService); + instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); + instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); + workspaceService.acquireInstantiationService(instantiationService); + testObject = workspaceService; + }); + }); + }); + + teardown(() => { + if (testObject) { + (testObject).dispose(); + } + if (parentResource) { + return pfs.rimraf(parentResource, pfs.RimRafMode.MOVE); + } + return undefined; + }); + + test('initialize a folder workspace from an empty workspace with no configuration changes', () => { + + fs.writeFileSync(globalSettingsFile, '{ "initialization.testSetting1": "userValue" }'); + + return testObject.reloadConfiguration() + .then(() => { + const target = sinon.spy(); + testObject.onDidChangeWorkbenchState(target); + testObject.onDidChangeWorkspaceName(target); + testObject.onDidChangeWorkspaceFolders(target); + testObject.onDidChangeConfiguration(target); + + return testObject.initialize(convertToWorkspacePayload(URI.file(path.join(parentResource, '1')))) + .then(() => { + assert.equal(testObject.getValue('initialization.testSetting1'), 'userValue'); + assert.equal(target.callCount, 3); + assert.deepEqual(target.args[0], [WorkbenchState.FOLDER]); + assert.deepEqual(target.args[1], [undefined]); + assert.deepEqual((target.args[2][0]).added.map(folder => folder.uri.fsPath), [URI.file(path.join(parentResource, '1')).fsPath]); + assert.deepEqual((target.args[2][0]).removed, []); + assert.deepEqual((target.args[2][0]).changed, []); + }); + + }); + + }); + + test('initialize a folder workspace from an empty workspace with configuration changes', () => { + + fs.writeFileSync(globalSettingsFile, '{ "initialization.testSetting1": "userValue" }'); + + return testObject.reloadConfiguration() + .then(() => { + const target = sinon.spy(); + testObject.onDidChangeWorkbenchState(target); + testObject.onDidChangeWorkspaceName(target); + testObject.onDidChangeWorkspaceFolders(target); + testObject.onDidChangeConfiguration(target); + + fs.writeFileSync(path.join(parentResource, '1', '.vscode', 'settings.json'), '{ "initialization.testSetting1": "workspaceValue" }'); + + return testObject.initialize(convertToWorkspacePayload(URI.file(path.join(parentResource, '1')))) + .then(() => { + assert.equal(testObject.getValue('initialization.testSetting1'), 'workspaceValue'); + assert.equal(target.callCount, 4); + assert.deepEqual((target.args[0][0]).affectedKeys, ['initialization.testSetting1']); + assert.deepEqual(target.args[1], [WorkbenchState.FOLDER]); + assert.deepEqual(target.args[2], [undefined]); + assert.deepEqual((target.args[3][0]).added.map(folder => folder.uri.fsPath), [URI.file(path.join(parentResource, '1')).fsPath]); + assert.deepEqual((target.args[3][0]).removed, []); + assert.deepEqual((target.args[3][0]).changed, []); + }); + + }); + + }); + + test('initialize a multi root workspace from an empty workspace with no configuration changes', () => { + + fs.writeFileSync(globalSettingsFile, '{ "initialization.testSetting1": "userValue" }'); + + return testObject.reloadConfiguration() + .then(() => { + const target = sinon.spy(); + testObject.onDidChangeWorkbenchState(target); + testObject.onDidChangeWorkspaceName(target); + testObject.onDidChangeWorkspaceFolders(target); + testObject.onDidChangeConfiguration(target); + + return testObject.initialize(getWorkspaceIdentifier(workspaceConfigPath)) + .then(() => { + assert.equal(target.callCount, 3); + assert.deepEqual(target.args[0], [WorkbenchState.WORKSPACE]); + assert.deepEqual(target.args[1], [undefined]); + assert.deepEqual((target.args[2][0]).added.map(folder => folder.uri.fsPath), [URI.file(path.join(parentResource, '1')).fsPath, URI.file(path.join(parentResource, '2')).fsPath]); + assert.deepEqual((target.args[2][0]).removed, []); + assert.deepEqual((target.args[2][0]).changed, []); + }); + + }); + + }); + + test('initialize a multi root workspace from an empty workspace with configuration changes', () => { + + fs.writeFileSync(globalSettingsFile, '{ "initialization.testSetting1": "userValue" }'); + + return testObject.reloadConfiguration() + .then(() => { + const target = sinon.spy(); + testObject.onDidChangeWorkbenchState(target); + testObject.onDidChangeWorkspaceName(target); + testObject.onDidChangeWorkspaceFolders(target); + testObject.onDidChangeConfiguration(target); + + fs.writeFileSync(path.join(parentResource, '1', '.vscode', 'settings.json'), '{ "initialization.testSetting1": "workspaceValue1" }'); + fs.writeFileSync(path.join(parentResource, '2', '.vscode', 'settings.json'), '{ "initialization.testSetting2": "workspaceValue2" }'); + + return testObject.initialize(getWorkspaceIdentifier(workspaceConfigPath)) + .then(() => { + assert.equal(target.callCount, 4); + assert.deepEqual((target.args[0][0]).affectedKeys, ['initialization.testSetting1', 'initialization.testSetting2']); + assert.deepEqual(target.args[1], [WorkbenchState.WORKSPACE]); + assert.deepEqual(target.args[2], [undefined]); + assert.deepEqual((target.args[3][0]).added.map(folder => folder.uri.fsPath), [URI.file(path.join(parentResource, '1')).fsPath, URI.file(path.join(parentResource, '2')).fsPath]); + assert.deepEqual((target.args[3][0]).removed, []); + assert.deepEqual((target.args[3][0]).changed, []); + }); + + }); + + }); + + test('initialize a folder workspace from a folder workspace with no configuration changes', () => { + + return testObject.initialize(convertToWorkspacePayload(URI.file(path.join(parentResource, '1')))) + .then(() => { + fs.writeFileSync(globalSettingsFile, '{ "initialization.testSetting1": "userValue" }'); + + return testObject.reloadConfiguration() + .then(() => { + const target = sinon.spy(); + testObject.onDidChangeWorkbenchState(target); + testObject.onDidChangeWorkspaceName(target); + testObject.onDidChangeWorkspaceFolders(target); + testObject.onDidChangeConfiguration(target); + + return testObject.initialize(convertToWorkspacePayload(URI.file(path.join(parentResource, '2')))) + .then(() => { + assert.equal(testObject.getValue('initialization.testSetting1'), 'userValue'); + assert.equal(target.callCount, 1); + assert.deepEqual((target.args[0][0]).added.map(folder => folder.uri.fsPath), [URI.file(path.join(parentResource, '2')).fsPath]); + assert.deepEqual((target.args[0][0]).removed.map(folder => folder.uri.fsPath), [URI.file(path.join(parentResource, '1')).fsPath]); + assert.deepEqual((target.args[0][0]).changed, []); + }); + + }); + }); + + }); + + test('initialize a folder workspace from a folder workspace with configuration changes', () => { + + return testObject.initialize(convertToWorkspacePayload(URI.file(path.join(parentResource, '1')))) + .then(() => { + + const target = sinon.spy(); + testObject.onDidChangeWorkbenchState(target); + testObject.onDidChangeWorkspaceName(target); + testObject.onDidChangeWorkspaceFolders(target); + testObject.onDidChangeConfiguration(target); + + fs.writeFileSync(path.join(parentResource, '2', '.vscode', 'settings.json'), '{ "initialization.testSetting1": "workspaceValue2" }'); + return testObject.initialize(convertToWorkspacePayload(URI.file(path.join(parentResource, '2')))) + .then(() => { + assert.equal(testObject.getValue('initialization.testSetting1'), 'workspaceValue2'); + assert.equal(target.callCount, 2); + assert.deepEqual((target.args[0][0]).affectedKeys, ['initialization.testSetting1']); + assert.deepEqual((target.args[1][0]).added.map(folder => folder.uri.fsPath), [URI.file(path.join(parentResource, '2')).fsPath]); + assert.deepEqual((target.args[1][0]).removed.map(folder => folder.uri.fsPath), [URI.file(path.join(parentResource, '1')).fsPath]); + assert.deepEqual((target.args[1][0]).changed, []); + }); + }); + + }); + + test('initialize a multi folder workspace from a folder workspacce triggers change events in the right order', () => { + const folderDir = path.join(parentResource, '1'); + return testObject.initialize(convertToWorkspacePayload(URI.file(folderDir))) + .then(() => { + + const target = sinon.spy(); + + testObject.onDidChangeWorkbenchState(target); + testObject.onDidChangeWorkspaceName(target); + testObject.onDidChangeWorkspaceFolders(target); + testObject.onDidChangeConfiguration(target); + + fs.writeFileSync(path.join(parentResource, '1', '.vscode', 'settings.json'), '{ "initialization.testSetting1": "workspaceValue2" }'); + return testObject.initialize(getWorkspaceIdentifier(workspaceConfigPath)) + .then(() => { + assert.equal(target.callCount, 4); + assert.deepEqual((target.args[0][0]).affectedKeys, ['initialization.testSetting1']); + assert.deepEqual(target.args[1], [WorkbenchState.WORKSPACE]); + assert.deepEqual(target.args[2], [undefined]); + assert.deepEqual((target.args[3][0]).added.map(folder => folder.uri.fsPath), [URI.file(path.join(parentResource, '2')).fsPath]); + assert.deepEqual((target.args[3][0]).removed, []); + assert.deepEqual((target.args[3][0]).changed, []); + }); + }); + }); + +}); + +suite.skip('WorkspaceConfigurationService - Folder', () => { // {{SQL CARBON EDIT}} skip suite + + let workspaceName = `testWorkspace${uuid.generateUuid()}`, parentResource: string, workspaceDir: string, testObject: IConfigurationService, globalSettingsFile: string; + const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); + + suiteSetup(() => { + configurationRegistry.registerConfiguration({ + 'id': '_test', + 'type': 'object', + 'properties': { + 'configurationService.folder.applicationSetting': { + 'type': 'string', + 'default': 'isSet', + scope: ConfigurationScope.APPLICATION + }, + 'configurationService.folder.machineSetting': { + 'type': 'string', + 'default': 'isSet', + scope: ConfigurationScope.MACHINE + }, + 'configurationService.folder.testSetting': { + 'type': 'string', + 'default': 'isSet', + scope: ConfigurationScope.RESOURCE + } + } + }); + }); + + setup(() => { + return setUpFolderWorkspace(workspaceName) + .then(({ parentDir, folderDir }) => { + + parentResource = parentDir; + workspaceDir = folderDir; + globalSettingsFile = path.join(parentDir, 'settings.json'); + + const instantiationService = workbenchInstantiationService(); + const environmentService = new TestEnvironmentService(URI.file(parentDir)); + const remoteAgentService = instantiationService.createInstance(RemoteAgentService, {}); + instantiationService.stub(IRemoteAgentService, remoteAgentService); + const fileService = new FileService(new NullLogService()); + const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService()); + fileService.registerProvider(Schemas.file, diskFileSystemProvider); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService)); + const workspaceService = new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, remoteAgentService); + instantiationService.stub(IWorkspaceContextService, workspaceService); + instantiationService.stub(IConfigurationService, workspaceService); + instantiationService.stub(IEnvironmentService, environmentService); + + return workspaceService.initialize(convertToWorkspacePayload(URI.file(folderDir))).then(() => { + instantiationService.stub(IFileService, fileService); + instantiationService.stub(IKeybindingEditingService, instantiationService.createInstance(KeybindingsEditingService)); + instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); + instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); + workspaceService.acquireInstantiationService(instantiationService); + testObject = workspaceService; + }); + }); + }); + + teardown(() => { + if (testObject) { + (testObject).dispose(); + } + if (parentResource) { + return pfs.rimraf(parentResource, pfs.RimRafMode.MOVE); + } + return undefined; + }); + + test('defaults', () => { + assert.deepEqual(testObject.getValue('configurationService'), { 'folder': { 'applicationSetting': 'isSet', 'machineSetting': 'isSet', 'testSetting': 'isSet' } }); + }); + + test('globals override defaults', () => { + fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.testSetting": "userValue" }'); + return testObject.reloadConfiguration() + .then(() => assert.equal(testObject.getValue('configurationService.folder.testSetting'), 'userValue')); + }); + + test('globals', () => { + fs.writeFileSync(globalSettingsFile, '{ "testworkbench.editor.tabs": true }'); + return testObject.reloadConfiguration() + .then(() => assert.equal(testObject.getValue('testworkbench.editor.tabs'), true)); + }); + + test('workspace settings', () => { + fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "testworkbench.editor.icons": true }'); + return testObject.reloadConfiguration() + .then(() => assert.equal(testObject.getValue('testworkbench.editor.icons'), true)); + }); + + test('workspace settings override user settings', () => { + fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.testSetting": "userValue" }'); + fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.testSetting": "workspaceValue" }'); + return testObject.reloadConfiguration() + .then(() => assert.equal(testObject.getValue('configurationService.folder.testSetting'), 'workspaceValue')); + }); + + test('workspace settings override user settings after defaults are registered ', () => { + fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.newSetting": "userValue" }'); + fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.newSetting": "workspaceValue" }'); + return testObject.reloadConfiguration() + .then(() => { + + configurationRegistry.registerConfiguration({ + 'id': '_test', + 'type': 'object', + 'properties': { + 'configurationService.folder.newSetting': { + 'type': 'string', + 'default': 'isSet' + } + } + }); + + assert.equal(testObject.getValue('configurationService.folder.newSetting'), 'workspaceValue'); + }); + }); + + test('application settings are not read from workspace', () => { + fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.applicationSetting": "userValue" }'); + fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.applicationSetting": "workspaceValue" }'); + return testObject.reloadConfiguration() + .then(() => assert.equal(testObject.getValue('configurationService.folder.applicationSetting'), 'userValue')); + }); + + test('machine settings are not read from workspace', () => { + fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.machineSetting": "userValue" }'); + fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.machineSetting": "workspaceValue" }'); + return testObject.reloadConfiguration() + .then(() => assert.equal(testObject.getValue('configurationService.folder.machineSetting'), 'userValue')); + }); + + test('get application scope settings are not loaded after defaults are registered', () => { + fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.anotherApplicationSetting": "workspaceValue" }'); + return testObject.reloadConfiguration() + .then(() => { + configurationRegistry.registerConfiguration({ + 'id': '_test', + 'type': 'object', + 'properties': { + 'configurationService.folder.anotherApplicationSetting': { + 'type': 'string', + 'default': 'isSet', + scope: ConfigurationScope.APPLICATION + } + } + }); + assert.deepEqual(testObject.keys().workspace, []); + }); + }); + + test('get machine scope settings are not loaded after defaults are registered', () => { + fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.anotherMachineSetting": "workspaceValue" }'); + return testObject.reloadConfiguration() + .then(() => { + configurationRegistry.registerConfiguration({ + 'id': '_test', + 'type': 'object', + 'properties': { + 'configurationService.folder.anotherMachineSetting': { + 'type': 'string', + 'default': 'isSet', + scope: ConfigurationScope.MACHINE + } + } + }); + assert.deepEqual(testObject.keys().workspace, []); + }); + }); + + test('reload configuration emits events after global configuraiton changes', () => { + fs.writeFileSync(globalSettingsFile, '{ "testworkbench.editor.tabs": true }'); + const target = sinon.spy(); + testObject.onDidChangeConfiguration(target); + return testObject.reloadConfiguration().then(() => assert.ok(target.called)); + }); + + test('reload configuration emits events after workspace configuraiton changes', () => { + fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.testSetting": "workspaceValue" }'); + const target = sinon.spy(); + testObject.onDidChangeConfiguration(target); + return testObject.reloadConfiguration().then(() => assert.ok(target.called)); + }); + + test('reload configuration should not emit event if no changes', () => { + fs.writeFileSync(globalSettingsFile, '{ "testworkbench.editor.tabs": true }'); + fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.testSetting": "workspaceValue" }'); + return testObject.reloadConfiguration() + .then(() => { + const target = sinon.spy(); + testObject.onDidChangeConfiguration(() => { target(); }); + return testObject.reloadConfiguration() + .then(() => assert.ok(!target.called)); + }); + }); + + test('inspect', () => { + let actual = testObject.inspect('something.missing'); + assert.equal(actual.default, undefined); + assert.equal(actual.user, undefined); + assert.equal(actual.workspace, undefined); + assert.equal(actual.workspaceFolder, undefined); + assert.equal(actual.value, undefined); + + actual = testObject.inspect('configurationService.folder.testSetting'); + assert.equal(actual.default, 'isSet'); + assert.equal(actual.user, undefined); + assert.equal(actual.workspace, undefined); + assert.equal(actual.workspaceFolder, undefined); + assert.equal(actual.value, 'isSet'); + + fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.testSetting": "userValue" }'); + return testObject.reloadConfiguration() + .then(() => { + actual = testObject.inspect('configurationService.folder.testSetting'); + assert.equal(actual.default, 'isSet'); + assert.equal(actual.user, 'userValue'); + assert.equal(actual.workspace, undefined); + assert.equal(actual.workspaceFolder, undefined); + assert.equal(actual.value, 'userValue'); + + fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.testSetting": "workspaceValue" }'); + + return testObject.reloadConfiguration() + .then(() => { + actual = testObject.inspect('configurationService.folder.testSetting'); + assert.equal(actual.default, 'isSet'); + assert.equal(actual.user, 'userValue'); + assert.equal(actual.workspace, 'workspaceValue'); + assert.equal(actual.workspaceFolder, undefined); + assert.equal(actual.value, 'workspaceValue'); + }); + }); + }); + + test('keys', () => { + let actual = testObject.keys(); + assert.ok(actual.default.indexOf('configurationService.folder.testSetting') !== -1); + assert.deepEqual(actual.user, []); + assert.deepEqual(actual.workspace, []); + assert.deepEqual(actual.workspaceFolder, []); + + fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.testSetting": "userValue" }'); + return testObject.reloadConfiguration() + .then(() => { + actual = testObject.keys(); + assert.ok(actual.default.indexOf('configurationService.folder.testSetting') !== -1); + assert.deepEqual(actual.user, ['configurationService.folder.testSetting']); + assert.deepEqual(actual.workspace, []); + assert.deepEqual(actual.workspaceFolder, []); + + fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.testSetting": "workspaceValue" }'); + + return testObject.reloadConfiguration() + .then(() => { + actual = testObject.keys(); + assert.ok(actual.default.indexOf('configurationService.folder.testSetting') !== -1); + assert.deepEqual(actual.user, ['configurationService.folder.testSetting']); + assert.deepEqual(actual.workspace, ['configurationService.folder.testSetting']); + assert.deepEqual(actual.workspaceFolder, []); + }); + }); + }); + + test('update user configuration', () => { + return testObject.updateValue('configurationService.folder.testSetting', 'value', ConfigurationTarget.USER) + .then(() => assert.equal(testObject.getValue('configurationService.folder.testSetting'), 'value')); + }); + + test('update workspace configuration', () => { + return testObject.updateValue('tasks.service.testSetting', 'value', ConfigurationTarget.WORKSPACE) + .then(() => assert.equal(testObject.getValue('tasks.service.testSetting'), 'value')); + }); + + test('update application setting into workspace configuration in a workspace is not supported', () => { + return testObject.updateValue('configurationService.folder.applicationSetting', 'workspaceValue', {}, ConfigurationTarget.WORKSPACE, true) + .then(() => assert.fail('Should not be supported'), (e) => assert.equal(e.code, ConfigurationEditingErrorCode.ERROR_INVALID_WORKSPACE_CONFIGURATION_APPLICATION)); + }); + + test('update machine setting into workspace configuration in a workspace is not supported', () => { + return testObject.updateValue('configurationService.folder.machineSetting', 'workspaceValue', {}, ConfigurationTarget.WORKSPACE, true) + .then(() => assert.fail('Should not be supported'), (e) => assert.equal(e.code, ConfigurationEditingErrorCode.ERROR_INVALID_WORKSPACE_CONFIGURATION_MACHINE)); + }); + + test('update tasks configuration', () => { + return testObject.updateValue('tasks', { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] }, ConfigurationTarget.WORKSPACE) + .then(() => assert.deepEqual(testObject.getValue('tasks'), { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] })); + }); + + test('update user configuration should trigger change event before promise is resolve', () => { + const target = sinon.spy(); + testObject.onDidChangeConfiguration(target); + return testObject.updateValue('configurationService.folder.testSetting', 'value', ConfigurationTarget.USER) + .then(() => assert.ok(target.called)); + }); + + test('update workspace configuration should trigger change event before promise is resolve', () => { + const target = sinon.spy(); + testObject.onDidChangeConfiguration(target); + return testObject.updateValue('configurationService.folder.testSetting', 'value', ConfigurationTarget.WORKSPACE) + .then(() => assert.ok(target.called)); + }); + + test('update memory configuration', () => { + return testObject.updateValue('configurationService.folder.testSetting', 'memoryValue', ConfigurationTarget.MEMORY) + .then(() => assert.equal(testObject.getValue('configurationService.folder.testSetting'), 'memoryValue')); + }); + + test('update memory configuration should trigger change event before promise is resolve', () => { + const target = sinon.spy(); + testObject.onDidChangeConfiguration(target); + return testObject.updateValue('configurationService.folder.testSetting', 'memoryValue', ConfigurationTarget.MEMORY) + .then(() => assert.ok(target.called)); + }); + + test('update task configuration should trigger change event before promise is resolve', () => { + const target = sinon.spy(); + testObject.onDidChangeConfiguration(target); + return testObject.updateValue('tasks', { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] }, ConfigurationTarget.WORKSPACE) + .then(() => assert.ok(target.called)); + }); + +}); + +suite.skip('WorkspaceConfigurationService-Multiroot', () => { // {{SQL CARBON EDIT}} skip suite + + let parentResource: string, workspaceContextService: IWorkspaceContextService, jsonEditingServce: IJSONEditingService, testObject: IConfigurationService, globalSettingsFile: string; + const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration); + + suiteSetup(() => { + configurationRegistry.registerConfiguration({ + 'id': '_test', + 'type': 'object', + 'properties': { + 'configurationService.workspace.testSetting': { + 'type': 'string', + 'default': 'isSet' + }, + 'configurationService.workspace.applicationSetting': { + 'type': 'string', + 'default': 'isSet', + scope: ConfigurationScope.APPLICATION + }, + 'configurationService.workspace.machineSetting': { + 'type': 'string', + 'default': 'isSet', + scope: ConfigurationScope.MACHINE + }, + 'configurationService.workspace.testResourceSetting': { + 'type': 'string', + 'default': 'isSet', + scope: ConfigurationScope.RESOURCE + } + } + }); + }); + + setup(() => { + return setUpWorkspace(['1', '2']) + .then(({ parentDir, configPath }) => { + + parentResource = parentDir; + globalSettingsFile = path.join(parentDir, 'settings.json'); + + const instantiationService = workbenchInstantiationService(); + const environmentService = new TestEnvironmentService(URI.file(parentDir)); + const remoteAgentService = instantiationService.createInstance(RemoteAgentService, {}); + instantiationService.stub(IRemoteAgentService, remoteAgentService); + const fileService = new FileService(new NullLogService()); + const diskFileSystemProvider = new DiskFileSystemProvider(new NullLogService()); + fileService.registerProvider(Schemas.file, diskFileSystemProvider); + fileService.registerProvider(Schemas.userData, new FileUserDataProvider(environmentService.appSettingsHome, environmentService.backupHome, diskFileSystemProvider, environmentService)); + const workspaceService = new WorkspaceService({ configurationCache: new ConfigurationCache(environmentService) }, environmentService, fileService, remoteAgentService); + + instantiationService.stub(IWorkspaceContextService, workspaceService); + instantiationService.stub(IConfigurationService, workspaceService); + instantiationService.stub(IWorkbenchEnvironmentService, environmentService); + + return workspaceService.initialize(getWorkspaceIdentifier(configPath)).then(() => { + instantiationService.stub(IFileService, fileService); + instantiationService.stub(IKeybindingEditingService, instantiationService.createInstance(KeybindingsEditingService)); + instantiationService.stub(ITextFileService, instantiationService.createInstance(TestTextFileService)); + instantiationService.stub(ITextModelService, instantiationService.createInstance(TextModelResolverService)); + workspaceService.acquireInstantiationService(instantiationService); + + workspaceContextService = workspaceService; + jsonEditingServce = instantiationService.createInstance(JSONEditingService); + testObject = workspaceService; + }); + }); + }); + + teardown(() => { + if (testObject) { + (testObject).dispose(); + } + if (parentResource) { + return pfs.rimraf(parentResource, pfs.RimRafMode.MOVE); + } + return undefined; + }); + + test('application settings are not read from workspace', () => { + fs.writeFileSync(globalSettingsFile, '{ "configurationService.workspace.applicationSetting": "userValue" }'); + return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, { key: 'settings', value: { 'configurationService.workspace.applicationSetting': 'workspaceValue' } }, true) + .then(() => testObject.reloadConfiguration()) + .then(() => assert.equal(testObject.getValue('configurationService.workspace.applicationSetting'), 'userValue')); + }); + + test('machine settings are not read from workspace', () => { + fs.writeFileSync(globalSettingsFile, '{ "configurationService.workspace.machineSetting": "userValue" }'); + return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, { key: 'settings', value: { 'configurationService.workspace.machineSetting': 'workspaceValue' } }, true) + .then(() => testObject.reloadConfiguration()) + .then(() => assert.equal(testObject.getValue('configurationService.workspace.machineSetting'), 'userValue')); + }); + + test('workspace settings override user settings after defaults are registered ', () => { + fs.writeFileSync(globalSettingsFile, '{ "configurationService.workspace.newSetting": "userValue" }'); + return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, { key: 'settings', value: { 'configurationService.workspace.newSetting': 'workspaceValue' } }, true) + .then(() => testObject.reloadConfiguration()) + .then(() => { + configurationRegistry.registerConfiguration({ + 'id': '_test', + 'type': 'object', + 'properties': { + 'configurationService.workspace.newSetting': { + 'type': 'string', + 'default': 'isSet' + } + } + }); + assert.equal(testObject.getValue('configurationService.workspace.newSetting'), 'workspaceValue'); + }); + }); + + test('application settings are not read from workspace folder', () => { + fs.writeFileSync(globalSettingsFile, '{ "configurationService.workspace.applicationSetting": "userValue" }'); + fs.writeFileSync(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json').fsPath, '{ "configurationService.workspace.applicationSetting": "workspaceFolderValue" }'); + return testObject.reloadConfiguration() + .then(() => assert.equal(testObject.getValue('configurationService.workspace.applicationSetting'), 'userValue')); + }); + + test('machine settings are not read from workspace folder', () => { + fs.writeFileSync(globalSettingsFile, '{ "configurationService.workspace.machineSetting": "userValue" }'); + fs.writeFileSync(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json').fsPath, '{ "configurationService.workspace.machineSetting": "workspaceFolderValue" }'); + return testObject.reloadConfiguration() + .then(() => assert.equal(testObject.getValue('configurationService.workspace.machineSetting'), 'userValue')); + }); + + test('application settings are not read from workspace folder after defaults are registered', () => { + fs.writeFileSync(globalSettingsFile, '{ "configurationService.workspace.testNewApplicationSetting": "userValue" }'); + fs.writeFileSync(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json').fsPath, '{ "configurationService.workspace.testNewApplicationSetting": "workspaceFolderValue" }'); + return testObject.reloadConfiguration() + .then(() => { + configurationRegistry.registerConfiguration({ + 'id': '_test', + 'type': 'object', + 'properties': { + 'configurationService.workspace.testNewApplicationSetting': { + 'type': 'string', + 'default': 'isSet', + scope: ConfigurationScope.APPLICATION + } + } + }); + assert.equal(testObject.getValue('configurationService.workspace.testNewApplicationSetting', { resource: workspaceContextService.getWorkspace().folders[0].uri }), 'userValue'); + }); + }); + + test('application settings are not read from workspace folder after defaults are registered', () => { + fs.writeFileSync(globalSettingsFile, '{ "configurationService.workspace.testNewMachineSetting": "userValue" }'); + fs.writeFileSync(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json').fsPath, '{ "configurationService.workspace.testNewMachineSetting": "workspaceFolderValue" }'); + return testObject.reloadConfiguration() + .then(() => { + configurationRegistry.registerConfiguration({ + 'id': '_test', + 'type': 'object', + 'properties': { + 'configurationService.workspace.testNewMachineSetting': { + 'type': 'string', + 'default': 'isSet', + scope: ConfigurationScope.MACHINE + } + } + }); + assert.equal(testObject.getValue('configurationService.workspace.testNewMachineSetting', { resource: workspaceContextService.getWorkspace().folders[0].uri }), 'userValue'); + }); + }); + + test('resource setting in folder is read after it is registered later', () => { + fs.writeFileSync(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json').fsPath, '{ "configurationService.workspace.testNewResourceSetting2": "workspaceFolderValue" }'); + return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, { key: 'settings', value: { 'configurationService.workspace.testNewResourceSetting2': 'workspaceValue' } }, true) + .then(() => testObject.reloadConfiguration()) + .then(() => { + configurationRegistry.registerConfiguration({ + 'id': '_test', + 'type': 'object', + 'properties': { + 'configurationService.workspace.testNewResourceSetting2': { + 'type': 'string', + 'default': 'isSet', + scope: ConfigurationScope.RESOURCE + } + } + }); + assert.equal(testObject.getValue('configurationService.workspace.testNewResourceSetting2', { resource: workspaceContextService.getWorkspace().folders[0].uri }), 'workspaceFolderValue'); + }); + }); + + test('inspect', () => { + let actual = testObject.inspect('something.missing'); + assert.equal(actual.default, undefined); + assert.equal(actual.user, undefined); + assert.equal(actual.workspace, undefined); + assert.equal(actual.workspaceFolder, undefined); + assert.equal(actual.value, undefined); + + actual = testObject.inspect('configurationService.workspace.testResourceSetting'); + assert.equal(actual.default, 'isSet'); + assert.equal(actual.user, undefined); + assert.equal(actual.workspace, undefined); + assert.equal(actual.workspaceFolder, undefined); + assert.equal(actual.value, 'isSet'); + + fs.writeFileSync(globalSettingsFile, '{ "configurationService.workspace.testResourceSetting": "userValue" }'); + return testObject.reloadConfiguration() + .then(() => { + actual = testObject.inspect('configurationService.workspace.testResourceSetting'); + assert.equal(actual.default, 'isSet'); + assert.equal(actual.user, 'userValue'); + assert.equal(actual.workspace, undefined); + assert.equal(actual.workspaceFolder, undefined); + assert.equal(actual.value, 'userValue'); + + return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, { key: 'settings', value: { 'configurationService.workspace.testResourceSetting': 'workspaceValue' } }, true) + .then(() => testObject.reloadConfiguration()) + .then(() => { + actual = testObject.inspect('configurationService.workspace.testResourceSetting'); + assert.equal(actual.default, 'isSet'); + assert.equal(actual.user, 'userValue'); + assert.equal(actual.workspace, 'workspaceValue'); + assert.equal(actual.workspaceFolder, undefined); + assert.equal(actual.value, 'workspaceValue'); + + fs.writeFileSync(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json').fsPath, '{ "configurationService.workspace.testResourceSetting": "workspaceFolderValue" }'); + + return testObject.reloadConfiguration() + .then(() => { + actual = testObject.inspect('configurationService.workspace.testResourceSetting', { resource: workspaceContextService.getWorkspace().folders[0].uri }); + assert.equal(actual.default, 'isSet'); + assert.equal(actual.user, 'userValue'); + assert.equal(actual.workspace, 'workspaceValue'); + assert.equal(actual.workspaceFolder, 'workspaceFolderValue'); + assert.equal(actual.value, 'workspaceFolderValue'); + }); + }); + }); + }); + + test('get launch configuration', () => { + const expectedLaunchConfiguration = { + 'version': '0.1.0', + 'configurations': [ + { + 'type': 'node', + 'request': 'launch', + 'name': 'Gulp Build', + 'program': '${workspaceFolder}/node_modules/gulp/bin/gulp.js', + 'stopOnEntry': true, + 'args': [ + 'watch-extension:json-client' + ], + 'cwd': '${workspaceFolder}' + } + ] + }; + return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, { key: 'launch', value: expectedLaunchConfiguration }, true) + .then(() => testObject.reloadConfiguration()) + .then(() => { + const actual = testObject.getValue('launch'); + assert.deepEqual(actual, expectedLaunchConfiguration); + }); + }); + + test('inspect launch configuration', () => { + const expectedLaunchConfiguration = { + 'version': '0.1.0', + 'configurations': [ + { + 'type': 'node', + 'request': 'launch', + 'name': 'Gulp Build', + 'program': '${workspaceFolder}/node_modules/gulp/bin/gulp.js', + 'stopOnEntry': true, + 'args': [ + 'watch-extension:json-client' + ], + 'cwd': '${workspaceFolder}' + } + ] + }; + return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, { key: 'launch', value: expectedLaunchConfiguration }, true) + .then(() => testObject.reloadConfiguration()) + .then(() => { + const actual = testObject.inspect('launch').workspace; + assert.deepEqual(actual, expectedLaunchConfiguration); + }); + }); + + test('update user configuration', () => { + return testObject.updateValue('configurationService.workspace.testSetting', 'userValue', ConfigurationTarget.USER) + .then(() => assert.equal(testObject.getValue('configurationService.workspace.testSetting'), 'userValue')); + }); + + test('update user configuration should trigger change event before promise is resolve', () => { + const target = sinon.spy(); + testObject.onDidChangeConfiguration(target); + return testObject.updateValue('configurationService.workspace.testSetting', 'userValue', ConfigurationTarget.USER) + .then(() => assert.ok(target.called)); + }); + + test('update workspace configuration', () => { + return testObject.updateValue('configurationService.workspace.testSetting', 'workspaceValue', ConfigurationTarget.WORKSPACE) + .then(() => assert.equal(testObject.getValue('configurationService.workspace.testSetting'), 'workspaceValue')); + }); + + test('update workspace configuration should trigger change event before promise is resolve', () => { + const target = sinon.spy(); + testObject.onDidChangeConfiguration(target); + return testObject.updateValue('configurationService.workspace.testSetting', 'workspaceValue', ConfigurationTarget.WORKSPACE) + .then(() => assert.ok(target.called)); + }); + + test('update application setting into workspace configuration in a workspace is not supported', () => { + return testObject.updateValue('configurationService.workspace.applicationSetting', 'workspaceValue', {}, ConfigurationTarget.WORKSPACE, true) + .then(() => assert.fail('Should not be supported'), (e) => assert.equal(e.code, ConfigurationEditingErrorCode.ERROR_INVALID_WORKSPACE_CONFIGURATION_APPLICATION)); + }); + + test('update machine setting into workspace configuration in a workspace is not supported', () => { + return testObject.updateValue('configurationService.workspace.machineSetting', 'workspaceValue', {}, ConfigurationTarget.WORKSPACE, true) + .then(() => assert.fail('Should not be supported'), (e) => assert.equal(e.code, ConfigurationEditingErrorCode.ERROR_INVALID_WORKSPACE_CONFIGURATION_MACHINE)); + }); + + test('update workspace folder configuration', () => { + const workspace = workspaceContextService.getWorkspace(); + return testObject.updateValue('configurationService.workspace.testResourceSetting', 'workspaceFolderValue', { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER) + .then(() => assert.equal(testObject.getValue('configurationService.workspace.testResourceSetting', { resource: workspace.folders[0].uri }), 'workspaceFolderValue')); + }); + + test('update workspace folder configuration should trigger change event before promise is resolve', () => { + const workspace = workspaceContextService.getWorkspace(); + const target = sinon.spy(); + testObject.onDidChangeConfiguration(target); + return testObject.updateValue('configurationService.workspace.testResourceSetting', 'workspaceFolderValue', { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER) + .then(() => assert.ok(target.called)); + }); + + test('update workspace folder configuration second time should trigger change event before promise is resolve', () => { + const workspace = workspaceContextService.getWorkspace(); + return testObject.updateValue('configurationService.workspace.testResourceSetting', 'workspaceFolderValue', { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER) + .then(() => { + const target = sinon.spy(); + testObject.onDidChangeConfiguration(target); + return testObject.updateValue('configurationService.workspace.testResourceSetting', 'workspaceFolderValue2', { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER) + .then(() => assert.ok(target.called)); + }); + }); + + test('update memory configuration', () => { + return testObject.updateValue('configurationService.workspace.testSetting', 'memoryValue', ConfigurationTarget.MEMORY) + .then(() => assert.equal(testObject.getValue('configurationService.workspace.testSetting'), 'memoryValue')); + }); + + test('update memory configuration should trigger change event before promise is resolve', () => { + const target = sinon.spy(); + testObject.onDidChangeConfiguration(target); + return testObject.updateValue('configurationService.workspace.testSetting', 'memoryValue', ConfigurationTarget.MEMORY) + .then(() => assert.ok(target.called)); + }); + + test('update tasks configuration in a folder', () => { + const workspace = workspaceContextService.getWorkspace(); + return testObject.updateValue('tasks', { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] }, { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER) + .then(() => assert.deepEqual(testObject.getValue('tasks', { resource: workspace.folders[0].uri }), { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] })); + }); + + test('update tasks configuration in a workspace is not supported', () => { + const workspace = workspaceContextService.getWorkspace(); + return testObject.updateValue('tasks', { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] }, { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE, true) + .then(() => assert.fail('Should not be supported'), (e) => assert.equal(e.code, ConfigurationEditingErrorCode.ERROR_INVALID_WORKSPACE_TARGET)); + }); + + test('update launch configuration in a workspace', () => { + const workspace = workspaceContextService.getWorkspace(); + return testObject.updateValue('launch', { 'version': '1.0.0', configurations: [{ 'name': 'myLaunch' }] }, { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE, true) + .then(() => assert.deepEqual(testObject.getValue('launch'), { 'version': '1.0.0', configurations: [{ 'name': 'myLaunch' }] })); + }); + + test('task configurations are not read from workspace', () => { + return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, { key: 'tasks', value: { 'version': '1.0' } }, true) + .then(() => testObject.reloadConfiguration()) + .then(() => { + const actual = testObject.inspect('tasks.version'); + assert.equal(actual.workspace, undefined); + }); }); test('configuration of newly added folder is available on configuration change event', async () => { - // {{SQL CARBON EDIT}} - Remove tests - assert.equal(0, 0); + const workspaceService = testObject; + const uri = workspaceService.getWorkspace().folders[1].uri; + await workspaceService.removeFolders([uri]); + fs.writeFileSync(path.join(uri.fsPath, '.vscode', 'settings.json'), '{ "configurationService.workspace.testResourceSetting": "workspaceFolderValue" }'); + + return new Promise((c, e) => { + testObject.onDidChangeConfiguration(() => { + try { + assert.equal(testObject.getValue('configurationService.workspace.testResourceSetting', { resource: uri }), 'workspaceFolderValue'); + c(); + } catch (error) { + e(error); + } + }); + workspaceService.addFolders([{ uri }]); + }); }); }); diff --git a/src/vs/workbench/services/editor/test/browser/editorGroupsService.test.ts b/src/vs/workbench/services/editor/test/browser/editorGroupsService.test.ts index 1f5fbba7c9..16999786f5 100644 --- a/src/vs/workbench/services/editor/test/browser/editorGroupsService.test.ts +++ b/src/vs/workbench/services/editor/test/browser/editorGroupsService.test.ts @@ -8,7 +8,7 @@ import { EditorPart } from 'vs/workbench/browser/parts/editor/editorPart'; import { workbenchInstantiationService, TestStorageService } from 'vs/workbench/test/workbenchTestServices'; import { GroupDirection, GroupsOrder, MergeGroupMode, GroupOrientation, GroupChangeKind, EditorsOrder, GroupLocation } from 'vs/workbench/services/editor/common/editorGroupsService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { EditorInput, IFileEditorInput, IEditorInputFactory, IEditorInputFactoryRegistry, Extensions as EditorExtensions, EditorOptions, CloseDirection } from 'vs/workbench/common/editor'; +import { EditorInput, IFileEditorInput, IEditorInputFactory, IEditorInputFactoryRegistry, Extensions as EditorExtensions, EditorOptions, CloseDirection, IEditorPartOptions } from 'vs/workbench/common/editor'; import { IEditorModel } from 'vs/platform/editor/common/editor'; import { URI } from 'vs/base/common/uri'; import { Registry } from 'vs/platform/registry/common/platform'; @@ -51,9 +51,687 @@ export class TestEditorInput extends EditorInput implements IFileEditorInput { setForceOpenAsBinary(): void { } } -suite('Editor groups service', () => { - test('groups basics', function () { - // {{SQL CARBON EDIT}} - Remove test - assert.equal(0, 0); +suite.skip('EditorGroupsService', () => { // {{SQL CARBON EDIT}} skip suite + + function registerTestEditorInput(): void { + + interface ISerializedTestEditorInput { + resource: string; + } + + class TestEditorInputFactory implements IEditorInputFactory { + + constructor() { } + + serialize(editorInput: EditorInput): string { + const testEditorInput = editorInput; + const testInput: ISerializedTestEditorInput = { + resource: testEditorInput.getResource().toString() + }; + + return JSON.stringify(testInput); + } + + deserialize(instantiationService: IInstantiationService, serializedEditorInput: string): EditorInput { + const testInput: ISerializedTestEditorInput = JSON.parse(serializedEditorInput); + + return new TestEditorInput(URI.parse(testInput.resource)); + } + } + + (Registry.as(EditorExtensions.EditorInputFactories)).registerEditorInputFactory('testEditorInputForGroupsService', TestEditorInputFactory); + (Registry.as(Extensions.Editors)).registerEditor(new EditorDescriptor(TestEditorControl, 'MyTestEditorForGroupsService', 'My Test File Editor'), [new SyncDescriptor(TestEditorInput)]); + } + + registerTestEditorInput(); + + function createPart(): EditorPart { + const instantiationService = workbenchInstantiationService(); + + const part = instantiationService.createInstance(EditorPart); + part.create(document.createElement('div')); + part.layout(400, 300); + + return part; + } + + test('groups basics', async function () { + const part = createPart(); + + let activeGroupChangeCounter = 0; + const activeGroupChangeListener = part.onDidActiveGroupChange(() => { + activeGroupChangeCounter++; + }); + + let groupAddedCounter = 0; + const groupAddedListener = part.onDidAddGroup(() => { + groupAddedCounter++; + }); + + let groupRemovedCounter = 0; + const groupRemovedListener = part.onDidRemoveGroup(() => { + groupRemovedCounter++; + }); + + let groupMovedCounter = 0; + const groupMovedListener = part.onDidMoveGroup(() => { + groupMovedCounter++; + }); + + // always a root group + const rootGroup = part.groups[0]; + assert.equal(part.groups.length, 1); + assert.equal(part.count, 1); + assert.equal(rootGroup, part.getGroup(rootGroup.id)); + assert.ok(part.activeGroup === rootGroup); + assert.equal(rootGroup.label, 'Group 1'); + + let mru = part.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE); + assert.equal(mru.length, 1); + assert.equal(mru[0], rootGroup); + + const rightGroup = part.addGroup(rootGroup, GroupDirection.RIGHT); + assert.equal(rightGroup, part.getGroup(rightGroup.id)); + assert.equal(groupAddedCounter, 1); + assert.equal(part.groups.length, 2); + assert.equal(part.count, 2); + assert.ok(part.activeGroup === rootGroup); + assert.equal(rootGroup.label, 'Group 1'); + assert.equal(rightGroup.label, 'Group 2'); + + mru = part.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE); + assert.equal(mru.length, 2); + assert.equal(mru[0], rootGroup); + assert.equal(mru[1], rightGroup); + + assert.equal(activeGroupChangeCounter, 0); + + let rootGroupActiveChangeCounter = 0; + const rootGroupChangeListener = rootGroup.onDidGroupChange(e => { + if (e.kind === GroupChangeKind.GROUP_ACTIVE) { + rootGroupActiveChangeCounter++; + } + }); + + let rightGroupActiveChangeCounter = 0; + const rightGroupChangeListener = rightGroup.onDidGroupChange(e => { + if (e.kind === GroupChangeKind.GROUP_ACTIVE) { + rightGroupActiveChangeCounter++; + } + }); + + part.activateGroup(rightGroup); + assert.ok(part.activeGroup === rightGroup); + assert.equal(activeGroupChangeCounter, 1); + assert.equal(rootGroupActiveChangeCounter, 1); + assert.equal(rightGroupActiveChangeCounter, 1); + + rootGroupChangeListener.dispose(); + rightGroupChangeListener.dispose(); + + mru = part.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE); + assert.equal(mru.length, 2); + assert.equal(mru[0], rightGroup); + assert.equal(mru[1], rootGroup); + + const downGroup = part.addGroup(rightGroup, GroupDirection.DOWN); + let didDispose = false; + downGroup.onWillDispose(() => { + didDispose = true; + }); + assert.equal(groupAddedCounter, 2); + assert.equal(part.groups.length, 3); + assert.ok(part.activeGroup === rightGroup); + assert.ok(!downGroup.activeControl); + assert.equal(rootGroup.label, 'Group 1'); + assert.equal(rightGroup.label, 'Group 2'); + assert.equal(downGroup.label, 'Group 3'); + + mru = part.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE); + assert.equal(mru.length, 3); + assert.equal(mru[0], rightGroup); + assert.equal(mru[1], rootGroup); + assert.equal(mru[2], downGroup); + + const gridOrder = part.getGroups(GroupsOrder.GRID_APPEARANCE); + assert.equal(gridOrder.length, 3); + assert.equal(gridOrder[0], rootGroup); + assert.equal(gridOrder[0].index, 0); + assert.equal(gridOrder[1], rightGroup); + assert.equal(gridOrder[1].index, 1); + assert.equal(gridOrder[2], downGroup); + assert.equal(gridOrder[2].index, 2); + + part.moveGroup(downGroup, rightGroup, GroupDirection.DOWN); + assert.equal(groupMovedCounter, 1); + + part.removeGroup(downGroup); + assert.ok(!part.getGroup(downGroup.id)); + assert.equal(didDispose, true); + assert.equal(groupRemovedCounter, 1); + assert.equal(part.groups.length, 2); + assert.ok(part.activeGroup === rightGroup); + assert.equal(rootGroup.label, 'Group 1'); + assert.equal(rightGroup.label, 'Group 2'); + + mru = part.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE); + assert.equal(mru.length, 2); + assert.equal(mru[0], rightGroup); + assert.equal(mru[1], rootGroup); + + let rightGroupInstantiator!: IInstantiationService; + part.activeGroup.invokeWithinContext(accessor => { + rightGroupInstantiator = accessor.get(IInstantiationService); + }); + + let rootGroupInstantiator!: IInstantiationService; + rootGroup.invokeWithinContext(accessor => { + rootGroupInstantiator = accessor.get(IInstantiationService); + }); + + assert.ok(rightGroupInstantiator); + assert.ok(rootGroupInstantiator); + assert.ok(rightGroupInstantiator !== rootGroupInstantiator); + + part.removeGroup(rightGroup); + assert.equal(groupRemovedCounter, 2); + assert.equal(part.groups.length, 1); + assert.ok(part.activeGroup === rootGroup); + + mru = part.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE); + assert.equal(mru.length, 1); + assert.equal(mru[0], rootGroup); + + part.removeGroup(rootGroup); // cannot remove root group + assert.equal(part.groups.length, 1); + assert.equal(groupRemovedCounter, 2); + assert.ok(part.activeGroup === rootGroup); + + part.setGroupOrientation(part.orientation === GroupOrientation.HORIZONTAL ? GroupOrientation.VERTICAL : GroupOrientation.HORIZONTAL); + + activeGroupChangeListener.dispose(); + groupAddedListener.dispose(); + groupRemovedListener.dispose(); + groupMovedListener.dispose(); + + part.dispose(); + }); + + test('groups index / labels', function () { + const part = createPart(); + + const rootGroup = part.groups[0]; + const rightGroup = part.addGroup(rootGroup, GroupDirection.RIGHT); + const downGroup = part.addGroup(rightGroup, GroupDirection.DOWN); + + let groupIndexChangedCounter = 0; + const groupIndexChangedListener = part.onDidGroupIndexChange(() => { + groupIndexChangedCounter++; + }); + + let indexChangeCounter = 0; + const labelChangeListener = downGroup.onDidGroupChange(e => { + if (e.kind === GroupChangeKind.GROUP_INDEX) { + indexChangeCounter++; + } + }); + + assert.equal(rootGroup.index, 0); + assert.equal(rightGroup.index, 1); + assert.equal(downGroup.index, 2); + assert.equal(rootGroup.label, 'Group 1'); + assert.equal(rightGroup.label, 'Group 2'); + assert.equal(downGroup.label, 'Group 3'); + + part.removeGroup(rightGroup); + assert.equal(rootGroup.index, 0); + assert.equal(downGroup.index, 1); + assert.equal(rootGroup.label, 'Group 1'); + assert.equal(downGroup.label, 'Group 2'); + assert.equal(indexChangeCounter, 1); + assert.equal(groupIndexChangedCounter, 1); + + part.moveGroup(downGroup, rootGroup, GroupDirection.UP); + assert.equal(downGroup.index, 0); + assert.equal(rootGroup.index, 1); + assert.equal(downGroup.label, 'Group 1'); + assert.equal(rootGroup.label, 'Group 2'); + assert.equal(indexChangeCounter, 2); + assert.equal(groupIndexChangedCounter, 3); + + const newFirstGroup = part.addGroup(downGroup, GroupDirection.UP); + assert.equal(newFirstGroup.index, 0); + assert.equal(downGroup.index, 1); + assert.equal(rootGroup.index, 2); + assert.equal(newFirstGroup.label, 'Group 1'); + assert.equal(downGroup.label, 'Group 2'); + assert.equal(rootGroup.label, 'Group 3'); + assert.equal(indexChangeCounter, 3); + assert.equal(groupIndexChangedCounter, 6); + + labelChangeListener.dispose(); + groupIndexChangedListener.dispose(); + + part.dispose(); + }); + + test('copy/merge groups', async () => { + const part = createPart(); + + let groupAddedCounter = 0; + const groupAddedListener = part.onDidAddGroup(() => { + groupAddedCounter++; + }); + + let groupRemovedCounter = 0; + const groupRemovedListener = part.onDidRemoveGroup(() => { + groupRemovedCounter++; + }); + + const rootGroup = part.groups[0]; + let rootGroupDisposed = false; + const disposeListener = rootGroup.onWillDispose(() => { + rootGroupDisposed = true; + }); + + const input = new TestEditorInput(URI.file('foo/bar')); + + await rootGroup.openEditor(input, EditorOptions.create({ pinned: true })); + const rightGroup = part.addGroup(rootGroup, GroupDirection.RIGHT, { activate: true }); + const downGroup = part.copyGroup(rootGroup, rightGroup, GroupDirection.DOWN); + assert.equal(groupAddedCounter, 2); + assert.equal(downGroup.count, 1); + assert.ok(downGroup.activeEditor instanceof TestEditorInput); + part.mergeGroup(rootGroup, rightGroup, { mode: MergeGroupMode.COPY_EDITORS }); + assert.equal(rightGroup.count, 1); + assert.ok(rightGroup.activeEditor instanceof TestEditorInput); + part.mergeGroup(rootGroup, rightGroup, { mode: MergeGroupMode.MOVE_EDITORS }); + assert.equal(rootGroup.count, 0); + part.mergeGroup(rootGroup, downGroup); + assert.equal(groupRemovedCounter, 1); + assert.equal(rootGroupDisposed, true); + groupAddedListener.dispose(); + groupRemovedListener.dispose(); + disposeListener.dispose(); + part.dispose(); + }); + + test('whenRestored', async () => { + const part = createPart(); + + await part.whenRestored; + assert.ok(true); + part.dispose(); + }); + + test('options', () => { + const part = createPart(); + + let oldOptions!: IEditorPartOptions; + let newOptions!: IEditorPartOptions; + part.onDidEditorPartOptionsChange(event => { + oldOptions = event.oldPartOptions; + newOptions = event.newPartOptions; + }); + + const currentOptions = part.partOptions; + assert.ok(currentOptions); + + part.enforcePartOptions({ showTabs: false }); + assert.equal(part.partOptions.showTabs, false); + assert.equal(newOptions.showTabs, false); + assert.equal(oldOptions, currentOptions); + + part.dispose(); + }); + + test('editor basics', async function () { + const part = createPart(); + const group = part.activeGroup; + assert.equal(group.isEmpty, true); + + await part.whenRestored; + + let editorWillOpenCounter = 0; + const editorWillOpenListener = group.onWillOpenEditor(() => { + editorWillOpenCounter++; + }); + + let activeEditorChangeCounter = 0; + let editorDidOpenCounter = 0; + let editorCloseCounter1 = 0; + let editorPinCounter = 0; + const editorGroupChangeListener = group.onDidGroupChange(e => { + if (e.kind === GroupChangeKind.EDITOR_OPEN) { + assert.ok(e.editor); + editorDidOpenCounter++; + } else if (e.kind === GroupChangeKind.EDITOR_ACTIVE) { + assert.ok(e.editor); + activeEditorChangeCounter++; + } else if (e.kind === GroupChangeKind.EDITOR_CLOSE) { + assert.ok(e.editor); + editorCloseCounter1++; + } else if (e.kind === GroupChangeKind.EDITOR_PIN) { + assert.ok(e.editor); + editorPinCounter++; + } + }); + + let editorCloseCounter2 = 0; + const editorCloseListener = group.onDidCloseEditor(() => { + editorCloseCounter2++; + }); + + let editorWillCloseCounter = 0; + const editorWillCloseListener = group.onWillCloseEditor(() => { + editorWillCloseCounter++; + }); + + const input = new TestEditorInput(URI.file('foo/bar')); + const inputInactive = new TestEditorInput(URI.file('foo/bar/inactive')); + + await group.openEditor(input, EditorOptions.create({ pinned: true })); + await group.openEditor(inputInactive, EditorOptions.create({ inactive: true })); + + assert.equal(group.isActive(input), true); + assert.equal(group.isActive(inputInactive), false); + assert.equal(group.isOpened(input), true); + assert.equal(group.isOpened(inputInactive), true); + assert.equal(group.isEmpty, false); + assert.equal(group.count, 2); + assert.equal(editorWillOpenCounter, 2); + assert.equal(editorDidOpenCounter, 2); + assert.equal(activeEditorChangeCounter, 1); + assert.equal(group.getEditor(0), input); + assert.equal(group.getEditor(1), inputInactive); + assert.equal(group.getIndexOfEditor(input), 0); + assert.equal(group.getIndexOfEditor(inputInactive), 1); + + assert.equal(group.previewEditor, inputInactive); + assert.equal(group.isPinned(inputInactive), false); + group.pinEditor(inputInactive); + assert.equal(editorPinCounter, 1); + assert.equal(group.isPinned(inputInactive), true); + assert.ok(!group.previewEditor); + + assert.equal(group.activeEditor, input); + assert.ok(group.activeControl instanceof TestEditorControl); + assert.equal(group.editors.length, 2); + + const mru = group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE); + assert.equal(mru[0], input); + assert.equal(mru[1], inputInactive); + + await group.openEditor(inputInactive); + assert.equal(activeEditorChangeCounter, 2); + assert.equal(group.activeEditor, inputInactive); + + await group.openEditor(input); + await group.closeEditor(inputInactive); + + assert.equal(activeEditorChangeCounter, 3); + assert.equal(editorCloseCounter1, 1); + assert.equal(editorCloseCounter2, 1); + assert.equal(editorWillCloseCounter, 1); + + assert.equal(group.activeEditor, input); + + editorCloseListener.dispose(); + editorWillCloseListener.dispose(); + editorWillOpenListener.dispose(); + editorGroupChangeListener.dispose(); + part.dispose(); + }); + + test('openEditors / closeEditors', async () => { + const part = createPart(); + const group = part.activeGroup; + assert.equal(group.isEmpty, true); + + const input = new TestEditorInput(URI.file('foo/bar')); + const inputInactive = new TestEditorInput(URI.file('foo/bar/inactive')); + + await group.openEditors([{ editor: input, options: { pinned: true } }, { editor: inputInactive }]); + assert.equal(group.count, 2); + assert.equal(group.getEditor(0), input); + assert.equal(group.getEditor(1), inputInactive); + + await group.closeEditors([input, inputInactive]); + assert.equal(group.isEmpty, true); + part.dispose(); + }); + + test('closeEditors (except one)', async () => { + const part = createPart(); + const group = part.activeGroup; + assert.equal(group.isEmpty, true); + + const input1 = new TestEditorInput(URI.file('foo/bar1')); + const input2 = new TestEditorInput(URI.file('foo/bar2')); + const input3 = new TestEditorInput(URI.file('foo/bar3')); + + await group.openEditors([{ editor: input1, options: { pinned: true } }, { editor: input2, options: { pinned: true } }, { editor: input3 }]); + assert.equal(group.count, 3); + assert.equal(group.getEditor(0), input1); + assert.equal(group.getEditor(1), input2); + assert.equal(group.getEditor(2), input3); + + await group.closeEditors({ except: input2 }); + assert.equal(group.count, 1); + assert.equal(group.getEditor(0), input2); + part.dispose(); + }); + + test('closeEditors (saved only)', async () => { + const part = createPart(); + const group = part.activeGroup; + assert.equal(group.isEmpty, true); + + const input1 = new TestEditorInput(URI.file('foo/bar1')); + const input2 = new TestEditorInput(URI.file('foo/bar2')); + const input3 = new TestEditorInput(URI.file('foo/bar3')); + + await group.openEditors([{ editor: input1, options: { pinned: true } }, { editor: input2, options: { pinned: true } }, { editor: input3 }]); + assert.equal(group.count, 3); + assert.equal(group.getEditor(0), input1); + assert.equal(group.getEditor(1), input2); + assert.equal(group.getEditor(2), input3); + + await group.closeEditors({ savedOnly: true }); + assert.equal(group.count, 0); + part.dispose(); + }); + + test('closeEditors (direction: right)', async () => { + const part = createPart(); + const group = part.activeGroup; + assert.equal(group.isEmpty, true); + + const input1 = new TestEditorInput(URI.file('foo/bar1')); + const input2 = new TestEditorInput(URI.file('foo/bar2')); + const input3 = new TestEditorInput(URI.file('foo/bar3')); + + await group.openEditors([{ editor: input1, options: { pinned: true } }, { editor: input2, options: { pinned: true } }, { editor: input3 }]); + assert.equal(group.count, 3); + assert.equal(group.getEditor(0), input1); + assert.equal(group.getEditor(1), input2); + assert.equal(group.getEditor(2), input3); + + await group.closeEditors({ direction: CloseDirection.RIGHT, except: input2 }); + assert.equal(group.count, 2); + assert.equal(group.getEditor(0), input1); + assert.equal(group.getEditor(1), input2); + part.dispose(); + }); + + test('closeEditors (direction: left)', async () => { + const part = createPart(); + const group = part.activeGroup; + assert.equal(group.isEmpty, true); + + const input1 = new TestEditorInput(URI.file('foo/bar1')); + const input2 = new TestEditorInput(URI.file('foo/bar2')); + const input3 = new TestEditorInput(URI.file('foo/bar3')); + + await group.openEditors([{ editor: input1, options: { pinned: true } }, { editor: input2, options: { pinned: true } }, { editor: input3 }]); + assert.equal(group.count, 3); + assert.equal(group.getEditor(0), input1); + assert.equal(group.getEditor(1), input2); + assert.equal(group.getEditor(2), input3); + + await group.closeEditors({ direction: CloseDirection.LEFT, except: input2 }); + assert.equal(group.count, 2); + assert.equal(group.getEditor(0), input2); + assert.equal(group.getEditor(1), input3); + part.dispose(); + }); + + test('closeAllEditors', async () => { + const part = createPart(); + const group = part.activeGroup; + assert.equal(group.isEmpty, true); + + const input = new TestEditorInput(URI.file('foo/bar')); + const inputInactive = new TestEditorInput(URI.file('foo/bar/inactive')); + + await group.openEditors([{ editor: input, options: { pinned: true } }, { editor: inputInactive }]); + assert.equal(group.count, 2); + assert.equal(group.getEditor(0), input); + assert.equal(group.getEditor(1), inputInactive); + + await group.closeAllEditors(); + assert.equal(group.isEmpty, true); + part.dispose(); + }); + + test('moveEditor (same group)', async () => { + const part = createPart(); + const group = part.activeGroup; + assert.equal(group.isEmpty, true); + + const input = new TestEditorInput(URI.file('foo/bar')); + const inputInactive = new TestEditorInput(URI.file('foo/bar/inactive')); + + let editorMoveCounter = 0; + const editorGroupChangeListener = group.onDidGroupChange(e => { + if (e.kind === GroupChangeKind.EDITOR_MOVE) { + assert.ok(e.editor); + editorMoveCounter++; + } + }); + + await group.openEditors([{ editor: input, options: { pinned: true } }, { editor: inputInactive }]); + assert.equal(group.count, 2); + assert.equal(group.getEditor(0), input); + assert.equal(group.getEditor(1), inputInactive); + group.moveEditor(inputInactive, group, { index: 0 }); + assert.equal(editorMoveCounter, 1); + assert.equal(group.getEditor(0), inputInactive); + assert.equal(group.getEditor(1), input); + editorGroupChangeListener.dispose(); + part.dispose(); + }); + + test('moveEditor (across groups)', async () => { + const part = createPart(); + const group = part.activeGroup; + assert.equal(group.isEmpty, true); + + const rightGroup = part.addGroup(group, GroupDirection.RIGHT); + + const input = new TestEditorInput(URI.file('foo/bar')); + const inputInactive = new TestEditorInput(URI.file('foo/bar/inactive')); + + await group.openEditors([{ editor: input, options: { pinned: true } }, { editor: inputInactive }]); + assert.equal(group.count, 2); + assert.equal(group.getEditor(0), input); + assert.equal(group.getEditor(1), inputInactive); + group.moveEditor(inputInactive, rightGroup, { index: 0 }); + assert.equal(group.count, 1); + assert.equal(group.getEditor(0), input); + assert.equal(rightGroup.count, 1); + assert.equal(rightGroup.getEditor(0), inputInactive); + part.dispose(); + }); + + test('copyEditor (across groups)', async () => { + const part = createPart(); + const group = part.activeGroup; + assert.equal(group.isEmpty, true); + + const rightGroup = part.addGroup(group, GroupDirection.RIGHT); + + const input = new TestEditorInput(URI.file('foo/bar')); + const inputInactive = new TestEditorInput(URI.file('foo/bar/inactive')); + + await group.openEditors([{ editor: input, options: { pinned: true } }, { editor: inputInactive }]); + assert.equal(group.count, 2); + assert.equal(group.getEditor(0), input); + assert.equal(group.getEditor(1), inputInactive); + group.copyEditor(inputInactive, rightGroup, { index: 0 }); + assert.equal(group.count, 2); + assert.equal(group.getEditor(0), input); + assert.equal(group.getEditor(1), inputInactive); + assert.equal(rightGroup.count, 1); + assert.equal(rightGroup.getEditor(0), inputInactive); + part.dispose(); + }); + + test('replaceEditors', async () => { + const part = createPart(); + const group = part.activeGroup; + assert.equal(group.isEmpty, true); + + const input = new TestEditorInput(URI.file('foo/bar')); + const inputInactive = new TestEditorInput(URI.file('foo/bar/inactive')); + + await group.openEditor(input); + assert.equal(group.count, 1); + assert.equal(group.getEditor(0), input); + + await group.replaceEditors([{ editor: input, replacement: inputInactive }]); + assert.equal(group.count, 1); + assert.equal(group.getEditor(0), inputInactive); + part.dispose(); + }); + + test('find neighbour group (left/right)', function () { + const part = createPart(); + const rootGroup = part.activeGroup; + const rightGroup = part.addGroup(rootGroup, GroupDirection.RIGHT); + + assert.equal(rightGroup, part.findGroup({ direction: GroupDirection.RIGHT }, rootGroup)); + assert.equal(rootGroup, part.findGroup({ direction: GroupDirection.LEFT }, rightGroup)); + + part.dispose(); + }); + + test('find neighbour group (up/down)', function () { + const part = createPart(); + const rootGroup = part.activeGroup; + const downGroup = part.addGroup(rootGroup, GroupDirection.DOWN); + + assert.equal(downGroup, part.findGroup({ direction: GroupDirection.DOWN }, rootGroup)); + assert.equal(rootGroup, part.findGroup({ direction: GroupDirection.UP }, downGroup)); + + part.dispose(); + }); + + test('find group by location (left/right)', function () { + const part = createPart(); + const rootGroup = part.activeGroup; + const rightGroup = part.addGroup(rootGroup, GroupDirection.RIGHT); + const downGroup = part.addGroup(rightGroup, GroupDirection.DOWN); + + assert.equal(rootGroup, part.findGroup({ location: GroupLocation.FIRST })); + assert.equal(downGroup, part.findGroup({ location: GroupLocation.LAST })); + + assert.equal(rightGroup, part.findGroup({ location: GroupLocation.NEXT }, rootGroup)); + assert.equal(rootGroup, part.findGroup({ location: GroupLocation.PREVIOUS }, rightGroup)); + + assert.equal(downGroup, part.findGroup({ location: GroupLocation.NEXT }, rightGroup)); + assert.equal(rightGroup, part.findGroup({ location: GroupLocation.PREVIOUS }, downGroup)); + + part.dispose(); }); }); diff --git a/src/vs/workbench/services/editor/test/browser/editorService.test.ts b/src/vs/workbench/services/editor/test/browser/editorService.test.ts index eacb061e53..c0e982eeff 100644 --- a/src/vs/workbench/services/editor/test/browser/editorService.test.ts +++ b/src/vs/workbench/services/editor/test/browser/editorService.test.ts @@ -33,8 +33,6 @@ import { ModesRegistry } from 'vs/editor/common/modes/modesRegistry'; import { UntitledEditorModel } from 'vs/workbench/common/editor/untitledEditorModel'; import { NullFileSystemProvider } from 'vs/platform/files/test/common/nullFileSystemProvider'; -// {{SQL CARBON EDIT}} - Disable editor tests -/* export class TestEditorControl extends BaseEditor { constructor(@ITelemetryService telemetryService: ITelemetryService) { super('MyTestEditorForEditorService', NullTelemetryService, new TestThemeService(), new TestStorageService()); } @@ -82,7 +80,7 @@ class FileServiceProvider extends Disposable { } } -*/suite('EditorService', () => {/* +suite.skip('EditorService', () => { // {{SQL CARBON EDIT}} skip suite function registerTestEditorInput(): void { Registry.as(Extensions.Editors).registerEditor(new EditorDescriptor(TestEditorControl, 'MyTestEditorForEditorService', 'My Test Editor For Next Editor Service'), [new SyncDescriptor(TestEditorInput)]); @@ -646,5 +644,5 @@ class FileServiceProvider extends Disposable { let failingEditor = await service.openEditor(failingInput); assert.ok(!failingEditor); - });*/ + }); }); diff --git a/src/vs/workbench/services/textfile/test/textFileService.test.ts b/src/vs/workbench/services/textfile/test/textFileService.test.ts index 7d422457a7..aae5525f64 100644 --- a/src/vs/workbench/services/textfile/test/textFileService.test.ts +++ b/src/vs/workbench/services/textfile/test/textFileService.test.ts @@ -308,9 +308,7 @@ suite('Files - TextFileService', () => { targetModel.dispose(); } - // {{SQL CARBON EDIT}} - /* - suite('Hot Exit', () => { + suite.skip('Hot Exit', () => { // {{SQL CARBON EDIT}} skip suite suite('"onExit" setting', () => { test('should hot exit on non-Mac (reason: CLOSE, windows: single, workspace)', function () { return hotExitTest.call(this, HotExitConfiguration.ON_EXIT, ShutdownReason.CLOSE, false, true, !!platform.isMacintosh); @@ -443,6 +441,4 @@ suite('Files - TextFileService', () => { assert.equal(veto, shouldVeto); } }); - // {{SQL CARBON EDIT}} - */ });