mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-18 01:25:37 -05:00
Creating a new database project, project items
* can create, open, and close sqlproj files * can add sql objects to projects
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as path from 'path';
|
||||
import { promises as fs } from 'fs';
|
||||
|
||||
// Project baselines
|
||||
export let newProjectFileBaseline: string;
|
||||
export let openProjectFileBaseline: string;
|
||||
export let openDataSourcesBaseline: string;
|
||||
|
||||
const baselineFolderPath = __dirname;
|
||||
|
||||
export async function loadBaselines() {
|
||||
newProjectFileBaseline = await loadBaseline(baselineFolderPath, 'newSqlProjectBaseline.xml');
|
||||
openProjectFileBaseline = await loadBaseline(baselineFolderPath, 'openSqlProjectBaseline.xml');
|
||||
openDataSourcesBaseline = await loadBaseline(baselineFolderPath, 'openDataSourcesBaseline.json');
|
||||
}
|
||||
|
||||
async function loadBaseline(baselineFolderPath: string, fileName: string): Promise<string> {
|
||||
return (await fs.readFile(path.join(baselineFolderPath, fileName))).toString();
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<Name>TestProjectName</Name>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectVersion>4.1</ProjectVersion>
|
||||
<ProjectGuid>{BA5EBA11-C0DE-5EA7-ACED-BABB1E70A575}</ProjectGuid>
|
||||
<DSP>Microsoft.Data.Tools.Schema.Sql.Sql130DatabaseSchemaProvider</DSP>
|
||||
<OutputType>Database</OutputType>
|
||||
<RootPath>
|
||||
</RootPath>
|
||||
<RootNamespace>TestProjectName</RootNamespace>
|
||||
<AssemblyName>TestProjectName</AssemblyName>
|
||||
<ModelCollation>1033, CI</ModelCollation>
|
||||
<DefaultFileStructure>BySchemaAndSchemaType</DefaultFileStructure>
|
||||
<DeployToDatabase>True</DeployToDatabase>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetLanguage>CS</TargetLanguage>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<SqlServerVerification>False</SqlServerVerification>
|
||||
<IncludeCompositeObjects>True</IncludeCompositeObjects>
|
||||
<TargetDatabaseSet>True</TargetDatabaseSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<BuildScriptName>$(MSBuildProjectName).sql</BuildScriptName>
|
||||
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<DefineDebug>false</DefineDebug>
|
||||
<DefineTrace>true</DefineTrace>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<BuildScriptName>$(MSBuildProjectName).sql</BuildScriptName>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<DefineDebug>true</DefineDebug>
|
||||
<DefineTrace>true</DefineTrace>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">11.0</VisualStudioVersion>
|
||||
<!-- Default to the v11.0 targets path if the targets file for the current VS version is not found -->
|
||||
<SSDTExists Condition="Exists('$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets')">True</SSDTExists>
|
||||
<VisualStudioVersion Condition="'$(SSDTExists)' == ''">11.0</VisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<Import Condition="'$(SQLDBExtensionsRefPath)' != ''" Project="$(SQLDBExtensionsRefPath)\Microsoft.Data.Tools.Schema.SqlTasks.targets" />
|
||||
<Import Condition="'$(SQLDBExtensionsRefPath)' == ''" Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets" />
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"version": "0.0.0",
|
||||
"datasources" : [
|
||||
{
|
||||
"name": "Test Data Source 1",
|
||||
"type": "sql_connection_string",
|
||||
"version": "0.0.0",
|
||||
"data": {
|
||||
"connectionString": "Data Source=.;Initial Catalog=testDb;Integrated Security=True"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "My Other Data Source",
|
||||
"type": "sql_connection_string",
|
||||
"version": "0.0.0",
|
||||
"data": {
|
||||
"connectionString": "Data Source=.;Initial Catalog=testDb2;Integrated Security=False"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<Name>TestProjectName</Name>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectVersion>4.1</ProjectVersion>
|
||||
<ProjectGuid>{BA5EBA11-C0DE-5EA7-ACED-BABB1E70A575}</ProjectGuid>
|
||||
<DSP>Microsoft.Data.Tools.Schema.Sql.Sql130DatabaseSchemaProvider</DSP>
|
||||
<OutputType>Database</OutputType>
|
||||
<RootPath>
|
||||
</RootPath>
|
||||
<RootNamespace>TestProjectName</RootNamespace>
|
||||
<AssemblyName>TestProjectName</AssemblyName>
|
||||
<ModelCollation>1033, CI</ModelCollation>
|
||||
<DefaultFileStructure>BySchemaAndSchemaType</DefaultFileStructure>
|
||||
<DeployToDatabase>True</DeployToDatabase>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<TargetLanguage>CS</TargetLanguage>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<SqlServerVerification>False</SqlServerVerification>
|
||||
<IncludeCompositeObjects>True</IncludeCompositeObjects>
|
||||
<TargetDatabaseSet>True</TargetDatabaseSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<BuildScriptName>$(MSBuildProjectName).sql</BuildScriptName>
|
||||
<TreatWarningsAsErrors>False</TreatWarningsAsErrors>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<DefineDebug>false</DefineDebug>
|
||||
<DefineTrace>true</DefineTrace>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<BuildScriptName>$(MSBuildProjectName).sql</BuildScriptName>
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<DefineDebug>true</DefineDebug>
|
||||
<DefineTrace>true</DefineTrace>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">11.0</VisualStudioVersion>
|
||||
<!-- Default to the v11.0 targets path if the targets file for the current VS version is not found -->
|
||||
<SSDTExists Condition="Exists('$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets')">True</SSDTExists>
|
||||
<VisualStudioVersion Condition="'$(SSDTExists)' == ''">11.0</VisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<Import Condition="'$(SQLDBExtensionsRefPath)' != ''" Project="$(SQLDBExtensionsRefPath)\Microsoft.Data.Tools.Schema.SqlTasks.targets" />
|
||||
<Import Condition="'$(SQLDBExtensionsRefPath)' == ''" Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\SSDT\Microsoft.Data.Tools.Schema.SqlTasks.targets" />
|
||||
<ItemGroup>
|
||||
<Folder Include="Properties" />
|
||||
<Folder Include="Tables" />
|
||||
<Folder Include="Views" />
|
||||
<Folder Include="Views\Maintenance" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Build Include="Tables\Users.sql" />
|
||||
<Build Include="Tables\Action History.sql" />
|
||||
<Build Include="Views\Maintenance\Database Performance.sql" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Views\User" />
|
||||
<Build Include="Views\User\Profile.sql" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
30
extensions/sql-database-projects/src/test/datasource.test.ts
Normal file
30
extensions/sql-database-projects/src/test/datasource.test.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as should from 'should';
|
||||
import * as baselines from './baselines/baselines';
|
||||
import * as testUtils from './testUtils';
|
||||
import * as sql from '../models/dataSources/sqlConnectionStringSource';
|
||||
import * as dataSources from '../models/dataSources/dataSources';
|
||||
|
||||
describe('Data Sources: DataSource operations', function (): void {
|
||||
before(async function () : Promise<void> {
|
||||
await baselines.loadBaselines();
|
||||
});
|
||||
|
||||
it('Should read DataSources from datasource.json', async function (): Promise<void> {
|
||||
const dataSourcePath = await testUtils.createTestDataSources(baselines.openDataSourcesBaseline);
|
||||
const dataSourceList = await dataSources.load(dataSourcePath);
|
||||
|
||||
should(dataSourceList.length).equal(2);
|
||||
|
||||
should(dataSourceList[0].name).equal('Test Data Source 1');
|
||||
should(dataSourceList[0].type).equal(sql.SqlConnectionDataSource.type);
|
||||
should((dataSourceList[0] as sql.SqlConnectionDataSource).getSetting('Initial Catalog')).equal('testDb');
|
||||
|
||||
should(dataSourceList[1].name).equal('My Other Data Source');
|
||||
should((dataSourceList[1] as sql.SqlConnectionDataSource).getSetting('Integrated Security')).equal('False');
|
||||
});
|
||||
});
|
||||
48
extensions/sql-database-projects/src/test/index.ts
Normal file
48
extensions/sql-database-projects/src/test/index.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as path from 'path';
|
||||
const testRunner = require('vscodetestcover');
|
||||
|
||||
const suite = 'Database Projects Extension Tests';
|
||||
|
||||
const mochaOptions: any = {
|
||||
ui: 'bdd',
|
||||
useColors: true,
|
||||
timeout: 10000
|
||||
};
|
||||
|
||||
// set relevant mocha options from the environment
|
||||
if (process.env.ADS_TEST_GREP) {
|
||||
mochaOptions.grep = process.env.ADS_TEST_GREP;
|
||||
console.log(`setting options.grep to: ${mochaOptions.grep}`);
|
||||
}
|
||||
if (process.env.ADS_TEST_INVERT_GREP) {
|
||||
mochaOptions.invert = parseInt(process.env.ADS_TEST_INVERT_GREP);
|
||||
console.log(`setting options.invert to: ${mochaOptions.invert}`);
|
||||
}
|
||||
if (process.env.ADS_TEST_TIMEOUT) {
|
||||
mochaOptions.timeout = parseInt(process.env.ADS_TEST_TIMEOUT);
|
||||
console.log(`setting options.timeout to: ${mochaOptions.timeout}`);
|
||||
}
|
||||
if (process.env.ADS_TEST_RETRIES) {
|
||||
mochaOptions.retries = parseInt(process.env.ADS_TEST_RETRIES);
|
||||
console.log(`setting options.retries to: ${mochaOptions.retries}`);
|
||||
}
|
||||
|
||||
if (process.env.BUILD_ARTIFACTSTAGINGDIRECTORY) {
|
||||
mochaOptions.reporter = 'mocha-multi-reporters';
|
||||
mochaOptions.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`)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
testRunner.configure(mochaOptions, { coverConfig: '../../coverConfig.json' });
|
||||
|
||||
export = testRunner;
|
||||
57
extensions/sql-database-projects/src/test/project.test.ts
Normal file
57
extensions/sql-database-projects/src/test/project.test.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as should from 'should';
|
||||
import * as path from 'path';
|
||||
import * as baselines from './baselines/baselines';
|
||||
import * as testUtils from './testUtils';
|
||||
|
||||
import { promises as fs } from 'fs';
|
||||
import { Project, EntryType } from '../models/project';
|
||||
|
||||
let projFilePath: string;
|
||||
|
||||
describe('Project: sqlproj content operations', function (): void {
|
||||
before(async function () : Promise<void> {
|
||||
await baselines.loadBaselines();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
projFilePath = await testUtils.createTestSqlProj(baselines.openProjectFileBaseline);
|
||||
});
|
||||
|
||||
it('Should read Project from sqlproj', async function (): Promise<void> {
|
||||
const project: Project = new Project(projFilePath);
|
||||
await project.readProjFile();
|
||||
|
||||
should(project.files.filter(f => f.type === EntryType.File).length).equal(4);
|
||||
should(project.files.filter(f => f.type === EntryType.Folder).length).equal(5);
|
||||
|
||||
should(project.files.find(f => f.type === EntryType.Folder && f.relativePath === 'Views\\User')).not.equal(undefined); // mixed ItemGroup folder
|
||||
should(project.files.find(f => f.type === EntryType.File && f.relativePath === 'Views\\User\\Profile.sql')).not.equal(undefined); // mixed ItemGroup file
|
||||
});
|
||||
|
||||
it('Should add Folder and Build entries to sqlproj', async function (): Promise<void> {
|
||||
const project: Project = new Project(projFilePath);
|
||||
await project.readProjFile();
|
||||
|
||||
const folderPath = 'Stored Procedures';
|
||||
const filePath = path.join(folderPath, 'Fake Stored Proc.sql');
|
||||
const fileContents = 'SELECT \'This is not actually a stored procedure.\'';
|
||||
|
||||
await project.addFolderItem(folderPath);
|
||||
await project.addScriptItem(filePath, fileContents);
|
||||
|
||||
const newProject = new Project(projFilePath);
|
||||
await newProject.readProjFile();
|
||||
|
||||
should(newProject.files.find(f => f.type === EntryType.Folder && f.relativePath === folderPath)).not.equal(undefined);
|
||||
should(newProject.files.find(f => f.type === EntryType.File && f.relativePath === filePath)).not.equal(undefined);
|
||||
|
||||
const newFileContents = (await fs.readFile(path.join(newProject.projectFolderPath, filePath))).toString();
|
||||
|
||||
should (newFileContents).equal(fileContents);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,48 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as should from 'should';
|
||||
import * as path from 'path';
|
||||
import * as os from 'os';
|
||||
import * as vscode from 'vscode';
|
||||
import * as baselines from './baselines/baselines';
|
||||
import * as templates from '../templates/templates';
|
||||
import * as testUtils from './testUtils';
|
||||
|
||||
import { SqlDatabaseProjectTreeViewProvider } from '../controllers/databaseProjectTreeViewProvider';
|
||||
import { ProjectsController } from '../controllers/projectController';
|
||||
import { promises as fs } from 'fs';
|
||||
|
||||
describe('ProjectsController: project controller operations', function (): void {
|
||||
before(async function () : Promise<void> {
|
||||
await templates.loadTemplates(path.join(__dirname, '..', '..', 'resources', 'templates'));
|
||||
await baselines.loadBaselines();
|
||||
});
|
||||
|
||||
it('Should create new sqlproj file with correct values', async function (): Promise<void> {
|
||||
const projController = new ProjectsController(new SqlDatabaseProjectTreeViewProvider());
|
||||
const projFileDir = path.join(os.tmpdir(), `TestProject_${new Date().getTime()}`);
|
||||
|
||||
const projFilePath = await projController.createNewProject('TestProjectName', vscode.Uri.file(projFileDir), 'BA5EBA11-C0DE-5EA7-ACED-BABB1E70A575');
|
||||
|
||||
let projFileText = (await fs.readFile(projFilePath)).toString();
|
||||
|
||||
should(projFileText).equal(baselines.newProjectFileBaseline);
|
||||
});
|
||||
|
||||
it('Should load Project and associated DataSources', async function (): Promise<void> {
|
||||
// setup test files
|
||||
const folderPath = await testUtils.generateTestFolderPath();
|
||||
const sqlProjPath = await testUtils.createTestSqlProj(baselines.openProjectFileBaseline, folderPath);
|
||||
await testUtils.createTestDataSources(baselines.openDataSourcesBaseline, folderPath);
|
||||
|
||||
const projController = new ProjectsController(new SqlDatabaseProjectTreeViewProvider());
|
||||
|
||||
const project = await projController.openProject(vscode.Uri.file(sqlProjPath));
|
||||
|
||||
should(project.files.length).equal(9); // detailed sqlproj tests in their own test file
|
||||
should(project.dataSources.length).equal(2); // detailed datasources tests in their own test file
|
||||
});
|
||||
});
|
||||
35
extensions/sql-database-projects/src/test/testUtils.ts
Normal file
35
extensions/sql-database-projects/src/test/testUtils.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as path from 'path';
|
||||
import * as os from 'os';
|
||||
import * as constants from '../common/constants';
|
||||
|
||||
import { promises as fs } from 'fs';
|
||||
|
||||
export async function createTestSqlProj(contents: string, folderPath?: string): Promise<string> {
|
||||
return await createTestFile(contents, 'TestProject.sqlproj', folderPath);
|
||||
}
|
||||
|
||||
export async function createTestDataSources(contents: string, folderPath?: string): Promise<string> {
|
||||
return await createTestFile(contents, constants.dataSourcesFileName, folderPath);
|
||||
}
|
||||
|
||||
export async function generateTestFolderPath(): Promise<string> {
|
||||
const folderPath = path.join(os.tmpdir(), `TestProject_${new Date().getTime()}`);
|
||||
await fs.mkdir(folderPath, { recursive: true });
|
||||
|
||||
return folderPath;
|
||||
}
|
||||
|
||||
async function createTestFile(contents: string, fileName: string, folderPath?: string): Promise<string> {
|
||||
folderPath = folderPath ?? await generateTestFolderPath();
|
||||
const filePath = path.join(folderPath, fileName);
|
||||
|
||||
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
||||
await fs.writeFile(filePath, contents);
|
||||
|
||||
return filePath;
|
||||
}
|
||||
Reference in New Issue
Block a user