Skip to content

Commit

Permalink
Fix target platform when creating project from database via quickpick (
Browse files Browse the repository at this point in the history
…#26049)

* Create project from quickpick

* Fix test

* Fix test
  • Loading branch information
zijchen committed Dec 11, 2024
1 parent 49c73a8 commit 30c5519
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1581,10 +1581,7 @@ export class ProjectsController {
const databaseName = (await utils.getVscodeMssqlApi()).getDatabaseNameFromTreeNode(treeNodeContext);
(profile as mssqlVscode.IConnectionInfo).database = databaseName;
}
const model = await createNewProjectFromDatabaseWithQuickpick(profile as mssqlVscode.IConnectionInfo);
if (model) {
await this.createProjectFromDatabaseCallback(model, profile as mssqlVscode.IConnectionInfo, (profile as mssqlVscode.IConnectionInfo)?.server);
}
await createNewProjectFromDatabaseWithQuickpick(profile as mssqlVscode.IConnectionInfo, this.createProjectFromDatabaseCallback);
return undefined;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ import { getSDKStyleProjectInfo } from './quickpickHelper';
/**
* Create flow for a New Project using only VS Code-native APIs such as QuickPick
* @param connectionInfo Optional connection info to use instead of prompting the user for a connection
* @param createProjectFromDatabaseCallback Optional callback function to create the project from the user inputs
*/
export async function createNewProjectFromDatabaseWithQuickpick(connectionInfo?: IConnectionInfo): Promise<ImportDataModel | undefined> {
export async function createNewProjectFromDatabaseWithQuickpick(connectionInfo?: IConnectionInfo, createProjectFromDatabaseCallback?: (model: ImportDataModel, connectionInfo?: string | IConnectionInfo, serverName?: string) => Promise<void>): Promise<void> {
const vscodeMssqlApi = await getVscodeMssqlApi();

// 1. Select connection
Expand Down Expand Up @@ -162,7 +163,7 @@ export async function createNewProjectFromDatabaseWithQuickpick(connectionInfo?:
return;
}

return {
const model = {
connectionUri: connectionUri,
database: selectedDatabase,
projName: projectName,
Expand All @@ -171,5 +172,10 @@ export async function createNewProjectFromDatabaseWithQuickpick(connectionInfo?:
extractTarget: mapExtractTargetEnum(folderStructure),
sdkStyle: sdkStyle,
includePermissions: includePermissions
};
} as ImportDataModel;

// 8. Create the project using the callback
if (createProjectFromDatabaseCallback) {
await createProjectFromDatabaseCallback(model, connectionProfile, connectionProfile.server);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,35 +40,44 @@ describe('Create Project From Database Quickpick', () => {
//promptForConnection spy to verify test
const promptForConnectionSpy = sinon.stub(testUtils.vscodeMssqlIExtension.object, 'promptForConnection').withArgs(sinon.match.any).resolves(undefined);

const model = await createProjectFromDatabaseQuickpick.createNewProjectFromDatabaseWithQuickpick();
//createProjectFromDatabaseQuickpick spy to verify test
const createProjectFromDatabaseCallbackSpy = sinon.stub().resolves();

await createProjectFromDatabaseQuickpick.createNewProjectFromDatabaseWithQuickpick(undefined, createProjectFromDatabaseCallbackSpy);

//verify that prompt for connection was called
should(promptForConnectionSpy.calledOnce).be.true('promptForConnection should have been called');

//verify quickpick exited with undefined, since promptForConnection was set to cancel (resolves to undefined)
should.equal(model, undefined);
//verify create project callback was not called, since promptForConnection was set to cancel (resolves to undefined)
should(createProjectFromDatabaseCallbackSpy.notCalled).be.true('createProjectFromDatabaseCallback should not have been called');
});

it('Should not prompt for connection when connectionInfo is provided and exit when db is not selected', async function (): Promise<void> {
//promptForConnection spy to verify test
const promptForConnectionSpy = sinon.stub(testUtils.vscodeMssqlIExtension.object, 'promptForConnection').withArgs(sinon.match.any).resolves(undefined);

//createProjectFromDatabaseQuickpick spy to verify test
const createProjectFromDatabaseCallbackSpy = sinon.stub().resolves();

//user chooses connection
sinon.stub(testUtils.vscodeMssqlIExtension.object, 'connect').resolves('testConnectionURI');
sinon.stub(testUtils.vscodeMssqlIExtension.object, 'listDatabases').withArgs(sinon.match.any).resolves(dbList);
// user chooses to cancel when prompted for database
sinon.stub(vscode.window, 'showQuickPick').resolves(undefined);

const model = await createProjectFromDatabaseQuickpick.createNewProjectFromDatabaseWithQuickpick(mockConnectionInfo);
await createProjectFromDatabaseQuickpick.createNewProjectFromDatabaseWithQuickpick(mockConnectionInfo, createProjectFromDatabaseCallbackSpy);

//verify connection prompt wasn't presented, since connectionInfo was passed during the call
should(promptForConnectionSpy.notCalled).be.true('promptForConnection should not be called when connectionInfo is provided');

//verify quickpick exited with undefined, since database wasn't selected (resolved to undefined)
should.equal(model, undefined);
//verify create project callback was not called, since database wasn't selected (resolved to undefined)
should(createProjectFromDatabaseCallbackSpy.notCalled).be.true('createProjectFromDatabaseCallback should not have been called');
});

it('Should exit when project name is not selected', async function (): Promise<void> {
//createProjectFromDatabaseQuickpick spy to verify test
const createProjectFromDatabaseCallbackSpy = sinon.stub().resolves();

//user chooses connection and database
sinon.stub(testUtils.vscodeMssqlIExtension.object, 'connect').resolves('testConnectionURI');
sinon.stub(testUtils.vscodeMssqlIExtension.object, 'listDatabases').withArgs(sinon.match.any).resolves(dbList);
Expand All @@ -78,13 +87,16 @@ describe('Create Project From Database Quickpick', () => {
// user chooses to cancel when prompted to enter project name
inputBoxStub.onSecondCall().resolves(undefined);

const model = await createProjectFromDatabaseQuickpick.createNewProjectFromDatabaseWithQuickpick(mockConnectionInfo);
await createProjectFromDatabaseQuickpick.createNewProjectFromDatabaseWithQuickpick(mockConnectionInfo, createProjectFromDatabaseCallbackSpy);

//verify showInputBox exited with undefined, since project name wasn't selected (resolved to undefined)
should.equal(model, undefined);
//verify create project callback was not called, since project name wasn't selected (resolved to undefined)
should(createProjectFromDatabaseCallbackSpy.notCalled).be.true('createProjectFromDatabaseCallback should not have been called');
});

it('Should exit when project location is not selected', async function (): Promise<void> {
//createProjectFromDatabaseQuickpick spy to verify test
const createProjectFromDatabaseCallbackSpy = sinon.stub().resolves();

//user chooses connection and database
sinon.stub(testUtils.vscodeMssqlIExtension.object, 'connect').resolves('testConnectionURI');
sinon.stub(testUtils.vscodeMssqlIExtension.object, 'listDatabases').withArgs(sinon.match.any).resolves(dbList);
Expand All @@ -94,13 +106,16 @@ describe('Create Project From Database Quickpick', () => {
//user chooses to exit
quickPickStub.onSecondCall().resolves(undefined);

const model = await createProjectFromDatabaseQuickpick.createNewProjectFromDatabaseWithQuickpick(mockConnectionInfo);
await createProjectFromDatabaseQuickpick.createNewProjectFromDatabaseWithQuickpick(mockConnectionInfo, createProjectFromDatabaseCallbackSpy);

//verify showQuickPick exited with undefined, since project location wasn't selected (resolved to undefined)
should.equal(model, undefined);
//verify create project callback was not called, since project location wasn't selected (resolved to undefined)
should(createProjectFromDatabaseCallbackSpy.notCalled).be.true('createProjectFromDatabaseCallback should not have been called');
});

it('Should exit when project location is not selected (test repeatedness for project location)', async function (): Promise<void> {
//createProjectFromDatabaseQuickpick spy to verify test
const createProjectFromDatabaseCallbackSpy = sinon.stub().resolves();

//user chooses connection and database
sinon.stub(testUtils.vscodeMssqlIExtension.object, 'connect').resolves('testConnectionURI');
sinon.stub(testUtils.vscodeMssqlIExtension.object, 'listDatabases').withArgs(sinon.match.any).resolves(dbList);
Expand All @@ -122,13 +137,16 @@ describe('Create Project From Database Quickpick', () => {
//user chooses to exit
quickPickStub.onCall(4).resolves(undefined);

const model = await createProjectFromDatabaseQuickpick.createNewProjectFromDatabaseWithQuickpick(mockConnectionInfo);
await createProjectFromDatabaseQuickpick.createNewProjectFromDatabaseWithQuickpick(mockConnectionInfo, createProjectFromDatabaseCallbackSpy);

//verify showQuickPick exited with undefined, since project location wasn't selected (resolved to undefined)
should.equal(model, undefined);
//verify create project callback was not called, since project location wasn't selected (resolved to undefined)
should(createProjectFromDatabaseCallbackSpy.notCalled).be.true('createProjectFromDatabaseCallback should not have been called');
});

it('Should exit when folder structure is not selected and folder is selected through browsing (test repeatedness for project location)', async function (): Promise<void> {
//createProjectFromDatabaseQuickpick spy to verify test
const createProjectFromDatabaseCallbackSpy = sinon.stub().resolves();

//user chooses connection and database
sinon.stub(testUtils.vscodeMssqlIExtension.object, 'connect').resolves('testConnectionURI');
sinon.stub(testUtils.vscodeMssqlIExtension.object, 'listDatabases').withArgs(sinon.match.any).resolves(dbList);
Expand All @@ -146,13 +164,16 @@ describe('Create Project From Database Quickpick', () => {
//user chooses to exit when prompted for folder structure
quickPickStub.onCall(3).resolves(undefined);

const model = await createProjectFromDatabaseQuickpick.createNewProjectFromDatabaseWithQuickpick(mockConnectionInfo);
await createProjectFromDatabaseQuickpick.createNewProjectFromDatabaseWithQuickpick(mockConnectionInfo, createProjectFromDatabaseCallbackSpy);

//verify showQuickPick exited with undefined, since folder structure wasn't selected (resolved to undefined)
should.equal(model, undefined);
//verify create project callback was not called, since folder structure wasn't selected (resolved to undefined)
should(createProjectFromDatabaseCallbackSpy.notCalled).be.true('createProjectFromDatabaseCallback should not have been called');
});

it('Should exit when folder structure is not selected and existing folder/file location is selected', async function (): Promise<void> {
//createProjectFromDatabaseQuickpick spy to verify test
const createProjectFromDatabaseCallbackSpy = sinon.stub().resolves();

//create folder and project file
const projectFileName = 'TestProject';
const testProjectFilePath = await generateTestFolderPath(this.test);
Expand All @@ -172,15 +193,18 @@ describe('Create Project From Database Quickpick', () => {
//user chooses to exit when prompted for folder structure
quickPickStub.onCall(3).resolves(undefined);

const model = await createProjectFromDatabaseQuickpick.createNewProjectFromDatabaseWithQuickpick(mockConnectionInfo);
await createProjectFromDatabaseQuickpick.createNewProjectFromDatabaseWithQuickpick(mockConnectionInfo, createProjectFromDatabaseCallbackSpy);

await deleteGeneratedTestFolder();

//verify showQuickPick exited with undefined, since folder structure wasn't selected (resolved to undefined)
should.equal(model, undefined);
//verify create project callback was not called, since folder structure wasn't selected (resolved to undefined)
should(createProjectFromDatabaseCallbackSpy.notCalled).be.true('createProjectFromDatabaseCallback should not have been called');
});

it('Should exit when include permissions is not selected', async function (): Promise<void> {
//createProjectFromDatabaseQuickpick spy to verify test
const createProjectFromDatabaseCallbackSpy = sinon.stub().resolves();

//user chooses connection and database
sinon.stub(testUtils.vscodeMssqlIExtension.object, 'connect').resolves('testConnectionURI');
sinon.stub(testUtils.vscodeMssqlIExtension.object, 'listDatabases').withArgs(sinon.match.any).resolves(dbList);
Expand All @@ -194,13 +218,16 @@ describe('Create Project From Database Quickpick', () => {
//user chooses to exit when prompted for include permissions
quickPickStub.onCall(3).resolves(undefined);

const model = await createProjectFromDatabaseQuickpick.createNewProjectFromDatabaseWithQuickpick(mockConnectionInfo);
await createProjectFromDatabaseQuickpick.createNewProjectFromDatabaseWithQuickpick(mockConnectionInfo, createProjectFromDatabaseCallbackSpy);

//verify showQuickPick exited with undefined, since include permissions wasn't selected (resolved to undefined)
should.equal(model, undefined);
//verify create project callback was not called, since include permissions wasn't selected (resolved to undefined)
should(createProjectFromDatabaseCallbackSpy.notCalled).be.true('createProjectFromDatabaseCallback should not have been called');
});

it('Should exit when sdk style project is not selected', async function (): Promise<void> {
//createProjectFromDatabaseQuickpick spy to verify test
const createProjectFromDatabaseCallbackSpy = sinon.stub().resolves();

//user chooses connection and database
sinon.stub(testUtils.vscodeMssqlIExtension.object, 'connect').resolves('testConnectionURI');
sinon.stub(testUtils.vscodeMssqlIExtension.object, 'listDatabases').withArgs(sinon.match.any).resolves(dbList);
Expand All @@ -216,13 +243,16 @@ describe('Create Project From Database Quickpick', () => {
//user chooses to exit when prompted for sdk style project
sinon.stub(quickpickHelper, 'getSDKStyleProjectInfo').resolves(undefined);

const model = await createProjectFromDatabaseQuickpick.createNewProjectFromDatabaseWithQuickpick(mockConnectionInfo);
await createProjectFromDatabaseQuickpick.createNewProjectFromDatabaseWithQuickpick(mockConnectionInfo, createProjectFromDatabaseCallbackSpy);

//verify showQuickPick exited with undefined, since sdk style project wasn't selected (resolved to undefined)
should.equal(model, undefined);
//verify create project callback was not called, since sdk style project wasn't selected (resolved to undefined)
should(createProjectFromDatabaseCallbackSpy.notCalled).be.true('createProjectFromDatabaseCallback should not have been called');
});

it('Should create correct import data model when all the information is provided', async function (): Promise<void> {
it('Should create project when all the information is provided', async function (): Promise<void> {
//createProjectFromDatabaseQuickpick spy to verify test
const createProjectFromDatabaseCallbackSpy = sinon.stub().resolves();

//user chooses connection and database
sinon.stub(testUtils.vscodeMssqlIExtension.object, 'connect').resolves('testConnectionURI');
sinon.stub(testUtils.vscodeMssqlIExtension.object, 'listDatabases').withArgs(sinon.match.any).resolves(dbList);
Expand All @@ -238,7 +268,7 @@ describe('Create Project From Database Quickpick', () => {
//user chooses sdk style project to be true
sinon.stub(quickpickHelper, 'getSDKStyleProjectInfo').resolves(true);

const model = await createProjectFromDatabaseQuickpick.createNewProjectFromDatabaseWithQuickpick(mockConnectionInfo);
await createProjectFromDatabaseQuickpick.createNewProjectFromDatabaseWithQuickpick(mockConnectionInfo, createProjectFromDatabaseCallbackSpy);

const expectedImportDataModel: ImportDataModel = {
connectionUri: 'testConnectionURI',
Expand All @@ -251,7 +281,8 @@ describe('Create Project From Database Quickpick', () => {
includePermissions: false
};

//verify the model is correctly generated
should(model!).deepEqual(expectedImportDataModel);
//verify create project callback was called with the correct model
should(createProjectFromDatabaseCallbackSpy.calledOnce).be.true('createProjectFromDatabaseCallback should have been called');
should(createProjectFromDatabaseCallbackSpy.calledWithMatch(expectedImportDataModel)).be.true('createProjectFromDatabaseCallback should have been called with the correct model');
});
});

0 comments on commit 30c5519

Please sign in to comment.