mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-17 02:51:36 -05:00
Alanren/integration test (#3657)
* add an extension for integration tests * setup ads before running test * test setup * test cases * bash script * shorter temp folder name * code cleanup * add commented out original code * fix test error * test result path * rename results file * change file path * report smoke test results * test stablize * test stablization and configurable test servers * fix smoke test error * connection provider * simplify the integration test script * add comment * fix tslint error * address PR comments * add temp log to check whether the environment variable is already set * remove temp log * move api definition to testapi typing file * exclude integration tests extension * address comments
This commit is contained in:
10
.vscode/launch.json
vendored
10
.vscode/launch.json
vendored
@@ -152,6 +152,16 @@
|
|||||||
"args": [
|
"args": [
|
||||||
"--extensionDevelopmentPath=${workspaceRoot}/extensions/debug-auto-launch"
|
"--extensionDevelopmentPath=${workspaceRoot}/extensions/debug-auto-launch"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "node",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Launch Smoke Test",
|
||||||
|
"program": "${workspaceFolder}/test/smoke/test/index.js",
|
||||||
|
"cwd": "${workspaceFolder}/test/smoke",
|
||||||
|
"env": {
|
||||||
|
"BUILD_ARTIFACTSTAGINGDIRECTORY": "${workspaceFolder}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"compounds": [
|
"compounds": [
|
||||||
|
|||||||
@@ -65,6 +65,8 @@ const excludedExtensions = [
|
|||||||
'vscode-colorize-tests',
|
'vscode-colorize-tests',
|
||||||
'ms-vscode.node-debug',
|
'ms-vscode.node-debug',
|
||||||
'ms-vscode.node-debug2',
|
'ms-vscode.node-debug2',
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
|
'integration-tests',
|
||||||
];
|
];
|
||||||
|
|
||||||
// {{SQL CARBON EDIT}}
|
// {{SQL CARBON EDIT}}
|
||||||
|
|||||||
17
extensions/integration-tests/.vscode/launch.json
vendored
Normal file
17
extensions/integration-tests/.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
// A launch configuration that compiles the extension and then opens it inside a new window
|
||||||
|
{
|
||||||
|
"version": "0.1.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Launch Tests",
|
||||||
|
"type": "extensionHost",
|
||||||
|
"request": "launch",
|
||||||
|
"runtimeExecutable": "${execPath}",
|
||||||
|
"args": ["${workspaceFolder}/../../", "${workspaceFolder}/test", "--extensionDevelopmentPath=${workspaceFolder}", "--extensionTestsPath=${workspaceFolder}/out" ],
|
||||||
|
"stopOnEntry": false,
|
||||||
|
"sourceMaps": true,
|
||||||
|
"outDir": "${workspaceFolder}/out",
|
||||||
|
"preLaunchTask": "npm"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
31
extensions/integration-tests/.vscode/tasks.json
vendored
Normal file
31
extensions/integration-tests/.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
// Available variables which can be used inside of strings.
|
||||||
|
// ${workspaceFolder}: the root folder of the team
|
||||||
|
// ${file}: the current opened file
|
||||||
|
// ${relativeFile}: the current opened file relative to cwd
|
||||||
|
// ${fileBasename}: the current opened file's basename
|
||||||
|
// ${fileDirname}: the current opened file's dirname
|
||||||
|
// ${fileExtname}: the current opened file's extension
|
||||||
|
// ${cwd}: the current working directory of the spawned process
|
||||||
|
|
||||||
|
// A task runner that calls a custom npm script that compiles the extension.
|
||||||
|
{
|
||||||
|
"version": "0.1.0",
|
||||||
|
|
||||||
|
// we want to run npm
|
||||||
|
"command": "npm",
|
||||||
|
|
||||||
|
// the command is a shell script
|
||||||
|
"isShellCommand": true,
|
||||||
|
|
||||||
|
// show the output window only if unrecognized errors occur.
|
||||||
|
"showOutput": "silent",
|
||||||
|
|
||||||
|
// we run the custom script "compile" as defined in package.json
|
||||||
|
"args": ["run", "compile", "--loglevel", "silent"],
|
||||||
|
|
||||||
|
// The tsc compiler is started in watching mode
|
||||||
|
"isWatching": true,
|
||||||
|
|
||||||
|
// use the standard tsc in watch mode problem matcher to find compile problems in the output.
|
||||||
|
"problemMatcher": "$tsc-watch"
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
copy the extension installers to this folder
|
||||||
2549
extensions/integration-tests/package-lock.json
generated
Normal file
2549
extensions/integration-tests/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
58
extensions/integration-tests/package.json
Normal file
58
extensions/integration-tests/package.json
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
{
|
||||||
|
"name": "integration-tests",
|
||||||
|
"description": "Integration Tests",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"publisher": "Microsoft",
|
||||||
|
"private": true,
|
||||||
|
"engines": {
|
||||||
|
"vscode": "*",
|
||||||
|
"sqlops": "*"
|
||||||
|
},
|
||||||
|
"activationEvents": [
|
||||||
|
"*"
|
||||||
|
],
|
||||||
|
"main": "./out/main",
|
||||||
|
"extensionDependencies": [
|
||||||
|
"Microsoft.agent",
|
||||||
|
"Microsoft.import",
|
||||||
|
"Microsoft.profiler",
|
||||||
|
"Microsoft.mssql",
|
||||||
|
"Microsoft.notebook"
|
||||||
|
],
|
||||||
|
"contributes": {
|
||||||
|
"configuration": {
|
||||||
|
"type": "object",
|
||||||
|
"title": "ADS Integration Test Configuration",
|
||||||
|
"properties": {
|
||||||
|
"test.testSetupCompleted": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false,
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"commands": [{
|
||||||
|
"command": "test.setupIntegrationTest",
|
||||||
|
"title": "Setup Integration Test",
|
||||||
|
"category": "Test"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"command": "test.waitForExtensionsToLoad",
|
||||||
|
"title": "Wait For Extensions To Load",
|
||||||
|
"category": "Test"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"vscode:prepublish": "node ../../node_modules/gulp/bin/gulp.js --gulpfile ../../build/gulpfile.extensions.js compile-extension:vscode-colorize-tests ./tsconfig.json",
|
||||||
|
"postinstall": "node ./node_modules/vscode/bin/install"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "7.0.43",
|
||||||
|
"@types/chai": "3.4.34",
|
||||||
|
"mocha-junit-reporter": "^1.17.0",
|
||||||
|
"mocha-multi-reporters": "^1.1.7",
|
||||||
|
"vscode": "1.1.5",
|
||||||
|
"chai": "3.5.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
36
extensions/integration-tests/src/index.ts
Normal file
36
extensions/integration-tests/src/index.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
import { context } from './testContext';
|
||||||
|
|
||||||
|
const path = require('path');
|
||||||
|
const testRunner = require('vscode/lib/testrunner');
|
||||||
|
|
||||||
|
const suite = 'Integration Tests';
|
||||||
|
|
||||||
|
const options: any = {
|
||||||
|
ui: 'tdd',
|
||||||
|
useColors: true,
|
||||||
|
timeout: 600000
|
||||||
|
};
|
||||||
|
|
||||||
|
if (process.env.BUILD_ARTIFACTSTAGINGDIRECTORY) {
|
||||||
|
options.reporter = 'mocha-multi-reporters';
|
||||||
|
options.reporterOptions = {
|
||||||
|
reporterEnabled: 'spec, mocha-junit-reporter',
|
||||||
|
mochaJunitReporterReporterOptions: {
|
||||||
|
testsuitesTitle: `${suite} ${process.platform}`,
|
||||||
|
mochaFile: path.join(process.env.BUILD_ARTIFACTSTAGINGDIRECTORY, `test-results/${process.platform}-${suite.toLowerCase().replace(/[^\w]/g, '-')}-results.xml`)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vscode.workspace.getConfiguration('test')['testSetupCompleted']) {
|
||||||
|
context.RunTest = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
testRunner.configure(options);
|
||||||
|
|
||||||
|
export = testRunner;
|
||||||
77
extensions/integration-tests/src/main.ts
Normal file
77
extensions/integration-tests/src/main.ts
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
'use strict';
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
import * as sqlops from 'sqlops';
|
||||||
|
import { normalize, join } from 'path';
|
||||||
|
import * as fs from 'fs';
|
||||||
|
|
||||||
|
const TEST_SETUP_COMPLETED_TEXT: string = 'Test Setup Completed';
|
||||||
|
const EXTENSION_LOADED_TEXT: string = 'Test Extension Loaded';
|
||||||
|
const ALL_EXTENSION_LOADED_TEXT: string = 'All Extensions Loaded';
|
||||||
|
|
||||||
|
var statusBarItemTimer: NodeJS.Timer;
|
||||||
|
|
||||||
|
export function activate(context: vscode.ExtensionContext) {
|
||||||
|
var statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
|
||||||
|
vscode.commands.registerCommand('test.setupIntegrationTest', async () => {
|
||||||
|
let extensionInstallersFolder = normalize(join(__dirname, '../extensionInstallers'));
|
||||||
|
let installers = fs.readdirSync(extensionInstallersFolder);
|
||||||
|
for (let i = 0; i < installers.length; i++) {
|
||||||
|
if (installers[i].endsWith('.vsix')) {
|
||||||
|
let installerFullPath = join(extensionInstallersFolder, installers[i]);
|
||||||
|
await sqlops.extensions.install(installerFullPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await setConfiguration('workbench.enablePreviewFeatures', true);
|
||||||
|
await setConfiguration('workbench.showConnectDialogOnStartup', false);
|
||||||
|
await setConfiguration('test.testSetupCompleted', true);
|
||||||
|
showStatusBarItem(statusBarItem, TEST_SETUP_COMPLETED_TEXT);
|
||||||
|
});
|
||||||
|
|
||||||
|
vscode.commands.registerCommand('test.waitForExtensionsToLoad', async () => {
|
||||||
|
let expectedExtensions = ['Microsoft.agent', 'Microsoft.import', 'Microsoft.mssql', 'Microsoft.profiler'];
|
||||||
|
do {
|
||||||
|
let extensions = vscode.extensions.all.filter(ext => { return expectedExtensions.indexOf(ext.id) !== -1; });
|
||||||
|
|
||||||
|
let isReady = true;
|
||||||
|
for (let i = 0; i < extensions.length; i++) {
|
||||||
|
let extension = extensions[i];
|
||||||
|
isReady = isReady && extension.isActive;
|
||||||
|
if (!isReady) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isReady) {
|
||||||
|
showStatusBarItem(statusBarItem, ALL_EXTENSION_LOADED_TEXT);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
await new Promise(resolve => { setTimeout(resolve, 1000); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (true);
|
||||||
|
});
|
||||||
|
showStatusBarItem(statusBarItem, EXTENSION_LOADED_TEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showStatusBarItem(statusBarItem: vscode.StatusBarItem, text: string) {
|
||||||
|
statusBarItem.text = text;
|
||||||
|
statusBarItem.tooltip = text;
|
||||||
|
statusBarItem.show();
|
||||||
|
clearTimeout(statusBarItemTimer);
|
||||||
|
statusBarItemTimer = setTimeout(function () {
|
||||||
|
statusBarItem.hide();
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// this method is called when your extension is deactivated
|
||||||
|
export function deactivate(): void {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async function setConfiguration(name: string, value: any) {
|
||||||
|
await vscode.workspace.getConfiguration().update(name, value, true);
|
||||||
|
}
|
||||||
29
extensions/integration-tests/src/objectExplorer.test.ts
Normal file
29
extensions/integration-tests/src/objectExplorer.test.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import 'mocha';
|
||||||
|
import * as sqlops from 'sqlops';
|
||||||
|
import { context } from './testContext';
|
||||||
|
import { getDefaultTestingServer } from './testConfig';
|
||||||
|
import { connectToServer } from './utils';
|
||||||
|
import assert = require('assert');
|
||||||
|
|
||||||
|
if (context.RunTest) {
|
||||||
|
suite('Object Explorer integration test suite', () => {
|
||||||
|
test('context menu test', async function () {
|
||||||
|
await connectToServer(await getDefaultTestingServer());
|
||||||
|
let nodes = <sqlops.objectexplorer.ObjectExplorerNode[]>await sqlops.objectexplorer.getActiveConnectionNodes();
|
||||||
|
assert(nodes.length === 1, `expecting 1 active connection, actual: ${nodes.length}`);
|
||||||
|
let actions = await sqlops.objectexplorer.getNodeActions(nodes[0].connectionId, nodes[0].nodePath);
|
||||||
|
const expectedActions = ['Manage', 'New Query', 'Disconnect', 'Delete Connection', 'Refresh', 'Launch Profiler'];
|
||||||
|
|
||||||
|
const expectedString = expectedActions.join(',');
|
||||||
|
const actualString = actions.join(',');
|
||||||
|
assert(expectedActions.length === actions.length && expectedString === actualString, `Expected actions: "${expectedString}", Actual actions: "${actualString}"`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
21
extensions/integration-tests/src/setup.test.ts
Normal file
21
extensions/integration-tests/src/setup.test.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import 'mocha';
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
import { context } from './testContext';
|
||||||
|
|
||||||
|
if (!context.RunTest) {
|
||||||
|
suite('integration test setup', () => {
|
||||||
|
test('test setup', async function () {
|
||||||
|
//Prepare the environment and make it ready for testing
|
||||||
|
await vscode.commands.executeCommand('test.setupIntegrationTest');
|
||||||
|
//Reload the window, this is required for some changes made by the 'test.setupIntegrationTest' to work
|
||||||
|
await vscode.commands.executeCommand('workbench.action.reloadWindow');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
92
extensions/integration-tests/src/testConfig.ts
Normal file
92
extensions/integration-tests/src/testConfig.ts
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO: Due to a runtime error, I duplicated this file at these 2 locations:
|
||||||
|
$/extensions/integration-test/src/testConfig.ts
|
||||||
|
$/test/smoke/src/sql/testConfig.ts
|
||||||
|
for now, make sure to keep both files in sync.
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface ITestServerProfile {
|
||||||
|
serverName: string;
|
||||||
|
userName: string;
|
||||||
|
password: string;
|
||||||
|
authenticationType: AuthenticationType;
|
||||||
|
database: string;
|
||||||
|
provider: ConnectionProvider;
|
||||||
|
version: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface INameDisplayNamePair {
|
||||||
|
name: string;
|
||||||
|
displayName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum AuthenticationType {
|
||||||
|
Windows,
|
||||||
|
SqlLogin
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ConnectionProvider {
|
||||||
|
SQLServer
|
||||||
|
}
|
||||||
|
|
||||||
|
var connectionProviderMapping = {};
|
||||||
|
var authenticationTypeMapping = {};
|
||||||
|
connectionProviderMapping[ConnectionProvider.SQLServer] = { name: 'MSSQL', displayName: 'Microsoft SQL Server' };
|
||||||
|
|
||||||
|
authenticationTypeMapping[AuthenticationType.SqlLogin] = { name: 'SqlLogin', displayName: 'SQL Login' };
|
||||||
|
authenticationTypeMapping[AuthenticationType.Windows] = { name: 'Integrated', displayName: 'Windows Authentication' };
|
||||||
|
|
||||||
|
export class TestServerProfile {
|
||||||
|
constructor(private _profile: ITestServerProfile) { }
|
||||||
|
public get serverName(): string { return this._profile.serverName; }
|
||||||
|
public get userName(): string { return this._profile.userName; }
|
||||||
|
public get password(): string { return this._profile.password; }
|
||||||
|
public get database(): string { return this._profile.database; }
|
||||||
|
public get version(): string { return this._profile.version; }
|
||||||
|
public get provider(): ConnectionProvider { return this._profile.provider; }
|
||||||
|
public get providerName(): string { return getEnumMappingEntry(connectionProviderMapping, this.provider).name; }
|
||||||
|
public get providerDisplayName(): string { return getEnumMappingEntry(connectionProviderMapping, this.provider).displayName; }
|
||||||
|
public get authenticationType(): AuthenticationType { return this._profile.authenticationType; }
|
||||||
|
public get authenticationTypeName(): string { return getEnumMappingEntry(authenticationTypeMapping, this.authenticationType).name; }
|
||||||
|
public get authenticationTypeDisplayName(): string { return getEnumMappingEntry(authenticationTypeMapping, this.authenticationType).displayName; }
|
||||||
|
}
|
||||||
|
|
||||||
|
var TestingServers: TestServerProfile[] = [
|
||||||
|
new TestServerProfile(
|
||||||
|
{
|
||||||
|
serverName: 'SQLTOOLS2017-3',
|
||||||
|
userName: '',
|
||||||
|
password: '',
|
||||||
|
authenticationType: AuthenticationType.Windows,
|
||||||
|
database: 'master',
|
||||||
|
provider: ConnectionProvider.SQLServer,
|
||||||
|
version: '2017'
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
function getEnumMappingEntry(mapping: any, enumValue: any): INameDisplayNamePair {
|
||||||
|
let entry = mapping[enumValue];
|
||||||
|
if (entry) {
|
||||||
|
return entry;
|
||||||
|
} else {
|
||||||
|
throw `Unknown enum type: ${enumValue.toString()}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getDefaultTestingServer(): Promise<TestServerProfile> {
|
||||||
|
let servers = await getTestingServers();
|
||||||
|
return servers[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getTestingServers(): Promise<TestServerProfile[]> {
|
||||||
|
let promise = new Promise<TestServerProfile[]>(resolve => {
|
||||||
|
resolve(TestingServers);
|
||||||
|
});
|
||||||
|
await promise;
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
8
extensions/integration-tests/src/testContext.ts
Normal file
8
extensions/integration-tests/src/testContext.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
export var context = {
|
||||||
|
RunTest: true
|
||||||
|
};
|
||||||
8
extensions/integration-tests/src/typings/ref.d.ts
vendored
Normal file
8
extensions/integration-tests/src/typings/ref.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
/// <reference path='../../../../src/sql/sqlops.d.ts'/>
|
||||||
|
/// <reference path='../../../../src/sql/sqlops.proposed.d.ts'/>
|
||||||
|
/// <reference path='../../../../src/sql/sqlops.test.d.ts'/>
|
||||||
|
/// <reference types='@types/node'/>
|
||||||
38
extensions/integration-tests/src/utils.ts
Normal file
38
extensions/integration-tests/src/utils.ts
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import assert = require('assert');
|
||||||
|
import * as sqlops from 'sqlops';
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
import { TestServerProfile } from './testConfig';
|
||||||
|
|
||||||
|
export async function connectToServer(server: TestServerProfile) {
|
||||||
|
let connectionProfile: sqlops.IConnectionProfile = {
|
||||||
|
serverName: server.serverName,
|
||||||
|
databaseName: server.database,
|
||||||
|
authenticationType: server.authenticationTypeName,
|
||||||
|
providerName: server.providerName,
|
||||||
|
connectionName: '',
|
||||||
|
userName: server.userName,
|
||||||
|
password: server.password,
|
||||||
|
savePassword: false,
|
||||||
|
groupFullName: undefined,
|
||||||
|
saveProfile: true,
|
||||||
|
id: undefined,
|
||||||
|
groupId: undefined,
|
||||||
|
options: {}
|
||||||
|
};
|
||||||
|
await ensureConnectionViewOpened();
|
||||||
|
let result = <sqlops.ConnectionResult>await sqlops.connection.connect(connectionProfile);
|
||||||
|
assert(result.connected, `Failed to connect to "${connectionProfile.serverName}", error code: ${result.errorCode}, error message: ${result.errorMessage}`);
|
||||||
|
|
||||||
|
//workaround
|
||||||
|
//wait for OE to load
|
||||||
|
await new Promise(c => setTimeout(c, 3000));
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function ensureConnectionViewOpened() {
|
||||||
|
await vscode.commands.executeCommand('workbench.view.connections');
|
||||||
|
}
|
||||||
15
extensions/integration-tests/tsconfig.json
Normal file
15
extensions/integration-tests/tsconfig.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "commonjs",
|
||||||
|
"target": "ES5",
|
||||||
|
"outDir": "out",
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"lib": [
|
||||||
|
"es2015"
|
||||||
|
],
|
||||||
|
"sourceMap": true
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"src/**/*"
|
||||||
|
]
|
||||||
|
}
|
||||||
2047
extensions/integration-tests/yarn.lock
Normal file
2047
extensions/integration-tests/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
20
scripts/sql-test-integration.bat
Normal file
20
scripts/sql-test-integration.bat
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
setlocal
|
||||||
|
|
||||||
|
pushd %~dp0\..
|
||||||
|
|
||||||
|
set VSCODEUSERDATADIR=%TMP%\adsuser-%RANDOM%-%TIME:~6,5%
|
||||||
|
set VSCODEEXTENSIONSDIR=%TMP%\adsext-%RANDOM%-%TIME:~6,5%
|
||||||
|
echo %VSCODEUSERDATADIR%
|
||||||
|
echo %VSCODEEXTENSIONSDIR%
|
||||||
|
@echo OFF
|
||||||
|
|
||||||
|
call .\scripts\code.bat --extensionDevelopmentPath=%~dp0\..\extensions\integration-tests --extensionTestsPath=%~dp0\..\extensions\integration-tests\out --user-data-dir=%VSCODEUSERDATADIR% --extensions-dir=%VSCODEEXTENSIONSDIR%
|
||||||
|
|
||||||
|
if %errorlevel% neq 0 exit /b %errorlevel%
|
||||||
|
|
||||||
|
rmdir /s /q %VSCODEUSERDATADIR%
|
||||||
|
rmdir /s /q %VSCODEEXTENSIONSDIR%
|
||||||
|
|
||||||
|
popd
|
||||||
|
|
||||||
|
endlocal
|
||||||
23
scripts/sql-test-integration.sh
Normal file
23
scripts/sql-test-integration.sh
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
|
realpath() { [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}"; }
|
||||||
|
ROOT=$(dirname $(dirname $(realpath "$0")))
|
||||||
|
VSCODEUSERDATADIR=`mktemp -d -t 'myuserdatadir'`
|
||||||
|
VSCODEEXTDIR=`mktemp -d -t 'myextdir'`
|
||||||
|
else
|
||||||
|
ROOT=$(dirname $(dirname $(readlink -f $0)))
|
||||||
|
VSCODEUSERDATADIR=`mktemp -d 2>/dev/null`
|
||||||
|
VSCODEEXTDIR=`mktemp -d 2>/dev/null`
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd $ROOT
|
||||||
|
echo $VSCODEUSERDATADIR
|
||||||
|
echo $VSCODEEXTDIR
|
||||||
|
|
||||||
|
./scripts/code.sh --extensionDevelopmentPath=$ROOT/extensions/integration-tests --extensionTestsPath=$ROOT/extensions/integration-tests/out --user-data-dir=$VSCODEUSERDATADIR --extensions-dir=$VSCODEEXTDIR
|
||||||
|
|
||||||
|
|
||||||
|
rm -r $VSCODEUSERDATADIR
|
||||||
|
rm -r $VSCODEEXTDIR
|
||||||
@@ -15,6 +15,7 @@ import { ConnectionProviderProperties, IConnectionProviderRegistry, Extensions a
|
|||||||
import * as TaskUtilities from 'sql/workbench/common/taskUtilities';
|
import * as TaskUtilities from 'sql/workbench/common/taskUtilities';
|
||||||
import { IObjectExplorerService } from 'sql/parts/objectExplorer/common/objectExplorerService';
|
import { IObjectExplorerService } from 'sql/parts/objectExplorer/common/objectExplorerService';
|
||||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||||
|
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
|
||||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||||
import { warn } from 'sql/base/common/log';
|
import { warn } from 'sql/base/common/log';
|
||||||
|
|
||||||
@@ -30,7 +31,8 @@ export class CommandLineService implements ICommandLineProcessing {
|
|||||||
@IQueryEditorService private _queryEditorService: IQueryEditorService,
|
@IQueryEditorService private _queryEditorService: IQueryEditorService,
|
||||||
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
|
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
|
||||||
@IEditorService private _editorService: IEditorService,
|
@IEditorService private _editorService: IEditorService,
|
||||||
@ICommandService private _commandService: ICommandService
|
@ICommandService private _commandService: ICommandService,
|
||||||
|
@IWorkspaceConfigurationService private _configurationService: IWorkspaceConfigurationService
|
||||||
) {
|
) {
|
||||||
let profile = null;
|
let profile = null;
|
||||||
if (this._environmentService) {
|
if (this._environmentService) {
|
||||||
@@ -76,8 +78,8 @@ export class CommandLineService implements ICommandLineProcessing {
|
|||||||
|
|
||||||
let self = this;
|
let self = this;
|
||||||
return new Promise<void>((resolve, reject) => {
|
return new Promise<void>((resolve, reject) => {
|
||||||
|
let showConnectDialogOnStartup: boolean = this._configurationService.getValue('workbench.showConnectDialogOnStartup');
|
||||||
if (!self._commandName && !self._connectionProfile && !self._connectionManagementService.hasRegisteredServers()) {
|
if (showConnectDialogOnStartup && !self._commandName && !self._connectionProfile && !self._connectionManagementService.hasRegisteredServers()) {
|
||||||
// prompt the user for a new connection on startup if no profiles are registered
|
// prompt the user for a new connection on startup if no profiles are registered
|
||||||
self._connectionManagementService.showConnectionDialog()
|
self._connectionManagementService.showConnectionDialog()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|||||||
@@ -77,6 +77,11 @@ export interface IObjectExplorerService {
|
|||||||
getTreeNode(connectionId: string, nodePath: string): Thenable<TreeNode>;
|
getTreeNode(connectionId: string, nodePath: string): Thenable<TreeNode>;
|
||||||
|
|
||||||
refreshNodeInView(connectionId: string, nodePath: string): Thenable<TreeNode>;
|
refreshNodeInView(connectionId: string, nodePath: string): Thenable<TreeNode>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For Testing purpose only. Get the context menu actions for an object explorer node.
|
||||||
|
*/
|
||||||
|
getNodeActions(connectionId: string, nodePath: string): Thenable<string[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SessionStatus {
|
interface SessionStatus {
|
||||||
@@ -522,6 +527,17 @@ export class ObjectExplorerService implements IObjectExplorerService {
|
|||||||
return Object.values(this._activeObjectExplorerNodes);
|
return Object.values(this._activeObjectExplorerNodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For Testing purpose only. Get the context menu actions for an object explorer node
|
||||||
|
*/
|
||||||
|
public getNodeActions(connectionId: string, nodePath: string): Thenable<string[]> {
|
||||||
|
return this.getTreeNode(connectionId, nodePath).then(node => {
|
||||||
|
return this._serverTreeView.treeActionProvider.getActions(this._serverTreeView.tree, this.getTreeItem(node)).then((actions) => {
|
||||||
|
return actions.filter(action => action.label).map(action => action.label);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public async refreshNodeInView(connectionId: string, nodePath: string): Promise<TreeNode> {
|
public async refreshNodeInView(connectionId: string, nodePath: string): Promise<TreeNode> {
|
||||||
// Get the tree node and call refresh from the provider
|
// Get the tree node and call refresh from the provider
|
||||||
let treeNode = await this.getTreeNode(connectionId, nodePath);
|
let treeNode = await this.getTreeNode(connectionId, nodePath);
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import { Event, Emitter } from 'vs/base/common/event';
|
|||||||
import { TreeNode, TreeItemCollapsibleState } from 'sql/parts/objectExplorer/common/treeNode';
|
import { TreeNode, TreeItemCollapsibleState } from 'sql/parts/objectExplorer/common/treeNode';
|
||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
import { SERVER_GROUP_CONFIG, SERVER_GROUP_AUTOEXPAND_CONFIG } from 'sql/parts/objectExplorer/serverGroupDialog/serverGroup.contribution';
|
import { SERVER_GROUP_CONFIG, SERVER_GROUP_AUTOEXPAND_CONFIG } from 'sql/parts/objectExplorer/serverGroupDialog/serverGroup.contribution';
|
||||||
|
import { ServerTreeActionProvider } from 'sql/parts/objectExplorer/viewlet/serverTreeActionProvider';
|
||||||
|
|
||||||
const $ = builder.$;
|
const $ = builder.$;
|
||||||
|
|
||||||
@@ -46,7 +47,7 @@ export class ServerTreeView {
|
|||||||
private _tree: ITree;
|
private _tree: ITree;
|
||||||
private _toDispose: IDisposable[] = [];
|
private _toDispose: IDisposable[] = [];
|
||||||
private _onSelectionOrFocusChange: Emitter<void>;
|
private _onSelectionOrFocusChange: Emitter<void>;
|
||||||
|
private _actionProvider: ServerTreeActionProvider;
|
||||||
constructor(
|
constructor(
|
||||||
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
|
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
|
||||||
@IInstantiationService private _instantiationService: IInstantiationService,
|
@IInstantiationService private _instantiationService: IInstantiationService,
|
||||||
@@ -63,6 +64,7 @@ export class ServerTreeView {
|
|||||||
this);
|
this);
|
||||||
this._treeSelectionHandler = this._instantiationService.createInstance(TreeSelectionHandler);
|
this._treeSelectionHandler = this._instantiationService.createInstance(TreeSelectionHandler);
|
||||||
this._onSelectionOrFocusChange = new Emitter();
|
this._onSelectionOrFocusChange = new Emitter();
|
||||||
|
this._actionProvider = this._instantiationService.createInstance(ServerTreeActionProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -79,6 +81,14 @@ export class ServerTreeView {
|
|||||||
return this._onSelectionOrFocusChange.event;
|
return this._onSelectionOrFocusChange.event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public get treeActionProvider(): ServerTreeActionProvider {
|
||||||
|
return this._actionProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public get tree(): ITree {
|
||||||
|
return this._tree;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render the view body
|
* Render the view body
|
||||||
*/
|
*/
|
||||||
@@ -98,7 +108,6 @@ export class ServerTreeView {
|
|||||||
this._connectionManagementService.showConnectionDialog();
|
this._connectionManagementService.showConnectionDialog();
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
this._tree = TreeCreationUtils.createRegisteredServersTree(container, this._instantiationService);
|
this._tree = TreeCreationUtils.createRegisteredServersTree(container, this._instantiationService);
|
||||||
//this._tree.setInput(undefined);
|
//this._tree.setInput(undefined);
|
||||||
this._toDispose.push(this._tree.onDidChangeSelection((event) => this.onSelected(event)));
|
this._toDispose.push(this._tree.onDidChangeSelection((event) => this.onSelected(event)));
|
||||||
|
|||||||
18
src/sql/sqlops.proposed.d.ts
vendored
18
src/sql/sqlops.proposed.d.ts
vendored
@@ -133,7 +133,7 @@ declare module 'sqlops' {
|
|||||||
* @param index index to insert the component to
|
* @param index index to insert the component to
|
||||||
* @param itemLayout Item Layout
|
* @param itemLayout Item Layout
|
||||||
*/
|
*/
|
||||||
insertFormItem(formComponent: FormComponent | FormComponentGroup, index?: number, itemLayout?: FormItemLayout);
|
insertFormItem(formComponent: FormComponent | FormComponentGroup, index?: number, itemLayout?: FormItemLayout): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes a from item from the from
|
* Removes a from item from the from
|
||||||
@@ -1209,7 +1209,7 @@ declare module 'sqlops' {
|
|||||||
* Registers a save handler for this editor. This will be called if [supportsSave](#ModelViewEditorOptions.supportsSave)
|
* Registers a save handler for this editor. This will be called if [supportsSave](#ModelViewEditorOptions.supportsSave)
|
||||||
* is set to true and the editor is marked as dirty
|
* is set to true and the editor is marked as dirty
|
||||||
*/
|
*/
|
||||||
registerSaveHandler(handler: () => Thenable<boolean>);
|
registerSaveHandler(handler: () => Thenable<boolean>): void;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1349,6 +1349,13 @@ declare module 'sqlops' {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ConnectionResult {
|
||||||
|
connected: boolean;
|
||||||
|
connectionId: string;
|
||||||
|
errorMessage: string;
|
||||||
|
errorCode: number;
|
||||||
|
}
|
||||||
|
|
||||||
export namespace connection {
|
export namespace connection {
|
||||||
/**
|
/**
|
||||||
* List the databases that can be accessed from the given connection
|
* List the databases that can be accessed from the given connection
|
||||||
@@ -1371,6 +1378,12 @@ declare module 'sqlops' {
|
|||||||
* @param callback
|
* @param callback
|
||||||
*/
|
*/
|
||||||
export function openConnectionDialog(providers?: string[], initialConnectionProfile?: IConnectionProfile, connectionCompletionOptions?: IConnectionCompletionOptions): Thenable<connection.Connection>;
|
export function openConnectionDialog(providers?: string[], initialConnectionProfile?: IConnectionProfile, connectionCompletionOptions?: IConnectionCompletionOptions): Thenable<connection.Connection>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the connection and add it to object explorer and opens the dashboard and returns the ConnectionResult
|
||||||
|
* @param connectionProfile connection profile
|
||||||
|
*/
|
||||||
|
export function connect(connectionProfile: IConnectionProfile): Thenable<ConnectionResult>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace nb {
|
export namespace nb {
|
||||||
@@ -2319,5 +2332,4 @@ declare module 'sqlops' {
|
|||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
23
src/sql/sqlops.test.d.ts
vendored
Normal file
23
src/sql/sqlops.test.d.ts
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// This is the place for APIs used for testing
|
||||||
|
|
||||||
|
import * as core from 'sqlops';
|
||||||
|
import * as vscode from 'vscode';
|
||||||
|
|
||||||
|
declare module 'sqlops' {
|
||||||
|
|
||||||
|
export namespace extensions {
|
||||||
|
export function install(vsixPath: string): Thenable<string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace objectexplorer {
|
||||||
|
/**
|
||||||
|
* get object explorer node context menu actions
|
||||||
|
*/
|
||||||
|
export function getNodeActions(connectionId: string, nodePath: string): Thenable<string[]>;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -47,4 +47,8 @@ export class ExtHostConnectionManagement extends ExtHostConnectionManagementShap
|
|||||||
public $getUriForConnection(connectionId: string): Thenable<string> {
|
public $getUriForConnection(connectionId: string): Thenable<string> {
|
||||||
return this._proxy.$getUriForConnection(connectionId);
|
return this._proxy.$getUriForConnection(connectionId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public $connect(connectionProfile: sqlops.IConnectionProfile): Thenable<sqlops.ConnectionResult> {
|
||||||
|
return this._proxy.$connect(connectionProfile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
23
src/sql/workbench/api/node/extHostExtensionManagement.ts
Normal file
23
src/sql/workbench/api/node/extHostExtensionManagement.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import { IMainContext } from 'vs/workbench/api/node/extHost.protocol';
|
||||||
|
|
||||||
|
import { ExtHostExtensionManagementShape, MainThreadExtensionManagementShape, SqlMainContext } from 'sql/workbench/api/node/sqlExtHost.protocol';
|
||||||
|
|
||||||
|
|
||||||
|
export class ExtHostExtensionManagement implements ExtHostExtensionManagementShape {
|
||||||
|
|
||||||
|
private readonly _proxy: MainThreadExtensionManagementShape;
|
||||||
|
|
||||||
|
constructor(_mainContext: IMainContext) {
|
||||||
|
this._proxy = _mainContext.getProxy(SqlMainContext.MainThreadExtensionManagement);
|
||||||
|
}
|
||||||
|
|
||||||
|
$install(vsixPath: string): Thenable<string> {
|
||||||
|
return this._proxy.$install(vsixPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -105,7 +105,7 @@ class ModelViewEditorImpl extends ModelViewPanelImpl implements sqlops.workspace
|
|||||||
this._proxy.$setDirty(this.handle, value);
|
this._proxy.$setDirty(this.handle, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
registerSaveHandler(handler: () => Thenable<boolean>) {
|
registerSaveHandler(handler: () => Thenable<boolean>): void {
|
||||||
this._saveHandler = handler;
|
this._saveHandler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,10 @@ export class ExtHostObjectExplorer implements ExtHostObjectExplorerShape {
|
|||||||
public $findNodes(connectionId: string, type: string, schema: string, name: string, database: string, parentObjectNames: string[]): Thenable<sqlops.objectexplorer.ObjectExplorerNode[]> {
|
public $findNodes(connectionId: string, type: string, schema: string, name: string, database: string, parentObjectNames: string[]): Thenable<sqlops.objectexplorer.ObjectExplorerNode[]> {
|
||||||
return this._proxy.$findNodes(connectionId, type, schema, name, database, parentObjectNames).then(results => results.map(result => new ExtHostObjectExplorerNode(result, connectionId, this._proxy)));
|
return this._proxy.$findNodes(connectionId, type, schema, name, database, parentObjectNames).then(results => results.map(result => new ExtHostObjectExplorerNode(result, connectionId, this._proxy)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public $getNodeActions(connectionId: string, nodePath: string): Thenable<string[]> {
|
||||||
|
return this._proxy.$getNodeActions(connectionId, nodePath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ExtHostObjectExplorerNode implements sqlops.objectexplorer.ObjectExplorerNode {
|
class ExtHostObjectExplorerNode implements sqlops.objectexplorer.ObjectExplorerNode {
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ import * as TaskUtilities from 'sql/workbench/common/taskUtilities';
|
|||||||
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
|
||||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||||
import { isUndefinedOrNull } from 'vs/base/common/types';
|
import { isUndefinedOrNull } from 'vs/base/common/types';
|
||||||
|
import { generateUuid } from 'vs/base/common/uuid';
|
||||||
|
import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
|
||||||
|
import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
|
||||||
|
|
||||||
@extHostNamedCustomer(SqlMainContext.MainThreadConnectionManagement)
|
@extHostNamedCustomer(SqlMainContext.MainThreadConnectionManagement)
|
||||||
export class MainThreadConnectionManagement implements MainThreadConnectionManagementShape {
|
export class MainThreadConnectionManagement implements MainThreadConnectionManagementShape {
|
||||||
@@ -28,6 +31,7 @@ export class MainThreadConnectionManagement implements MainThreadConnectionManag
|
|||||||
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
|
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
|
||||||
@IEditorService private _workbenchEditorService: IEditorService,
|
@IEditorService private _workbenchEditorService: IEditorService,
|
||||||
@IConnectionDialogService private _connectionDialogService: IConnectionDialogService,
|
@IConnectionDialogService private _connectionDialogService: IConnectionDialogService,
|
||||||
|
@ICapabilitiesService private _capabilitiesService: ICapabilitiesService
|
||||||
) {
|
) {
|
||||||
if (extHostContext) {
|
if (extHostContext) {
|
||||||
this._proxy = extHostContext.getProxy(SqlExtHostContext.ExtHostConnectionManagement);
|
this._proxy = extHostContext.getProxy(SqlExtHostContext.ExtHostConnectionManagement);
|
||||||
@@ -101,4 +105,23 @@ export class MainThreadConnectionManagement implements MainThreadConnectionManag
|
|||||||
};
|
};
|
||||||
return connection;
|
return connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public $connect(connectionProfile: IConnectionProfile): Thenable<sqlops.ConnectionResult> {
|
||||||
|
let profile = new ConnectionProfile(this._capabilitiesService, connectionProfile);
|
||||||
|
profile.id = generateUuid();
|
||||||
|
return this._connectionManagementService.connectAndSaveProfile(profile, undefined, {
|
||||||
|
saveTheConnection: true,
|
||||||
|
showDashboard: true,
|
||||||
|
params: undefined,
|
||||||
|
showConnectionDialogOnError: true,
|
||||||
|
showFirewallRuleOnError: true
|
||||||
|
}).then((result) => {
|
||||||
|
return <sqlops.ConnectionResult>{
|
||||||
|
connected: result.connected,
|
||||||
|
connectionId: result.connected ? profile.id : undefined,
|
||||||
|
errorCode: result.errorCode,
|
||||||
|
errorMessage: result.errorMessage
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
32
src/sql/workbench/api/node/mainThreadExtensionManagement.ts
Normal file
32
src/sql/workbench/api/node/mainThreadExtensionManagement.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import { SqlMainContext, MainThreadExtensionManagementShape } from 'sql/workbench/api/node/sqlExtHost.protocol';
|
||||||
|
import { IExtHostContext } from 'vs/workbench/api/node/extHost.protocol';
|
||||||
|
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
|
||||||
|
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||||
|
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||||
|
|
||||||
|
@extHostNamedCustomer(SqlMainContext.MainThreadExtensionManagement)
|
||||||
|
export class MainThreadExtensionManagement implements MainThreadExtensionManagementShape {
|
||||||
|
|
||||||
|
private _toDispose: IDisposable[];
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
extHostContext: IExtHostContext,
|
||||||
|
@IExtensionManagementService private _extensionService: IExtensionManagementService
|
||||||
|
) {
|
||||||
|
this._toDispose = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public dispose(): void {
|
||||||
|
this._toDispose = dispose(this._toDispose);
|
||||||
|
}
|
||||||
|
|
||||||
|
public $install(vsixPath: string): Thenable<string> {
|
||||||
|
return this._extensionService.install(vsixPath).then((value: void) => { return undefined; }, (reason: any) => { return reason ? reason.toString() : undefined; });
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -78,4 +78,8 @@ export class MainThreadObjectExplorer implements MainThreadObjectExplorerShape {
|
|||||||
public $refresh(connectionId: string, nodePath: string): Thenable<sqlops.NodeInfo> {
|
public $refresh(connectionId: string, nodePath: string): Thenable<sqlops.NodeInfo> {
|
||||||
return this._objectExplorerService.refreshNodeInView(connectionId, nodePath).then(node => node.toNodeInfo());
|
return this._objectExplorerService.refreshNodeInView(connectionId, nodePath).then(node => node.toNodeInfo());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public $getNodeActions(connectionId: string, nodePath: string): Thenable<string[]> {
|
||||||
|
return this._objectExplorerService.getNodeActions(connectionId, nodePath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import { ExtHostQueryEditor } from 'sql/workbench/api/node/extHostQueryEditor';
|
|||||||
import { ExtHostBackgroundTaskManagement } from './extHostBackgroundTaskManagement';
|
import { ExtHostBackgroundTaskManagement } from './extHostBackgroundTaskManagement';
|
||||||
import { ExtHostNotebook } from 'sql/workbench/api/node/extHostNotebook';
|
import { ExtHostNotebook } from 'sql/workbench/api/node/extHostNotebook';
|
||||||
import { ExtHostNotebookDocumentsAndEditors } from 'sql/workbench/api/node/extHostNotebookDocumentsAndEditors';
|
import { ExtHostNotebookDocumentsAndEditors } from 'sql/workbench/api/node/extHostNotebookDocumentsAndEditors';
|
||||||
|
import { ExtHostExtensionManagement } from 'sql/workbench/api/node/extHostExtensionManagement';
|
||||||
|
|
||||||
export interface ISqlExtensionApiFactory {
|
export interface ISqlExtensionApiFactory {
|
||||||
vsCodeFactory(extension: IExtensionDescription): typeof vscode;
|
vsCodeFactory(extension: IExtensionDescription): typeof vscode;
|
||||||
@@ -77,6 +78,7 @@ export function createApiFactory(
|
|||||||
const extHostQueryEditor = rpcProtocol.set(SqlExtHostContext.ExtHostQueryEditor, new ExtHostQueryEditor(rpcProtocol));
|
const extHostQueryEditor = rpcProtocol.set(SqlExtHostContext.ExtHostQueryEditor, new ExtHostQueryEditor(rpcProtocol));
|
||||||
const extHostNotebook = rpcProtocol.set(SqlExtHostContext.ExtHostNotebook, new ExtHostNotebook(rpcProtocol));
|
const extHostNotebook = rpcProtocol.set(SqlExtHostContext.ExtHostNotebook, new ExtHostNotebook(rpcProtocol));
|
||||||
const extHostNotebookDocumentsAndEditors = rpcProtocol.set(SqlExtHostContext.ExtHostNotebookDocumentsAndEditors, new ExtHostNotebookDocumentsAndEditors(rpcProtocol));
|
const extHostNotebookDocumentsAndEditors = rpcProtocol.set(SqlExtHostContext.ExtHostNotebookDocumentsAndEditors, new ExtHostNotebookDocumentsAndEditors(rpcProtocol));
|
||||||
|
const extHostExtensionManagement = rpcProtocol.set(SqlExtHostContext.ExtHostExtensionManagement, new ExtHostExtensionManagement(rpcProtocol));
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -129,6 +131,9 @@ export function createApiFactory(
|
|||||||
},
|
},
|
||||||
getUriForConnection(connectionId: string): Thenable<string> {
|
getUriForConnection(connectionId: string): Thenable<string> {
|
||||||
return extHostConnectionManagement.$getUriForConnection(connectionId);
|
return extHostConnectionManagement.$getUriForConnection(connectionId);
|
||||||
|
},
|
||||||
|
connect(connectionProfile: sqlops.IConnectionProfile): Thenable<sqlops.ConnectionResult> {
|
||||||
|
return extHostConnectionManagement.$connect(connectionProfile);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -152,6 +157,9 @@ export function createApiFactory(
|
|||||||
},
|
},
|
||||||
findNodes(connectionId: string, type: string, schema: string, name: string, database: string, parentObjectNames: string[]): Thenable<sqlops.objectexplorer.ObjectExplorerNode[]> {
|
findNodes(connectionId: string, type: string, schema: string, name: string, database: string, parentObjectNames: string[]): Thenable<sqlops.objectexplorer.ObjectExplorerNode[]> {
|
||||||
return extHostObjectExplorer.$findNodes(connectionId, type, schema, name, database, parentObjectNames);
|
return extHostObjectExplorer.$findNodes(connectionId, type, schema, name, database, parentObjectNames);
|
||||||
|
},
|
||||||
|
getNodeActions(connectionId: string, nodePath: string): Thenable<string[]> {
|
||||||
|
return extHostObjectExplorer.$getNodeActions(connectionId, nodePath);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -421,6 +429,12 @@ export function createApiFactory(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const extensions: typeof sqlops.extensions = {
|
||||||
|
install(vsixPath: string): Thenable<string> {
|
||||||
|
return extHostExtensionManagement.$install(vsixPath);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const nb = {
|
const nb = {
|
||||||
get notebookDocuments() {
|
get notebookDocuments() {
|
||||||
return extHostNotebookDocumentsAndEditors.getAllDocuments().map(doc => doc.document);
|
return extHostNotebookDocumentsAndEditors.getAllDocuments().map(doc => doc.document);
|
||||||
@@ -483,7 +497,8 @@ export function createApiFactory(
|
|||||||
SqlThemeIcon: sqlExtHostTypes.SqlThemeIcon,
|
SqlThemeIcon: sqlExtHostTypes.SqlThemeIcon,
|
||||||
TreeComponentItem: sqlExtHostTypes.TreeComponentItem,
|
TreeComponentItem: sqlExtHostTypes.TreeComponentItem,
|
||||||
nb: nb,
|
nb: nb,
|
||||||
AzureResource: sqlExtHostTypes.AzureResource
|
AzureResource: sqlExtHostTypes.AzureResource,
|
||||||
|
extensions: extensions,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import 'sql/workbench/api/node/mainThreadModelViewDialog';
|
|||||||
import 'sql/workbench/api/node/mainThreadNotebook';
|
import 'sql/workbench/api/node/mainThreadNotebook';
|
||||||
import 'sql/workbench/api/node/mainThreadNotebookDocumentsAndEditors';
|
import 'sql/workbench/api/node/mainThreadNotebookDocumentsAndEditors';
|
||||||
import 'sql/workbench/api/node/mainThreadAccountManagement';
|
import 'sql/workbench/api/node/mainThreadAccountManagement';
|
||||||
|
import 'sql/workbench/api/node/mainThreadExtensionManagement';
|
||||||
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
||||||
|
|
||||||
export class SqlExtHostContribution implements IWorkbenchContribution {
|
export class SqlExtHostContribution implements IWorkbenchContribution {
|
||||||
|
|||||||
@@ -546,6 +546,7 @@ export interface MainThreadConnectionManagementShape extends IDisposable {
|
|||||||
$listDatabases(connectionId: string): Thenable<string[]>;
|
$listDatabases(connectionId: string): Thenable<string[]>;
|
||||||
$getConnectionString(connectionId: string, includePassword: boolean): Thenable<string>;
|
$getConnectionString(connectionId: string, includePassword: boolean): Thenable<string>;
|
||||||
$getUriForConnection(connectionId: string): Thenable<string>;
|
$getUriForConnection(connectionId: string): Thenable<string>;
|
||||||
|
$connect(connectionProfile: sqlops.IConnectionProfile): Thenable<sqlops.ConnectionResult>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MainThreadCredentialManagementShape extends IDisposable {
|
export interface MainThreadCredentialManagementShape extends IDisposable {
|
||||||
@@ -580,8 +581,8 @@ export const SqlMainContext = {
|
|||||||
MainThreadModelViewDialog: createMainId<MainThreadModelViewDialogShape>('MainThreadModelViewDialog'),
|
MainThreadModelViewDialog: createMainId<MainThreadModelViewDialogShape>('MainThreadModelViewDialog'),
|
||||||
MainThreadQueryEditor: createMainId<MainThreadQueryEditorShape>('MainThreadQueryEditor'),
|
MainThreadQueryEditor: createMainId<MainThreadQueryEditorShape>('MainThreadQueryEditor'),
|
||||||
MainThreadNotebook: createMainId<MainThreadNotebookShape>('MainThreadNotebook'),
|
MainThreadNotebook: createMainId<MainThreadNotebookShape>('MainThreadNotebook'),
|
||||||
MainThreadNotebookDocumentsAndEditors: createMainId<MainThreadNotebookDocumentsAndEditorsShape>('MainThreadNotebookDocumentsAndEditors')
|
MainThreadNotebookDocumentsAndEditors: createMainId<MainThreadNotebookDocumentsAndEditorsShape>('MainThreadNotebookDocumentsAndEditors'),
|
||||||
|
MainThreadExtensionManagement: createMainId<MainThreadExtensionManagementShape>('MainThreadExtensionManagement')
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SqlExtHostContext = {
|
export const SqlExtHostContext = {
|
||||||
@@ -602,7 +603,8 @@ export const SqlExtHostContext = {
|
|||||||
ExtHostModelViewDialog: createExtId<ExtHostModelViewDialogShape>('ExtHostModelViewDialog'),
|
ExtHostModelViewDialog: createExtId<ExtHostModelViewDialogShape>('ExtHostModelViewDialog'),
|
||||||
ExtHostQueryEditor: createExtId<ExtHostQueryEditorShape>('ExtHostQueryEditor'),
|
ExtHostQueryEditor: createExtId<ExtHostQueryEditorShape>('ExtHostQueryEditor'),
|
||||||
ExtHostNotebook: createExtId<ExtHostNotebookShape>('ExtHostNotebook'),
|
ExtHostNotebook: createExtId<ExtHostNotebookShape>('ExtHostNotebook'),
|
||||||
ExtHostNotebookDocumentsAndEditors: createExtId<ExtHostNotebookDocumentsAndEditorsShape>('ExtHostNotebookDocumentsAndEditors')
|
ExtHostNotebookDocumentsAndEditors: createExtId<ExtHostNotebookDocumentsAndEditorsShape>('ExtHostNotebookDocumentsAndEditors'),
|
||||||
|
ExtHostExtensionManagement: createExtId<ExtHostExtensionManagementShape>('ExtHostExtensionManagement')
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface MainThreadDashboardShape extends IDisposable {
|
export interface MainThreadDashboardShape extends IDisposable {
|
||||||
@@ -708,6 +710,7 @@ export interface MainThreadObjectExplorerShape extends IDisposable {
|
|||||||
$isExpanded(connectionId: string, nodePath: string): Thenable<boolean>;
|
$isExpanded(connectionId: string, nodePath: string): Thenable<boolean>;
|
||||||
$findNodes(connectionId: string, type: string, schema: string, name: string, database: string, parentObjectNames: string[]): Thenable<sqlops.NodeInfo[]>;
|
$findNodes(connectionId: string, type: string, schema: string, name: string, database: string, parentObjectNames: string[]): Thenable<sqlops.NodeInfo[]>;
|
||||||
$refresh(connectionId: string, nodePath: string): Thenable<sqlops.NodeInfo>;
|
$refresh(connectionId: string, nodePath: string): Thenable<sqlops.NodeInfo>;
|
||||||
|
$getNodeActions(connectionId: string, nodePath: string): Thenable<string[]>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ExtHostModelViewDialogShape {
|
export interface ExtHostModelViewDialogShape {
|
||||||
@@ -838,3 +841,11 @@ export interface MainThreadNotebookDocumentsAndEditorsShape extends IDisposable
|
|||||||
$tryShowNotebookDocument(resource: UriComponents, options: INotebookShowOptions): TPromise<string>;
|
$tryShowNotebookDocument(resource: UriComponents, options: INotebookShowOptions): TPromise<string>;
|
||||||
$tryApplyEdits(id: string, modelVersionId: number, edits: ISingleNotebookEditOperation[], opts: IUndoStopOptions): TPromise<boolean>;
|
$tryApplyEdits(id: string, modelVersionId: number, edits: ISingleNotebookEditOperation[], opts: IUndoStopOptions): TPromise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ExtHostExtensionManagementShape {
|
||||||
|
$install(vsixPath: string): Thenable<string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MainThreadExtensionManagementShape extends IDisposable {
|
||||||
|
$install(vsixPath: string): Thenable<string>;
|
||||||
|
}
|
||||||
@@ -37,3 +37,16 @@ Registry.as<IConfigurationRegistry>(ConfigExtensions.Configuration).registerConf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Registry.as<IConfigurationRegistry>(ConfigExtensions.Configuration).registerConfiguration({
|
||||||
|
'id': 'showConnectDialogOnStartup',
|
||||||
|
'title': nls.localize('showConnectDialogOnStartup', 'Show connect dialog on startup'),
|
||||||
|
'type': 'object',
|
||||||
|
'properties': {
|
||||||
|
'workbench.showConnectDialogOnStartup': {
|
||||||
|
'type': 'boolean',
|
||||||
|
'default': true,
|
||||||
|
'description': nls.localize('showConnectDialogOnStartup', 'Show connect dialog on startup')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -32,6 +32,8 @@ import { ConnectionStore } from 'sql/parts/connection/common/connectionStore';
|
|||||||
import { TestConnectionManagementService } from 'sqltest/stubs/connectionManagementService.test';
|
import { TestConnectionManagementService } from 'sqltest/stubs/connectionManagementService.test';
|
||||||
import { ICommandService, ICommandEvent, CommandsRegistry } from 'vs/platform/commands/common/commands';
|
import { ICommandService, ICommandEvent, CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||||
import { TestCommandService } from 'vs/editor/test/browser/editorTestServices';
|
import { TestCommandService } from 'vs/editor/test/browser/editorTestServices';
|
||||||
|
import { WorkspaceConfigurationTestService } from 'sqltest/stubs/workspaceConfigurationTestService';
|
||||||
|
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
|
||||||
|
|
||||||
class TestParsedArgs implements ParsedArgs {
|
class TestParsedArgs implements ParsedArgs {
|
||||||
[arg: string]: any;
|
[arg: string]: any;
|
||||||
@@ -112,11 +114,11 @@ suite('commandLineService tests', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function getCommandLineService(connectionManagementService: IConnectionManagementService,
|
function getCommandLineService(connectionManagementService: IConnectionManagementService,
|
||||||
|
configurationService: IWorkspaceConfigurationService,
|
||||||
environmentService?: IEnvironmentService,
|
environmentService?: IEnvironmentService,
|
||||||
capabilitiesService?: ICapabilitiesService,
|
capabilitiesService?: ICapabilitiesService,
|
||||||
commandService?: ICommandService
|
commandService?: ICommandService
|
||||||
) : CommandLineService
|
): CommandLineService {
|
||||||
{
|
|
||||||
let service = new CommandLineService(
|
let service = new CommandLineService(
|
||||||
connectionManagementService,
|
connectionManagementService,
|
||||||
capabilitiesService,
|
capabilitiesService,
|
||||||
@@ -124,11 +126,18 @@ suite('commandLineService tests', () => {
|
|||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
commandService
|
commandService,
|
||||||
|
configurationService
|
||||||
);
|
);
|
||||||
return service;
|
return service;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getConfigurationServiceMock(showConnectDialogOnStartup: boolean): TypeMoq.Mock<IWorkspaceConfigurationService> {
|
||||||
|
let configurationService = TypeMoq.Mock.ofType<IWorkspaceConfigurationService>(WorkspaceConfigurationTestService);
|
||||||
|
configurationService.setup((c) => c.getValue(TypeMoq.It.isAnyString())).returns((config: string) => showConnectDialogOnStartup);
|
||||||
|
return configurationService;
|
||||||
|
}
|
||||||
|
|
||||||
test('processCommandLine shows connection dialog by default', done => {
|
test('processCommandLine shows connection dialog by default', done => {
|
||||||
const connectionManagementService: TypeMoq.Mock<IConnectionManagementService>
|
const connectionManagementService: TypeMoq.Mock<IConnectionManagementService>
|
||||||
= TypeMoq.Mock.ofType<IConnectionManagementService>(TestConnectionManagementService, TypeMoq.MockBehavior.Strict);
|
= TypeMoq.Mock.ofType<IConnectionManagementService>(TestConnectionManagementService, TypeMoq.MockBehavior.Strict);
|
||||||
@@ -140,13 +149,30 @@ suite('commandLineService tests', () => {
|
|||||||
connectionManagementService.setup(c => c.connectIfNotConnected(TypeMoq.It.isAny(), TypeMoq.It.isAny()))
|
connectionManagementService.setup(c => c.connectIfNotConnected(TypeMoq.It.isAny(), TypeMoq.It.isAny()))
|
||||||
.returns(() => new Promise<string>((resolve, reject) => { resolve('unused'); }))
|
.returns(() => new Promise<string>((resolve, reject) => { resolve('unused'); }))
|
||||||
.verifiable(TypeMoq.Times.never());
|
.verifiable(TypeMoq.Times.never());
|
||||||
let service = getCommandLineService(connectionManagementService.object);
|
const configurationService = getConfigurationServiceMock(true);
|
||||||
|
let service = getCommandLineService(connectionManagementService.object, configurationService.object);
|
||||||
service.processCommandLine().then(() => {
|
service.processCommandLine().then(() => {
|
||||||
connectionManagementService.verifyAll();
|
connectionManagementService.verifyAll();
|
||||||
done();
|
done();
|
||||||
}, error => { assert.fail(error, null, 'processCommandLine rejected ' + error); done(); });
|
}, error => { assert.fail(error, null, 'processCommandLine rejected ' + error); done(); });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('processCommandLine does nothing if no server name and command name is provided and the configuration \'workbench.showConnectDialogOnStartup\' is set to false, even if registered servers exist', done => {
|
||||||
|
const connectionManagementService: TypeMoq.Mock<IConnectionManagementService>
|
||||||
|
= TypeMoq.Mock.ofType<IConnectionManagementService>(TestConnectionManagementService, TypeMoq.MockBehavior.Strict);
|
||||||
|
|
||||||
|
connectionManagementService.setup((c) => c.showConnectionDialog()).verifiable(TypeMoq.Times.never());
|
||||||
|
connectionManagementService.setup(c => c.hasRegisteredServers()).returns(() => false);
|
||||||
|
connectionManagementService.setup(c => c.connectIfNotConnected(TypeMoq.It.isAny(), TypeMoq.It.isAny()))
|
||||||
|
.verifiable(TypeMoq.Times.never());
|
||||||
|
const configurationService = getConfigurationServiceMock(false);
|
||||||
|
let service = getCommandLineService(connectionManagementService.object, configurationService.object);
|
||||||
|
|
||||||
|
service.processCommandLine();
|
||||||
|
connectionManagementService.verifyAll();
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
test('processCommandLine does nothing if registered servers exist and no server name is provided', done => {
|
test('processCommandLine does nothing if registered servers exist and no server name is provided', done => {
|
||||||
const connectionManagementService: TypeMoq.Mock<IConnectionManagementService>
|
const connectionManagementService: TypeMoq.Mock<IConnectionManagementService>
|
||||||
= TypeMoq.Mock.ofType<IConnectionManagementService>(TestConnectionManagementService, TypeMoq.MockBehavior.Strict);
|
= TypeMoq.Mock.ofType<IConnectionManagementService>(TestConnectionManagementService, TypeMoq.MockBehavior.Strict);
|
||||||
@@ -156,7 +182,8 @@ suite('commandLineService tests', () => {
|
|||||||
connectionManagementService.setup(c => c.connectIfNotConnected(TypeMoq.It.isAny(), TypeMoq.It.isAny()))
|
connectionManagementService.setup(c => c.connectIfNotConnected(TypeMoq.It.isAny(), TypeMoq.It.isAny()))
|
||||||
.returns(() => new Promise<string>((resolve, reject) => { resolve('unused'); }))
|
.returns(() => new Promise<string>((resolve, reject) => { resolve('unused'); }))
|
||||||
.verifiable(TypeMoq.Times.never());
|
.verifiable(TypeMoq.Times.never());
|
||||||
let service = getCommandLineService(connectionManagementService.object);
|
const configurationService = getConfigurationServiceMock(true);
|
||||||
|
let service = getCommandLineService(connectionManagementService.object, configurationService.object);
|
||||||
service.processCommandLine().then(() => {
|
service.processCommandLine().then(() => {
|
||||||
connectionManagementService.verifyAll();
|
connectionManagementService.verifyAll();
|
||||||
done();
|
done();
|
||||||
@@ -177,7 +204,8 @@ suite('commandLineService tests', () => {
|
|||||||
connectionManagementService.setup(c => c.connectIfNotConnected(TypeMoq.It.isAny(), 'connection', true))
|
connectionManagementService.setup(c => c.connectIfNotConnected(TypeMoq.It.isAny(), 'connection', true))
|
||||||
.returns(() => new Promise<string>((resolve, reject) => { resolve('unused'); }))
|
.returns(() => new Promise<string>((resolve, reject) => { resolve('unused'); }))
|
||||||
.verifiable(TypeMoq.Times.once());
|
.verifiable(TypeMoq.Times.once());
|
||||||
let service = getCommandLineService(connectionManagementService.object, environmentService.object, capabilitiesService);
|
const configurationService = getConfigurationServiceMock(true);
|
||||||
|
let service = getCommandLineService(connectionManagementService.object, configurationService.object, environmentService.object, capabilitiesService);
|
||||||
service.processCommandLine().then(() => {
|
service.processCommandLine().then(() => {
|
||||||
environmentService.verifyAll();
|
environmentService.verifyAll();
|
||||||
connectionManagementService.verifyAll();
|
connectionManagementService.verifyAll();
|
||||||
@@ -201,7 +229,8 @@ suite('commandLineService tests', () => {
|
|||||||
commandService.setup(c => c.executeCommand('mycommand'))
|
commandService.setup(c => c.executeCommand('mycommand'))
|
||||||
.returns(() => TPromise.wrap(1))
|
.returns(() => TPromise.wrap(1))
|
||||||
.verifiable(TypeMoq.Times.once());
|
.verifiable(TypeMoq.Times.once());
|
||||||
let service = getCommandLineService(connectionManagementService.object, environmentService.object, capabilitiesService, commandService.object);
|
const configurationService = getConfigurationServiceMock(true);
|
||||||
|
let service = getCommandLineService(connectionManagementService.object, configurationService.object, environmentService.object, capabilitiesService, commandService.object);
|
||||||
service.processCommandLine().then(() => {
|
service.processCommandLine().then(() => {
|
||||||
connectionManagementService.verifyAll();
|
connectionManagementService.verifyAll();
|
||||||
commandService.verifyAll();
|
commandService.verifyAll();
|
||||||
@@ -229,7 +258,8 @@ suite('commandLineService tests', () => {
|
|||||||
commandService.setup(c => c.executeCommand('mycommand', TypeMoq.It.is<ConnectionProfile>(p => p.serverName === 'myserver')))
|
commandService.setup(c => c.executeCommand('mycommand', TypeMoq.It.is<ConnectionProfile>(p => p.serverName === 'myserver')))
|
||||||
.returns(() => TPromise.wrap(1))
|
.returns(() => TPromise.wrap(1))
|
||||||
.verifiable(TypeMoq.Times.once());
|
.verifiable(TypeMoq.Times.once());
|
||||||
let service = getCommandLineService(connectionManagementService.object, environmentService.object, capabilitiesService, commandService.object);
|
const configurationService = getConfigurationServiceMock(true);
|
||||||
|
let service = getCommandLineService(connectionManagementService.object, configurationService.object, environmentService.object, capabilitiesService, commandService.object);
|
||||||
service.processCommandLine().then(() => {
|
service.processCommandLine().then(() => {
|
||||||
connectionManagementService.verifyAll();
|
connectionManagementService.verifyAll();
|
||||||
commandService.verifyAll();
|
commandService.verifyAll();
|
||||||
@@ -250,7 +280,8 @@ suite('commandLineService tests', () => {
|
|||||||
commandService.setup(c => c.executeCommand('mycommand'))
|
commandService.setup(c => c.executeCommand('mycommand'))
|
||||||
.returns(() => TPromise.wrapError(new Error('myerror')))
|
.returns(() => TPromise.wrapError(new Error('myerror')))
|
||||||
.verifiable(TypeMoq.Times.once());
|
.verifiable(TypeMoq.Times.once());
|
||||||
let service = getCommandLineService(connectionManagementService.object, environmentService.object, capabilitiesService, commandService.object);
|
const configurationService = getConfigurationServiceMock(true);
|
||||||
|
let service = getCommandLineService(connectionManagementService.object, configurationService.object, environmentService.object, capabilitiesService, commandService.object);
|
||||||
service.processCommandLine().then(() => {
|
service.processCommandLine().then(() => {
|
||||||
assert.fail(1, null, 'processCommandLine should reject when executeCommand errors out');
|
assert.fail(1, null, 'processCommandLine should reject when executeCommand errors out');
|
||||||
done();
|
done();
|
||||||
|
|||||||
@@ -151,6 +151,9 @@ export class Button extends Disposable {
|
|||||||
this.$el.addClass('monaco-text-button');
|
this.$el.addClass('monaco-text-button');
|
||||||
}
|
}
|
||||||
this.$el.text(value);
|
this.$el.text(value);
|
||||||
|
//{{SQL CARBON EDIT}}
|
||||||
|
this.$el.attr('aria-label', value);
|
||||||
|
//{{END}}
|
||||||
if (this.options.title) {
|
if (this.options.title) {
|
||||||
this.$el.title(value);
|
this.$el.title(value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,8 +62,15 @@ export class Application {
|
|||||||
|
|
||||||
async start(): Promise<any> {
|
async start(): Promise<any> {
|
||||||
await this._start();
|
await this._start();
|
||||||
|
//{{SQL CARBON EDIT}}
|
||||||
|
await this.code.waitForElement('.object-explorer-view');
|
||||||
|
|
||||||
|
//Original
|
||||||
|
/*
|
||||||
await this.code.waitForElement('.explorer-folders-view');
|
await this.code.waitForElement('.explorer-folders-view');
|
||||||
await this.code.waitForActiveElement(`.editor-instance[id="workbench.editor.walkThroughPart"] > div > div[tabIndex="0"]`);
|
await this.code.waitForActiveElement(`.editor-instance[id="workbench.editor.walkThroughPart"] > div > div[tabIndex="0"]`);
|
||||||
|
*/
|
||||||
|
//{{END}}
|
||||||
}
|
}
|
||||||
|
|
||||||
async restart(options: { workspaceOrFolder?: string, extraArgs?: string[] }): Promise<any> {
|
async restart(options: { workspaceOrFolder?: string, extraArgs?: string[] }): Promise<any> {
|
||||||
|
|||||||
@@ -20,6 +20,11 @@ import { Editors } from '../editor/editors';
|
|||||||
import { Code } from '../../vscode/code';
|
import { Code } from '../../vscode/code';
|
||||||
import { Terminal } from '../terminal/terminal';
|
import { Terminal } from '../terminal/terminal';
|
||||||
|
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
|
import { ConnectionDialog } from '../../sql/connectionDialog/connectionDialog';
|
||||||
|
import { Profiler } from '../../sql/profiler/profiler';
|
||||||
|
// {{END}}
|
||||||
|
|
||||||
export interface Commands {
|
export interface Commands {
|
||||||
runCommand(command: string): Promise<any>;
|
runCommand(command: string): Promise<any>;
|
||||||
}
|
}
|
||||||
@@ -42,6 +47,11 @@ export class Workbench {
|
|||||||
readonly keybindingsEditor: KeybindingsEditor;
|
readonly keybindingsEditor: KeybindingsEditor;
|
||||||
readonly terminal: Terminal;
|
readonly terminal: Terminal;
|
||||||
|
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
|
readonly connectionDialog: ConnectionDialog;
|
||||||
|
readonly profiler: Profiler;
|
||||||
|
// {{END}}
|
||||||
|
|
||||||
constructor(code: Code, userDataPath: string) {
|
constructor(code: Code, userDataPath: string) {
|
||||||
this.editors = new Editors(code);
|
this.editors = new Editors(code);
|
||||||
this.quickopen = new QuickOpen(code, this.editors);
|
this.quickopen = new QuickOpen(code, this.editors);
|
||||||
@@ -58,6 +68,10 @@ export class Workbench {
|
|||||||
this.settingsEditor = new SettingsEditor(code, userDataPath, this.editors, this.editor, this.quickopen);
|
this.settingsEditor = new SettingsEditor(code, userDataPath, this.editors, this.editor, this.quickopen);
|
||||||
this.keybindingsEditor = new KeybindingsEditor(code);
|
this.keybindingsEditor = new KeybindingsEditor(code);
|
||||||
this.terminal = new Terminal(code);
|
this.terminal = new Terminal(code);
|
||||||
|
// {{SQL CARBON EDIT}}
|
||||||
|
this.connectionDialog = new ConnectionDialog(code);
|
||||||
|
this.profiler = new Profiler(code, this.quickopen);
|
||||||
|
// {{END}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,10 @@ import * as rimraf from 'rimraf';
|
|||||||
import * as mkdirp from 'mkdirp';
|
import * as mkdirp from 'mkdirp';
|
||||||
import { ncp } from 'ncp';
|
import { ncp } from 'ncp';
|
||||||
import { Application, Quality } from './application';
|
import { Application, Quality } from './application';
|
||||||
|
//{{SQL CARBON EDIT}}
|
||||||
|
import { setup as runProfilerTests } from './sql/profiler/profiler.test';
|
||||||
|
//Original
|
||||||
|
/*
|
||||||
import { setup as setupDataMigrationTests } from './areas/workbench/data-migration.test';
|
import { setup as setupDataMigrationTests } from './areas/workbench/data-migration.test';
|
||||||
import { setup as setupDataLossTests } from './areas/workbench/data-loss.test';
|
import { setup as setupDataLossTests } from './areas/workbench/data-loss.test';
|
||||||
import { setup as setupDataExplorerTests } from './areas/explorer/explorer.test';
|
import { setup as setupDataExplorerTests } from './areas/explorer/explorer.test';
|
||||||
@@ -27,6 +30,8 @@ import { setup as setupDataExtensionTests } from './areas/extensions/extensions.
|
|||||||
import { setup as setupTerminalTests } from './areas/terminal/terminal.test';
|
import { setup as setupTerminalTests } from './areas/terminal/terminal.test';
|
||||||
import { setup as setupDataMultirootTests } from './areas/multiroot/multiroot.test';
|
import { setup as setupDataMultirootTests } from './areas/multiroot/multiroot.test';
|
||||||
import { setup as setupDataLocalizationTests } from './areas/workbench/localization.test';
|
import { setup as setupDataLocalizationTests } from './areas/workbench/localization.test';
|
||||||
|
*/
|
||||||
|
//{{END}}
|
||||||
import { MultiLogger, Logger, ConsoleLogger, FileLogger } from './logger';
|
import { MultiLogger, Logger, ConsoleLogger, FileLogger } from './logger';
|
||||||
|
|
||||||
const tmpDir = tmp.dirSync({ prefix: 't' }) as { name: string; removeCallback: Function; };
|
const tmpDir = tmp.dirSync({ prefix: 't' }) as { name: string; removeCallback: Function; };
|
||||||
@@ -250,14 +255,32 @@ after(async function () {
|
|||||||
await new Promise((c, e) => rimraf(testDataPath, { maxBusyTries: 10 }, err => err ? e(err) : c()));
|
await new Promise((c, e) => rimraf(testDataPath, { maxBusyTries: 10 }, err => err ? e(err) : c()));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//{{SQL CARBON EDIT}}
|
||||||
|
/*
|
||||||
describe('Data Migration', () => {
|
describe('Data Migration', () => {
|
||||||
setupDataMigrationTests(userDataDir, createApp);
|
setupDataMigrationTests(userDataDir, createApp);
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
//{{END}}
|
||||||
|
|
||||||
describe('Test', () => {
|
describe('Smoke Test', () => {
|
||||||
before(async function () {
|
before(async function () {
|
||||||
const app = createApp(quality);
|
const app = createApp(quality);
|
||||||
await app!.start();
|
await app!.start();
|
||||||
|
//{{SQL CARBON EDIT}}
|
||||||
|
const testExtLoadedText = 'Test Extension Loaded';
|
||||||
|
const testSetupCompletedText = 'Test Setup Completed';
|
||||||
|
const allExtensionsLoadedText = 'All Extensions Loaded';
|
||||||
|
const setupTestCommand = 'Test: Setup Integration Test';
|
||||||
|
const waitForExtensionsCommand = 'Test: Wait For Extensions To Load';
|
||||||
|
await app.workbench.statusbar.waitForStatusbarText(testExtLoadedText, testExtLoadedText);
|
||||||
|
await app.workbench.quickopen.runCommand(setupTestCommand);
|
||||||
|
await app.workbench.statusbar.waitForStatusbarText(testSetupCompletedText, testSetupCompletedText);
|
||||||
|
await app!.reload();
|
||||||
|
await app.workbench.statusbar.waitForStatusbarText(testExtLoadedText, testExtLoadedText);
|
||||||
|
await app.workbench.quickopen.runCommand(waitForExtensionsCommand);
|
||||||
|
await app.workbench.statusbar.waitForStatusbarText(allExtensionsLoadedText, allExtensionsLoadedText);
|
||||||
|
//{{END}}
|
||||||
this.app = app;
|
this.app = app;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -295,6 +318,10 @@ describe('Test', () => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//{{SQL CARBON EDIT}}
|
||||||
|
runProfilerTests();
|
||||||
|
//Original
|
||||||
|
/*
|
||||||
setupDataLossTests();
|
setupDataLossTests();
|
||||||
setupDataExplorerTests();
|
setupDataExplorerTests();
|
||||||
setupDataPreferencesTests();
|
setupDataPreferencesTests();
|
||||||
@@ -308,4 +335,6 @@ describe('Test', () => {
|
|||||||
setupTerminalTests();
|
setupTerminalTests();
|
||||||
setupDataMultirootTests();
|
setupDataMultirootTests();
|
||||||
setupDataLocalizationTests();
|
setupDataLocalizationTests();
|
||||||
|
*/
|
||||||
|
//{{END}}
|
||||||
});
|
});
|
||||||
|
|||||||
51
test/smoke/src/sql/connectionDialog/connectionDialog.ts
Normal file
51
test/smoke/src/sql/connectionDialog/connectionDialog.ts
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { Code } from '../../vscode/code';
|
||||||
|
import { waitForNewDialog, clickDialogButton } from '../sqlutils';
|
||||||
|
import { TestServerProfile, AuthenticationType } from '../testConfig';
|
||||||
|
|
||||||
|
const CONNECTION_DIALOG_TITLE = 'Connection';
|
||||||
|
const CONNECTION_DIALOG_SELECTOR: string = '.modal-dialog .modal-content .modal-body .connection-dialog';
|
||||||
|
const CONNECTION_DETAIL_CONTROL_SELECTOR: string = '.connection-type .connection-table .connection-input';
|
||||||
|
|
||||||
|
const SERVER_INPUT_ARIA_LABEL = 'Server';
|
||||||
|
const USERNAME_INPUT_ARIA_LABEL = 'User name';
|
||||||
|
const PASSWORD_INPUT_ARIA_LABEL = 'Password';
|
||||||
|
const AUTH_TYPE_ARIA_LABEL = 'Authentication type';
|
||||||
|
|
||||||
|
const CONNECT_BUTTON_ARIA_LABEL = 'Connect';
|
||||||
|
|
||||||
|
export class ConnectionDialog {
|
||||||
|
|
||||||
|
constructor(private code: Code) { }
|
||||||
|
|
||||||
|
async waitForConnectionDialog(): Promise<void> {
|
||||||
|
await waitForNewDialog(this.code, CONNECTION_DIALOG_TITLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
async connect(profile: TestServerProfile): Promise<void> {
|
||||||
|
await this.code.waitForSetValue(this.getInputCssSelector(SERVER_INPUT_ARIA_LABEL), profile.serverName);
|
||||||
|
if (profile.authenticationType === AuthenticationType.SqlLogin) {
|
||||||
|
await this.code.waitAndClick(this.getSelectCssSelector(AUTH_TYPE_ARIA_LABEL));
|
||||||
|
await this.selectAuthType(profile.authenticationTypeDisplayName);
|
||||||
|
await this.code.waitForSetValue(this.getInputCssSelector(USERNAME_INPUT_ARIA_LABEL), profile.userName);
|
||||||
|
await this.code.waitForSetValue(this.getInputCssSelector(PASSWORD_INPUT_ARIA_LABEL), profile.password);
|
||||||
|
}
|
||||||
|
await clickDialogButton(this.code, CONNECT_BUTTON_ARIA_LABEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
private getInputCssSelector(ariaLabel: string): string {
|
||||||
|
return `${CONNECTION_DIALOG_SELECTOR} ${CONNECTION_DETAIL_CONTROL_SELECTOR} .monaco-inputbox input[aria-label="${ariaLabel}"]`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getSelectCssSelector(ariaLabel: string): string {
|
||||||
|
return `${CONNECTION_DIALOG_SELECTOR} ${CONNECTION_DETAIL_CONTROL_SELECTOR} select[aria-label="${ariaLabel}"]`;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async selectAuthType(authType: string) {
|
||||||
|
await this.code.waitAndClick(`.context-view.bottom.left .monaco-select-box-dropdown-container .select-box-dropdown-list-container .monaco-list .monaco-scrollable-element .monaco-list-rows div[aria-label="${authType}"][class*="monaco-list-row"]`);
|
||||||
|
}
|
||||||
|
}
|
||||||
19
test/smoke/src/sql/profiler/profiler.test.ts
Normal file
19
test/smoke/src/sql/profiler/profiler.test.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { Application } from '../../application';
|
||||||
|
import { getDefaultTestingServer } from '../testConfig';
|
||||||
|
|
||||||
|
export function setup() {
|
||||||
|
describe('profiler test suite', () => {
|
||||||
|
it('Launch profiler test', async function () {
|
||||||
|
const app = this.app as Application;
|
||||||
|
await app.workbench.profiler.launchProfiler();
|
||||||
|
await app.workbench.connectionDialog.waitForConnectionDialog();
|
||||||
|
await app.workbench.connectionDialog.connect(await getDefaultTestingServer());
|
||||||
|
await app.workbench.profiler.waitForNewSessionDialogAndStart();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
28
test/smoke/src/sql/profiler/profiler.ts
Normal file
28
test/smoke/src/sql/profiler/profiler.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { Code } from '../../vscode/code';
|
||||||
|
import { QuickOpen } from '../../areas/quickopen/quickopen';
|
||||||
|
import { waitForNewDialog, clickDialogButton } from '../sqlutils';
|
||||||
|
|
||||||
|
const NEW_SESSION_DIALOG_TITLE: string = 'Start New Profiler Session';
|
||||||
|
|
||||||
|
export class Profiler {
|
||||||
|
|
||||||
|
constructor(private code: Code, private quickopen: QuickOpen) { }
|
||||||
|
|
||||||
|
async launchProfiler(): Promise<void> {
|
||||||
|
await this.quickopen.runCommand('Profiler: Launch Profiler');
|
||||||
|
}
|
||||||
|
|
||||||
|
async waitForNewSessionDialog() {
|
||||||
|
await waitForNewDialog(this.code, NEW_SESSION_DIALOG_TITLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
async waitForNewSessionDialogAndStart() {
|
||||||
|
await this.waitForNewSessionDialog();
|
||||||
|
await clickDialogButton(this.code, 'Start');
|
||||||
|
}
|
||||||
|
}
|
||||||
9
test/smoke/src/sql/sqlutils.ts
Normal file
9
test/smoke/src/sql/sqlutils.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import { Code } from '../vscode/code';
|
||||||
|
|
||||||
|
export async function waitForNewDialog(code: Code, title: string) {
|
||||||
|
await code.waitForElement(`div[aria-label="${title}"][class="modal fade flyout-dialog"]`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function clickDialogButton(code: Code, title: string) {
|
||||||
|
await code.waitAndClick(`.modal-dialog .modal-content .modal-footer .right-footer .footer-button a[aria-label="${title}"][aria-disabled="false"]`);
|
||||||
|
}
|
||||||
92
test/smoke/src/sql/testConfig.ts
Normal file
92
test/smoke/src/sql/testConfig.ts
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO: Due to a runtime error, I duplicated this file at these 2 locations:
|
||||||
|
$/extensions/integration-test/src/testConfig.ts
|
||||||
|
$/test/smoke/src/sql/testConfig.ts
|
||||||
|
for now, make sure to keep both files in sync.
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface ITestServerProfile {
|
||||||
|
serverName: string;
|
||||||
|
userName: string;
|
||||||
|
password: string;
|
||||||
|
authenticationType: AuthenticationType;
|
||||||
|
database: string;
|
||||||
|
provider: ConnectionProvider;
|
||||||
|
version: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface INameDisplayNamePair {
|
||||||
|
name: string;
|
||||||
|
displayName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum AuthenticationType {
|
||||||
|
Windows,
|
||||||
|
SqlLogin
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ConnectionProvider {
|
||||||
|
SQLServer
|
||||||
|
}
|
||||||
|
|
||||||
|
var connectionProviderMapping = {};
|
||||||
|
var authenticationTypeMapping = {};
|
||||||
|
connectionProviderMapping[ConnectionProvider.SQLServer] = { name: 'MSSQL', displayName: 'Microsoft SQL Server' };
|
||||||
|
|
||||||
|
authenticationTypeMapping[AuthenticationType.SqlLogin] = { name: 'SqlLogin', displayName: 'SQL Login' };
|
||||||
|
authenticationTypeMapping[AuthenticationType.Windows] = { name: 'Integrated', displayName: 'Windows Authentication' };
|
||||||
|
|
||||||
|
export class TestServerProfile {
|
||||||
|
constructor(private _profile: ITestServerProfile) { }
|
||||||
|
public get serverName(): string { return this._profile.serverName; }
|
||||||
|
public get userName(): string { return this._profile.userName; }
|
||||||
|
public get password(): string { return this._profile.password; }
|
||||||
|
public get database(): string { return this._profile.database; }
|
||||||
|
public get version(): string { return this._profile.version; }
|
||||||
|
public get provider(): ConnectionProvider { return this._profile.provider; }
|
||||||
|
public get providerName(): string { return getEnumMappingEntry(connectionProviderMapping, this.provider).name; }
|
||||||
|
public get providerDisplayName(): string { return getEnumMappingEntry(connectionProviderMapping, this.provider).displayName; }
|
||||||
|
public get authenticationType(): AuthenticationType { return this._profile.authenticationType; }
|
||||||
|
public get authenticationTypeName(): string { return getEnumMappingEntry(authenticationTypeMapping, this.authenticationType).name; }
|
||||||
|
public get authenticationTypeDisplayName(): string { return getEnumMappingEntry(authenticationTypeMapping, this.authenticationType).displayName; }
|
||||||
|
}
|
||||||
|
|
||||||
|
var TestingServers: TestServerProfile[] = [
|
||||||
|
new TestServerProfile(
|
||||||
|
{
|
||||||
|
serverName: 'SQLTOOLS2017-3',
|
||||||
|
userName: '',
|
||||||
|
password: '',
|
||||||
|
authenticationType: AuthenticationType.Windows,
|
||||||
|
database: 'master',
|
||||||
|
provider: ConnectionProvider.SQLServer,
|
||||||
|
version: '2017'
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
function getEnumMappingEntry(mapping: any, enumValue: any): INameDisplayNamePair {
|
||||||
|
let entry = mapping[enumValue];
|
||||||
|
if (entry) {
|
||||||
|
return entry;
|
||||||
|
} else {
|
||||||
|
throw `Unknown enum type: ${enumValue.toString()}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getDefaultTestingServer(): Promise<TestServerProfile> {
|
||||||
|
let servers = await getTestingServers();
|
||||||
|
return servers[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getTestingServers(): Promise<TestServerProfile[]> {
|
||||||
|
let promise = new Promise<TestServerProfile[]>(resolve => {
|
||||||
|
resolve(TestingServers);
|
||||||
|
});
|
||||||
|
await promise;
|
||||||
|
return promise;
|
||||||
|
}
|
||||||
@@ -217,7 +217,9 @@ export class Code {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async waitForWindowIds(fn: (windowIds: number[]) => boolean): Promise<void> {
|
async waitForWindowIds(fn: (windowIds: number[]) => boolean): Promise<void> {
|
||||||
await poll(() => this.driver.getWindowIds(), fn, `get window ids`);
|
// {{SQL CARBON EDIT}}
|
||||||
|
await poll(() => this.driver.getWindowIds(), fn, `get window ids`, 600, 100);
|
||||||
|
// {{END}}
|
||||||
}
|
}
|
||||||
|
|
||||||
async dispatchKeybinding(keybinding: string): Promise<void> {
|
async dispatchKeybinding(keybinding: string): Promise<void> {
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ const opts = minimist(args, {
|
|||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
useColors: true,
|
useColors: true,
|
||||||
timeout: 60000,
|
//{{SQL CARBON EDIT}}
|
||||||
|
timeout: 60000 * 2,
|
||||||
|
//{{END}}
|
||||||
slow: 30000,
|
slow: 30000,
|
||||||
grep: opts['f']
|
grep: opts['f']
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user