From 84492049e8992e47a4dcaefdacb4fdcf3fcc291f Mon Sep 17 00:00:00 2001 From: Sakshi Sharma <57200045+SakshiS-harma@users.noreply.github.com> Date: Sat, 30 May 2020 09:05:55 -0700 Subject: [PATCH] Enable sql-database-projects tests with few fixes (#10610) * Added 2tests related to import. Fixed a few issues. Enable sql-database-projects * Addressed comment --- .github/workflows/ci.yml | 2 +- .../src/test/project.test.ts | 20 +++++++++++--- .../src/test/projectController.test.ts | 27 ++++++++++++++++--- .../src/test/testUtils.ts | 8 +++--- scripts/test-extensions-unit.bat | 8 +++--- 5 files changed, 50 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cf60a7ef21..27da500e85 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,7 +54,7 @@ jobs: # {{SQL CARBON EDIT}} Add coveralls. We merge first to get around issue where parallel builds weren't being combined correctly - run: | mkdir .build/coverage-combined - cat .build/coverage-single/lcov.info ./extensions/admin-tool-ext-win/coverage/lcov.info ./extensions/agent/coverage/lcov.info ./extensions/azurecore/coverage/lcov.info ./extensions/cms/coverage/lcov.info ./extensions/dacpac/coverage/lcov.info ./extensions/schema-compare/coverage/lcov.info ./extensions/notebook/coverage/lcov.info ./extensions/resource-deployment/coverage/lcov.info ./extensions/machine-learning/coverage/lcov.info > .build/coverage-combined/lcov.info + cat .build/coverage-single/lcov.info ./extensions/admin-tool-ext-win/coverage/lcov.info ./extensions/agent/coverage/lcov.info ./extensions/azurecore/coverage/lcov.info ./extensions/cms/coverage/lcov.info ./extensions/dacpac/coverage/lcov.info ./extensions/schema-compare/coverage/lcov.info ./extensions/notebook/coverage/lcov.info ./extensions/resource-deployment/coverage/lcov.info ./extensions/machine-learning/coverage/lcov.info ./extensions/sql-database-projects/coverage/lcov.info > .build/coverage-combined/lcov.info name: Merge coverage reports - name: Upload Code Coverage uses: coverallsapp/github-action@v1.1.1 diff --git a/extensions/sql-database-projects/src/test/project.test.ts b/extensions/sql-database-projects/src/test/project.test.ts index 3cb064c4d8..21d31e1774 100644 --- a/extensions/sql-database-projects/src/test/project.test.ts +++ b/extensions/sql-database-projects/src/test/project.test.ts @@ -14,7 +14,7 @@ import { Project, EntryType } from '../models/project'; let projFilePath: string; describe('Project: sqlproj content operations', function (): void { - before(async function () : Promise { + before(async function() : Promise { await baselines.loadBaselines(); }); @@ -52,7 +52,7 @@ describe('Project: sqlproj content operations', function (): void { const newFileContents = (await fs.readFile(path.join(newProject.projectFolderPath, filePath))).toString(); - should (newFileContents).equal(fileContents); + should(newFileContents).equal(fileContents); }); it('Should add Folder and Build entries to sqlproj with pre-existing scripts on disk', async function (): Promise { @@ -65,6 +65,20 @@ describe('Project: sqlproj content operations', function (): void { await project.addToProject(list); should(project.files.filter(f => f.type === EntryType.File).length).equal(11); // txt file shouldn't be added to the project - should(project.files.filter(f => f.type === EntryType.Folder).length).equal(3); // 2folders + default Properties folder + should(project.files.filter(f => f.type === EntryType.Folder).length).equal(3); // 2folders + default Properties folder + }); + + it('Should throw error while adding Folder and Build entries to sqlproj when a file/folder does not exist on disk', async function (): Promise { + projFilePath = await testUtils.createTestSqlProjFile(baselines.newProjectFileBaseline); + const project = new Project(projFilePath); + await project.readProjFile(); + + let list: string[] = []; + let testFolderPath: string = await testUtils.createDummyFileStructure(true, list, path.dirname(projFilePath)); + + const nonexistentFile = path.join(testFolderPath, 'nonexistentFile.sql'); + list.push(nonexistentFile); + + await testUtils.shouldThrowSpecificError(async () => await project.addToProject(list), `ENOENT: no such file or directory, stat \'${nonexistentFile}\'`); }); }); diff --git a/extensions/sql-database-projects/src/test/projectController.test.ts b/extensions/sql-database-projects/src/test/projectController.test.ts index e3b5a6c943..35086447ea 100644 --- a/extensions/sql-database-projects/src/test/projectController.test.ts +++ b/extensions/sql-database-projects/src/test/projectController.test.ts @@ -42,9 +42,12 @@ const mockConnectionProfile: azdata.IConnectionProfile = { options: undefined as any }; +beforeEach(async function (): Promise { + testContext = createContext(); +}); + describe('ProjectsController: project controller operations', function (): void { before(async function (): Promise { - testContext = createContext(); await templates.loadTemplates(path.join(__dirname, '..', '..', 'resources', 'templates')); await baselines.loadBaselines(); }); @@ -157,8 +160,10 @@ describe('ProjectsController: import operations', function (): void { }); it('Should error out for inaccessible path', async function (): Promise { + testContext.apiWrapper.setup(x => x.showErrorMessage(TypeMoq.It.isAny())).returns((s) => { throw new Error(s); }); + let testFolderPath = await testUtils.generateTestFolderPath(); - testFolderPath += '_nonExistant'; // Modify folder path to point to a non-existant location + testFolderPath += '_nonexistentFolder'; // Modify folder path to point to a nonexistent location const projController = new ProjectsController(testContext.apiWrapper.object, new SqlDatabaseProjectTreeViewProvider()); @@ -187,7 +192,7 @@ describe('ProjectsController: import operations', function (): void { it('Should show error when no location provided with ExtractTarget = File', async function (): Promise { testContext.apiWrapper.setup(x => x.showInputBox(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => Promise.resolve('MyProjectName')); - testContext.apiWrapper.setup(x => x.showQuickPick(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => Promise.resolve({label: 'File'})); + testContext.apiWrapper.setup(x => x.showQuickPick(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => Promise.resolve({ label: 'File' })); testContext.apiWrapper.setup(x => x.showSaveDialog(TypeMoq.It.isAny())).returns(() => Promise.resolve(undefined)); testContext.apiWrapper.setup(x => x.showErrorMessage(TypeMoq.It.isAny())).returns((s) => { throw new Error(s); }); @@ -197,7 +202,7 @@ describe('ProjectsController: import operations', function (): void { it('Should show error when no location provided with ExtractTarget = SchemaObjectType', async function (): Promise { testContext.apiWrapper.setup(x => x.showInputBox(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => Promise.resolve('MyProjectName')); - testContext.apiWrapper.setup(x => x.showQuickPick(TypeMoq.It.isAny())).returns(() => Promise.resolve({label: 'SchemaObjectType'})); + testContext.apiWrapper.setup(x => x.showQuickPick(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => Promise.resolve({ label: 'SchemaObjectType' })); testContext.apiWrapper.setup(x => x.showOpenDialog(TypeMoq.It.isAny())).returns(() => Promise.resolve(undefined)); testContext.apiWrapper.setup(x => x.workspaceFolders()).returns(() => undefined); testContext.apiWrapper.setup(x => x.showErrorMessage(TypeMoq.It.isAny())).returns((s) => { throw new Error(s); }); @@ -205,4 +210,18 @@ describe('ProjectsController: import operations', function (): void { const projController = new ProjectsController(testContext.apiWrapper.object, new SqlDatabaseProjectTreeViewProvider()); await testUtils.shouldThrowSpecificError(async () => await projController.importNewDatabaseProject(mockConnectionProfile), constants.projectLocationRequired); }); + + it('Should show error when selected folder is not empty', async function (): Promise { + const testFolderPath = await testUtils.createDummyFileStructure(); + + testContext.apiWrapper.setup(x => x.showInputBox(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => Promise.resolve('MyProjectName')); + testContext.apiWrapper.setup(x => x.showQuickPick(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => Promise.resolve({ label: 'ObjectType' })); + testContext.apiWrapper.setup(x => x.showOpenDialog(TypeMoq.It.isAny())).returns(() => Promise.resolve([vscode.Uri.file(testFolderPath)])); + testContext.apiWrapper.setup(x => x.workspaceFolders()).returns(() => undefined); + testContext.apiWrapper.setup(x => x.showErrorMessage(TypeMoq.It.isAny())).returns((s) => { throw new Error(s); }); + + const projController = new ProjectsController(testContext.apiWrapper.object, new SqlDatabaseProjectTreeViewProvider()); + + await testUtils.shouldThrowSpecificError(async () => await projController.importNewDatabaseProject(mockConnectionProfile), constants.projectLocationNotEmpty); + }); }); diff --git a/extensions/sql-database-projects/src/test/testUtils.ts b/extensions/sql-database-projects/src/test/testUtils.ts index 562212f1c4..a3abbc5aeb 100644 --- a/extensions/sql-database-projects/src/test/testUtils.ts +++ b/extensions/sql-database-projects/src/test/testUtils.ts @@ -79,7 +79,7 @@ export async function createDummyFileStructure(createList?: boolean, list?: stri testFolderPath = testFolderPath ?? await generateTestFolderPath(); let filePath = path.join(testFolderPath, 'file1.sql'); - await fs.open(filePath, 'w'); + await fs.writeFile(filePath, ''); if (createList) { list?.push(testFolderPath); list?.push(filePath); @@ -88,13 +88,14 @@ export async function createDummyFileStructure(createList?: boolean, list?: stri for (let dirCount = 1; dirCount <= 2; dirCount++) { let dirName = path.join(testFolderPath, `folder${dirCount}`); await fs.mkdir(dirName, { recursive: true }); + if (createList) { list?.push(dirName); } for (let fileCount = 1; fileCount <= 5; fileCount++) { let fileName = path.join(dirName, `file${fileCount}.sql`); - await fs.open(fileName, 'w'); + await fs.writeFile(fileName, ''); if (createList) { list?.push(fileName); } @@ -102,7 +103,8 @@ export async function createDummyFileStructure(createList?: boolean, list?: stri } filePath = path.join(testFolderPath, 'file2.txt'); - await fs.open(filePath, 'w'); + //await touchFile(filePath); + await fs.writeFile(filePath, ''); if (createList) { list?.push(filePath); } diff --git a/scripts/test-extensions-unit.bat b/scripts/test-extensions-unit.bat index f191d70ca7..283caffa42 100755 --- a/scripts/test-extensions-unit.bat +++ b/scripts/test-extensions-unit.bat @@ -91,10 +91,10 @@ REM echo *** starting mssql tests *** REM echo ****************************************** REM call "%INTEGRATION_TEST_ELECTRON_PATH%" --extensionDevelopmentPath=%~dp0\..\extensions\mssql --extensionTestsPath=%~dp0\..\extensions\mssql\out\test --user-data-dir=%VSCODEUSERDATADIR% --extensions-dir=%VSCODEEXTENSIONSDIR% --remote-debugging-port=9222 --disable-telemetry --disable-crash-reporter --disable-updates --nogpu -REM echo ******************************************** -REM echo *** starting sql-database-projects tests *** -REM echo ******************************************** -REM call "%INTEGRATION_TEST_ELECTRON_PATH%" --extensionDevelopmentPath=%~dp0\..\extensions\sql-database-projects --extensionTestsPath=%~dp0\..\extensions\sql-database-projects\out\test --user-data-dir=%VSCODEUSERDATADIR% --extensions-dir=%VSCODEEXTENSIONSDIR% --remote-debugging-port=9222 --disable-telemetry --disable-crash-reporter --disable-updates --nogpu +echo ******************************************** +echo *** starting sql-database-projects tests *** +echo ******************************************** +call "%INTEGRATION_TEST_ELECTRON_PATH%" --extensionDevelopmentPath=%~dp0\..\extensions\sql-database-projects --extensionTestsPath=%~dp0\..\extensions\sql-database-projects\out\test --user-data-dir=%VSCODEUSERDATADIR% --extensions-dir=%VSCODEEXTENSIONSDIR% --remote-debugging-port=9222 --disable-telemetry --disable-crash-reporter --disable-updates --nogpu if %errorlevel% neq 0 exit /b %errorlevel%