Reenable disabled tests post VSCode refresh (#20899)

* Reenable disabled tests

* Extension unit test updates

* Turn off data workspace tests on Linux

* Keep integration and smoke tests disabled
This commit is contained in:
Karl Burtram
2022-10-21 21:40:52 -07:00
committed by GitHub
parent 3e1f2b0d9d
commit 5a7ae8a3d0
12 changed files with 342 additions and 95 deletions

View File

@@ -0,0 +1,13 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'mocha';
import * as vscode from 'vscode';
describe('Extension activate test', () => {
it('Extension should activate correctly', async function (): Promise<void> {
await vscode.extensions.getExtension('Microsoft.admin-tool-ext-win')!.activate();
});
});

View File

@@ -162,7 +162,7 @@ suite('WorkspaceService', function (): void {
}
]);
sinon.stub(ProjectProviderRegistry, 'providers').value([provider1, provider2]);
// const consoleErrorStub = sinon.stub(console, 'error');
const consoleErrorStub = sinon.stub(console, 'error');
const projectTypes = await service.getAllProjectTypes();
should.strictEqual(projectTypes.length, 3);
should.strictEqual(projectTypes[0].projectFileExtension, 'testproj');
@@ -175,9 +175,7 @@ suite('WorkspaceService', function (): void {
should.strictEqual(extension5.activationStub.called, true, 'extension5.activate() should have been called');
should.strictEqual(extension6.activationStub.notCalled, true, 'extension6.activate() should not have been called');
should.strictEqual(extension7.activationStub.notCalled, true, 'extension7.activate() should not have been called');
// {{SQL CARBON TODO}} - disable this assertion
// should.strictEqual(consoleErrorStub.calledOnce, true, 'Logger.error should be called once');
should.strictEqual(consoleErrorStub.calledOnce, true, 'Logger.error should be called once');
});
test('getProjectProvider', async () => {

View File

@@ -22,7 +22,7 @@ describe('DataItemCache', function (): void {
});
it('Should be initialized empty', function (): void {
should(dataItemCache).not.have.property('cachedItem').and.be.undefined();
should(dataItemCache).property('cachedItem').be.undefined();
});
it('Should be initialized as expired', function (): void {
@@ -52,7 +52,7 @@ describe('DataItemCache', function (): void {
await dataItemCache.getData();
await dataItemCache.getData();
fetchFunctionMock.verify(fx => fx() ,TypeMoq.Times.once());
fetchFunctionMock.verify(fx => fx(), TypeMoq.Times.once());
});
it('Should call fetch function twice for consecutive getValue() calls if TTL expires in between', async function (): Promise<void> {

View File

@@ -0,0 +1,233 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import * as vscode from 'vscode';
import * as should from 'should';
import 'mocha';
import * as sinon from 'sinon';
import * as azdataTest from '@microsoft/azdata-test';
import { QueryHistoryProvider } from '../queryHistoryProvider';
import { QueryHistoryItem } from '../queryHistoryItem';
describe('QueryHistoryProvider', () => {
let testProvider: QueryHistoryProvider;
let testListener: azdata.queryeditor.QueryEventListener;
let textDocumentSandbox: sinon.SinonSandbox;
const testUri = vscode.Uri.parse('untitled://query1');
beforeEach(async function (): Promise<void> {
sinon.stub(azdata.queryeditor, 'registerQueryEventListener').callsFake((listener: azdata.queryeditor.QueryEventListener) => {
testListener = listener;
return { dispose: (): void => { } };
});
textDocumentSandbox = sinon.createSandbox();
textDocumentSandbox.replaceGetter(vscode.workspace, 'textDocuments', () => [azdataTest.mocks.vscode.createTextDocumentMock(testUri).object]);
const getConnectionStub = sinon.stub(azdata.connection, 'getConnection');
getConnectionStub.resolves(<any>{});
const contextMock = azdataTest.mocks.vscode.createExtensionContextMock();
testProvider = new QueryHistoryProvider(contextMock.object, contextMock.object.globalStorageUri);
// Disable persistence during tests
await testProvider.setPersistenceEnabled(false);
});
afterEach(function (): void {
sinon.restore();
});
it('There should be no children initially', async function () {
const children = await testProvider.getChildren();
should(children).length(0);
});
it('Clearing empty list does not throw', async function () {
await testProvider.clearAll();
const children = await testProvider.getChildren();
should(children).length(0);
});
it('non-queryStop events don\'t cause children to be added', async function () {
const types: azdata.queryeditor.QueryEventType[] = ['executionPlan', 'queryStart', 'queryUpdate', 'visualize'];
for (const type of types) {
await fireQueryEventAndWaitForRefresh(type, <any>{ uri: testUri.toString() }, { messages: [], batchRanges: [] }, 2000);
const children = await testProvider.getChildren();
should(children).length(0, `Should have no children after ${type} event`);
}
});
it('queryStop events cause children to be added', async function () {
setupTextEditorMock('SELECT 1');
await fireQueryStartAndStopAndWaitForRefresh(testUri);
const children = await testProvider.getChildren();
should(children).length(1, 'Should have one child after adding item');
await fireQueryStartAndStopAndWaitForRefresh(testUri);
should(children).length(2, 'Should have two children after adding another item');
});
it('no selection records entire text', async function () {
const content = 'SELECT 1\nSELECT 2';
setupTextEditorMock(content);
await fireQueryStartAndStopAndWaitForRefresh(testUri);
const children = await testProvider.getChildren();
should(children).length(1, 'Should have one child after adding item');
should(children[0].queryText).be.equal(content, 'item content should be full text content');
});
it('active selection records only selected text', async function () {
const rangeWithContent1: azdataTest.mocks.vscode.RangeWithContent = { range: new vscode.Range(new vscode.Position(0, 0), new vscode.Position(2, 0)), content: 'SELECT 1' };
const rangeWithContent2: azdataTest.mocks.vscode.RangeWithContent = { range: new vscode.Range(new vscode.Position(3, 0), new vscode.Position(3, 5)), content: 'SELECT 2' };
setupTextEditorMock([rangeWithContent1, rangeWithContent2], [new vscode.Selection(rangeWithContent1.range.start, rangeWithContent1.range.end)]);
await fireQueryStartAndStopAndWaitForRefresh(testUri);
const children = await testProvider.getChildren();
should(children).length(1, 'Should have one child after adding item');
should(children[0].queryText).be.equal(rangeWithContent1.content, 'item content should be only active selection');
});
it('event with errors is marked as error', async function () {
setupTextEditorMock('SELECT 1');
const message1: azdata.queryeditor.QueryMessage = { message: 'Message 1', isError: false };
const message2: azdata.queryeditor.QueryMessage = { message: 'Error message', isError: true };
const message3: azdata.queryeditor.QueryMessage = { message: 'Message 2', isError: false };
await fireQueryStartAndStopAndWaitForRefresh(testUri, { messages: [message1, message2, message3], batchRanges: [] });
const children = await testProvider.getChildren();
should(children).length(1, 'Should have one child after adding item');
should(children[0].isSuccess).be.false('Event with errors should have error icon');
});
it('event without errors is marked as success', async function () {
setupTextEditorMock('SELECT 1');
const message1: azdata.queryeditor.QueryMessage = { message: 'Message 1', isError: false };
const message2: azdata.queryeditor.QueryMessage = { message: 'Message 2', isError: false };
const message3: azdata.queryeditor.QueryMessage = { message: 'Message 3', isError: false };
await fireQueryStartAndStopAndWaitForRefresh(testUri, { messages: [message1, message2, message3], batchRanges: [] });
const children = await testProvider.getChildren();
should(children).length(1, 'Should have one child after adding item');
should(children[0].isSuccess).be.true('Event without errors should have check icon');
});
it('queryStop events from unknown document are ignored', async function () {
const unknownUri = vscode.Uri.parse('untitled://query2');
const queryDocumentMock = azdataTest.mocks.azdata.queryeditor.createQueryDocumentMock(unknownUri.toString());
// Since we didn't find the text document we'll never update the item list so add a timeout since that event will never fire
await fireQueryEventAndWaitForRefresh('queryStop', queryDocumentMock.object, { messages: [], batchRanges: [] }, 2000);
const children = await testProvider.getChildren();
should(children).length(0, 'Should not have any children');
});
it('can clear all with one child', async function () {
await fireQueryStartAndStopAndWaitForRefresh(testUri);
let children = await testProvider.getChildren();
should(children).length(1, 'Should have one child after adding item');
await waitForItemRefresh(() => testProvider.clearAll());
children = await testProvider.getChildren();
should(children).length(0, 'Should have no children after clearing');
});
it('can clear all with multiple children', async function () {
await fireQueryStartAndStopAndWaitForRefresh(testUri);
await fireQueryStartAndStopAndWaitForRefresh(testUri);
await fireQueryStartAndStopAndWaitForRefresh(testUri);
let children = await testProvider.getChildren();
should(children).length(3, 'Should have 3 children after adding item');
await waitForItemRefresh(() => testProvider.clearAll());
children = await testProvider.getChildren();
should(children).length(0, 'Should have no children after clearing');
});
it('delete item when no items doesn\'t throw', async function () {
const testItem: QueryHistoryItem = { queryText: 'SELECT 1', connectionProfile: azdataTest.stubs.azdata.createConnectionProfile(), timestamp: new Date().toLocaleString(), isSuccess: true };
await waitForItemRefresh(() => testProvider.deleteItem(testItem));
const children = await testProvider.getChildren();
should(children).length(0, 'Should have no children after deleting item');
});
it('delete item that doesn\'t exist doesn\'t throw', async function () {
await fireQueryStartAndStopAndWaitForRefresh(testUri);
let children = await testProvider.getChildren();
should(children).length(1, 'Should have 1 child initially');
const testItem: QueryHistoryItem = { queryText: 'SELECT 1', connectionProfile: azdataTest.stubs.azdata.createConnectionProfile(), timestamp: new Date().toLocaleString(), isSuccess: true };
await waitForItemRefresh(() => testProvider.deleteItem(testItem));
children = await testProvider.getChildren();
should(children).length(1, 'Should still have 1 child after deleting item');
});
it('can delete single item', async function () {
await fireQueryStartAndStopAndWaitForRefresh(testUri);
await fireQueryStartAndStopAndWaitForRefresh(testUri);
await fireQueryStartAndStopAndWaitForRefresh(testUri);
const firstChildren = await testProvider.getChildren();
should(firstChildren).length(3, 'Should have 3 children initially');
let itemToDelete: QueryHistoryItem = firstChildren[1];
await waitForItemRefresh(() => testProvider.deleteItem(itemToDelete));
const secondChildren = await testProvider.getChildren();
should(secondChildren).length(2, 'Should still have 2 child after deleting item');
should(secondChildren[0]).be.equal(firstChildren[0], 'First item should still exist after deleting first item');
should(secondChildren[1]).be.equal(firstChildren[2], 'Second item should still exist after deleting first item');
itemToDelete = secondChildren[0];
await waitForItemRefresh(() => testProvider.deleteItem(itemToDelete));
const thirdChildren = await testProvider.getChildren();
should(thirdChildren).length(1, 'Should still have 1 child after deleting item');
should(thirdChildren[0]).be.equal(secondChildren[1], 'Second item should still exist after deleting second item');
itemToDelete = thirdChildren[0];
await waitForItemRefresh(() => testProvider.deleteItem(itemToDelete));
const fourthChildren = await testProvider.getChildren();
should(fourthChildren).length(0, 'Should have no children after deleting all items');
});
it('pausing capture causes children not to be added', async function () {
await fireQueryStartAndStopAndWaitForRefresh(testUri);
const children = await testProvider.getChildren();
should(children).length(1, 'Should have one child after adding initial item');
await testProvider.setCaptureEnabled(false);
// Add timeout since the item is never added, thus never triggering the event
await fireQueryStartAndStopAndWaitForRefresh(testUri, { messages: [], batchRanges: [] }, 2000);
should(children).length(1, 'Should still have 1 child after adding item when capture paused');
await testProvider.setCaptureEnabled(true);
await fireQueryStartAndStopAndWaitForRefresh(testUri);
should(children).length(2, 'Should have 2 child after adding item when capture was resumed');
});
function setupTextEditorMock(content: string | azdataTest.mocks.vscode.RangeWithContent[], selections?: vscode.Selection[] | undefined): void {
const textDocumentMock = azdataTest.mocks.vscode.createTextDocumentMock(testUri, content);
const textEditorMock = azdataTest.mocks.vscode.createTextEditorMock(textDocumentMock.object, selections);
textDocumentSandbox.replaceGetter(vscode.window, 'activeTextEditor', () => textEditorMock.object);
}
async function fireQueryStartAndStopAndWaitForRefresh(uri: vscode.Uri, queryInfo: azdata.queryeditor.QueryInfo = { messages: [], batchRanges: [] }, timeoutMs?: number): Promise<void> {
const queryDocumentMock = azdataTest.mocks.azdata.queryeditor.createQueryDocumentMock(uri.toString());
// First queryStart message to record text. QueryInfo is always empty for this.
testListener.onQueryEvent('queryStart', queryDocumentMock.object, undefined, { messages: [], batchRanges: [] });
// Fire queryStop message to trigger creation of the history node
await fireQueryEventAndWaitForRefresh('queryStop', queryDocumentMock.object, queryInfo, timeoutMs);
}
async function fireQueryEventAndWaitForRefresh(type: azdata.queryeditor.QueryEventType, document: azdata.queryeditor.QueryDocument, queryInfo: azdata.queryeditor.QueryInfo, timeoutMs?: number): Promise<void> {
await waitForItemRefresh(async () => testListener.onQueryEvent(type, document, undefined, queryInfo), timeoutMs);
}
async function waitForItemRefresh(func: () => Promise<void>, timeoutMs?: number): Promise<void> {
const promises: Promise<any>[] = [azdataTest.helpers.eventToPromise(testProvider.onDidChangeTreeData)];
const timeoutPromise = timeoutMs ? new Promise<void>(r => setTimeout(() => r(), timeoutMs)) : undefined;
if (timeoutPromise) {
promises.push(timeoutPromise);
}
await func();
await Promise.race(promises);
}
});

View File

@@ -18,6 +18,7 @@ import { createTestCredentials, createTestUtils, TestUtils } from '../testUtils'
const rootFolderPath = 'test';
const localSettingsPath: string = path.join(rootFolderPath, 'local.settings.json');
const tempFolderPath = path.sep + 'temp' + path.sep;
let testUtils: TestUtils;
describe('AzureFunctionUtils', function (): void {
@@ -234,12 +235,15 @@ describe('AzureFunctionUtils', function (): void {
});
describe('Get Azure Function Project', function (): void {
it('Should return undefined if no azure function projects are found', async () => {
// set workspace folder for testing
sinon.replaceGetter(vscode.workspace, 'workspaceFolders', () => {
return <vscode.WorkspaceFolder[]>[{
uri: {
fsPath: '/temp/'
fsPath: tempFolderPath
},
}];
});
@@ -255,17 +259,18 @@ describe('AzureFunctionUtils', function (): void {
sinon.replaceGetter(vscode.workspace, 'workspaceFolders', () => {
return <vscode.WorkspaceFolder[]>[{
uri: {
fsPath: '/temp/'
fsPath: tempFolderPath
},
}];
});
// only one azure function project found - hostFiles and csproj files stubs
let findFilesStub = sinon.stub(vscode.workspace, 'findFiles');
findFilesStub.onFirstCall().resolves([vscode.Uri.file('/temp/host.json')]);
findFilesStub.onSecondCall().resolves(([vscode.Uri.file('/temp/test.csproj')]) as any);
findFilesStub.onFirstCall().resolves([vscode.Uri.file(path.join(tempFolderPath, 'host.json'))]);
findFilesStub.onSecondCall().resolves(([vscode.Uri.file(path.join(tempFolderPath, 'test.csproj'))]) as any);
let result = await azureFunctionsUtils.getAzureFunctionProject();
should(result).be.equal('/temp/test.csproj', 'Should return test.csproj since only one Azure function project is found');
should(result).be.equal(path.join(tempFolderPath, 'test.csproj'), 'Should return test.csproj since only one Azure function project is found');
});
it('Should return prompt to choose azure function project if multiple azure function projects are found', async () => {
@@ -273,22 +278,23 @@ describe('AzureFunctionUtils', function (): void {
sinon.replaceGetter(vscode.workspace, 'workspaceFolders', () => {
return <vscode.WorkspaceFolder[]>[{
uri: {
fsPath: '/temp/'
fsPath: tempFolderPath
},
}];
});
// multiple azure function projects found in workspace - hostFiles and project find files stubs
let findFilesStub = sinon.stub(vscode.workspace, 'findFiles');
findFilesStub.onFirstCall().resolves(([vscode.Uri.file('/temp/host.json'), vscode.Uri.file('/temp2/host.json')]) as any);
const temp2FolderPath = path.delimiter + 'temp2' + path.delimiter;
findFilesStub.onFirstCall().resolves(([vscode.Uri.file(path.join(tempFolderPath, 'host.json')), vscode.Uri.file(path.join(temp2FolderPath, 'host.json'))]) as any);
// we loop through the hostFiles to find the csproj in same directory
// first loop we use host of /temp/host.json
findFilesStub.onSecondCall().resolves(([vscode.Uri.file('/temp/test.csproj')]) as any);
findFilesStub.onSecondCall().resolves(([vscode.Uri.file(path.join(tempFolderPath, 'test.csproj'))]) as any);
// second loop we use host of /temp2/host.json
findFilesStub.onThirdCall().resolves(([vscode.Uri.file('/temp2/test.csproj')]) as any);
let quickPickStub = sinon.stub(vscode.window, 'showQuickPick').resolves(('/temp/test.csproj') as any);
findFilesStub.onThirdCall().resolves(([vscode.Uri.file(path.join(temp2FolderPath, 'test.csproj'))]) as any);
let quickPickStub = sinon.stub(vscode.window, 'showQuickPick').resolves((path.join(tempFolderPath, 'test.csproj')) as any);
let result = await azureFunctionsUtils.getAzureFunctionProject();
should(result).be.equal('/temp/test.csproj', 'Should return test.csproj since user choose Azure function project');
should(result).be.equal(path.join(tempFolderPath, 'test.csproj'), 'Should return test.csproj since user choose Azure function project');
should(quickPickStub.calledOnce).be.true('showQuickPick should have been called to choose between azure function projects');
});
});