diff --git a/extensions/sql-database-projects/src/controllers/projectController.ts b/extensions/sql-database-projects/src/controllers/projectController.ts index 28f00f6872..5d0a23cc50 100644 --- a/extensions/sql-database-projects/src/controllers/projectController.ts +++ b/extensions/sql-database-projects/src/controllers/projectController.ts @@ -17,7 +17,7 @@ import * as azdata from 'azdata'; import { promises as fs } from 'fs'; import { PublishDatabaseDialog } from '../dialogs/publishDatabaseDialog'; -import { Project, ProjectEntry, reservedProjectFolders, SqlProjectReferenceProjectEntry } from '../models/project'; +import { Project, reservedProjectFolders, FileProjectEntry, SqlProjectReferenceProjectEntry } from '../models/project'; import { SqlDatabaseProjectTreeViewProvider } from './databaseProjectTreeViewProvider'; import { FolderNode, FileNode } from '../models/tree/fileFolderTreeItem'; import { IPublishSettings, IGenerateScriptSettings } from '../models/IPublishSettings'; @@ -372,7 +372,7 @@ export class ProjectsController { public async exclude(context: FileNode | FolderNode): Promise { const project = this.getProjectFromContext(context); - const fileEntry = this.getProjectEntry(project, context); + const fileEntry = this.getFileProjectEntry(project, context); if (fileEntry) { await project.exclude(fileEntry); @@ -396,7 +396,7 @@ export class ProjectsController { let success = false; if (context instanceof FileNode || FolderNode) { - const fileEntry = this.getProjectEntry(project, context); + const fileEntry = this.getFileProjectEntry(project, context); if (fileEntry) { await project.deleteFileFolder(fileEntry); @@ -411,7 +411,7 @@ export class ProjectsController { } } - private getProjectEntry(project: Project, context: BaseProjectTreeItem): ProjectEntry | undefined { + private getFileProjectEntry(project: Project, context: BaseProjectTreeItem): FileProjectEntry | undefined { const root = context.root as ProjectRootTreeItem; const fileOrFolder = context as FileNode ? context as FileNode : context as FolderNode; diff --git a/extensions/sql-database-projects/src/models/project.ts b/extensions/sql-database-projects/src/models/project.ts index bf0a3f8db9..b77180748f 100644 --- a/extensions/sql-database-projects/src/models/project.ts +++ b/extensions/sql-database-projects/src/models/project.ts @@ -22,14 +22,14 @@ import { ISystemDatabaseReferenceSettings, IDacpacReferenceSettings } from './ID export class Project { public projectFilePath: string; public projectFileName: string; - public files: ProjectEntry[] = []; + public files: FileProjectEntry[] = []; public dataSources: DataSource[] = []; public importedTargets: string[] = []; public databaseReferences: IDatabaseReferenceProjectEntry[] = []; public sqlCmdVariables: Record = {}; - public preDeployScripts: ProjectEntry[] = []; - public postDeployScripts: ProjectEntry[] = []; - public noneDeployScripts: ProjectEntry[] = []; + public preDeployScripts: FileProjectEntry[] = []; + public postDeployScripts: FileProjectEntry[] = []; + public noneDeployScripts: FileProjectEntry[] = []; public get projectFolderPath() { return Uri.file(path.dirname(this.projectFilePath)).fsPath; @@ -65,14 +65,14 @@ export class Project { const buildElements = itemGroup.getElementsByTagName(constants.Build); for (let b = 0; b < buildElements.length; b++) { - this.files.push(this.createProjectEntry(buildElements[b].getAttribute(constants.Include), EntryType.File)); + this.files.push(this.createFileProjectEntry(buildElements[b].getAttribute(constants.Include), EntryType.File)); } const folderElements = itemGroup.getElementsByTagName(constants.Folder); for (let f = 0; f < folderElements.length; f++) { // don't add Properties folder since it isn't supported for now if (folderElements[f].getAttribute(constants.Include) !== constants.Properties) { - this.files.push(this.createProjectEntry(folderElements[f].getAttribute(constants.Include), EntryType.Folder)); + this.files.push(this.createFileProjectEntry(folderElements[f].getAttribute(constants.Include), EntryType.Folder)); } } @@ -80,7 +80,7 @@ export class Project { let preDeployScriptCount: number = 0; const preDeploy = itemGroup.getElementsByTagName(constants.PreDeploy); for (let pre = 0; pre < preDeploy.length; pre++) { - this.preDeployScripts.push(this.createProjectEntry(preDeploy[pre].getAttribute(constants.Include), EntryType.File)); + this.preDeployScripts.push(this.createFileProjectEntry(preDeploy[pre].getAttribute(constants.Include), EntryType.File)); preDeployScriptCount++; } @@ -88,7 +88,7 @@ export class Project { let postDeployScriptCount: number = 0; const postDeploy = itemGroup.getElementsByTagName(constants.PostDeploy); for (let post = 0; post < postDeploy.length; post++) { - this.postDeployScripts.push(this.createProjectEntry(postDeploy[post].getAttribute(constants.Include), EntryType.File)); + this.postDeployScripts.push(this.createFileProjectEntry(postDeploy[post].getAttribute(constants.Include), EntryType.File)); postDeployScriptCount++; } @@ -99,7 +99,7 @@ export class Project { // find all none-deployment scripts to include const noneItems = itemGroup.getElementsByTagName(constants.None); for (let n = 0; n < noneItems.length; n++) { - this.noneDeployScripts.push(this.createProjectEntry(noneItems[n].getAttribute(constants.Include), EntryType.File)); + this.noneDeployScripts.push(this.createFileProjectEntry(noneItems[n].getAttribute(constants.Include), EntryType.File)); } } @@ -210,7 +210,7 @@ export class Project { await fs.mkdir(absoluteFolderPath, { recursive: true }); } - const folderEntry = this.createProjectEntry(relativeFolderPath, EntryType.Folder); + const folderEntry = this.createFileProjectEntry(relativeFolderPath, EntryType.Folder); this.files.push(folderEntry); await this.addToProjFile(folderEntry); @@ -222,7 +222,7 @@ export class Project { * @param relativeFilePath Relative path of the file * @param contents Contents to be written to the new file */ - public async addScriptItem(relativeFilePath: string, contents?: string, itemType?: string): Promise { + public async addScriptItem(relativeFilePath: string, contents?: string, itemType?: string): Promise { const absoluteFilePath = path.join(this.projectFolderPath, relativeFilePath); if (contents) { @@ -236,7 +236,7 @@ export class Project { throw new Error(constants.noFileExist(absoluteFilePath)); } - const fileEntry = this.createProjectEntry(relativeFilePath, EntryType.File); + const fileEntry = this.createFileProjectEntry(relativeFilePath, EntryType.File); let xmlTag; switch (itemType) { @@ -258,16 +258,16 @@ export class Project { return fileEntry; } - public async exclude(entry: ProjectEntry): Promise { - const toExclude: ProjectEntry[] = this.files.filter(x => x.fsUri.fsPath.startsWith(entry.fsUri.fsPath)); + public async exclude(entry: FileProjectEntry): Promise { + const toExclude: FileProjectEntry[] = this.files.filter(x => x.fsUri.fsPath.startsWith(entry.fsUri.fsPath)); await this.removeFromProjFile(toExclude); this.files = this.files.filter(x => !x.fsUri.fsPath.startsWith(entry.fsUri.fsPath)); } - public async deleteFileFolder(entry: ProjectEntry): Promise { + public async deleteFileFolder(entry: FileProjectEntry): Promise { // compile a list of folder contents to delete; if entry is a file, contents will contain only itself - const toDeleteFiles: ProjectEntry[] = this.files.filter(x => x.fsUri.fsPath.startsWith(entry.fsUri.fsPath) && x.type === EntryType.File); - const toDeleteFolders: ProjectEntry[] = this.files.filter(x => x.fsUri.fsPath.startsWith(entry.fsUri.fsPath) && x.type === EntryType.Folder).sort(x => -x.relativePath.length); + const toDeleteFiles: FileProjectEntry[] = this.files.filter(x => x.fsUri.fsPath.startsWith(entry.fsUri.fsPath) && x.type === EntryType.File); + const toDeleteFolders: FileProjectEntry[] = this.files.filter(x => x.fsUri.fsPath.startsWith(entry.fsUri.fsPath) && x.type === EntryType.Folder).sort(x => -x.relativePath.length); await Promise.all(toDeleteFiles.map(x => fs.unlink(x.fsUri.fsPath))); @@ -349,9 +349,19 @@ export class Project { await this.addToProjFile(databaseReferenceEntry); } - public createProjectEntry(relativePath: string, entryType: EntryType): ProjectEntry { + /** + * Adds a SQLCMD variable to the project + * @param name name of the variable + * @param defaultValue + */ + public async addSqlCmdVariable(name: string, defaultValue: string) { + const sqlCmdVariableEntry = new SqlCmdVariableProjectEntry(name, defaultValue); + await this.addToProjFile(sqlCmdVariableEntry); + } + + public createFileProjectEntry(relativePath: string, entryType: EntryType): FileProjectEntry { let platformSafeRelativePath = utils.getPlatformSafeFileEntryPath(relativePath); - return new ProjectEntry(Uri.file(path.join(this.projectFolderPath, platformSafeRelativePath)), relativePath, entryType); + return new FileProjectEntry(Uri.file(path.join(this.projectFolderPath, platformSafeRelativePath)), relativePath, entryType); } private findOrCreateItemGroup(containedTag?: string, prePostScriptExist?: { scriptExist: boolean; }): any { @@ -383,7 +393,7 @@ export class Project { return outputItemGroup; } - private addFileToProjFile(path: string, xmlTag: string) { + private addFileToProjFile(path: string, xmlTag: string): void { let itemGroup; if (xmlTag === constants.PreDeploy || xmlTag === constants.PostDeploy) { @@ -403,7 +413,7 @@ export class Project { itemGroup.appendChild(newFileNode); } - private removeFileFromProjFile(path: string) { + private removeFileFromProjFile(path: string): void { const fileNodes = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.Build); for (let i = 0; i < fileNodes.length; i++) { @@ -416,14 +426,14 @@ export class Project { throw new Error(constants.unableToFindObject(path, constants.fileObject)); } - private addFolderToProjFile(path: string) { + private addFolderToProjFile(path: string): void { const newFolderNode = this.projFileXmlDoc.createElement(constants.Folder); newFolderNode.setAttribute(constants.Include, utils.convertSlashesForSqlProj(path)); this.findOrCreateItemGroup(constants.Folder).appendChild(newFolderNode); } - private removeFolderFromProjFile(path: string) { + private removeFolderFromProjFile(path: string): void { const folderNodes = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.Folder); for (let i = 0; i < folderNodes.length; i++) { @@ -436,6 +446,16 @@ export class Project { throw new Error(constants.unableToFindObject(path, constants.folderObject)); } + private removeSqlCmdVariableFromProjFile(variableName: string): void { + const sqlCmdVariableNodes = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.SqlCmdVariable); + + for (let i = 0; i < sqlCmdVariableNodes.length; i++) { + if (sqlCmdVariableNodes[i].getAttribute(constants.Include) === variableName) { + sqlCmdVariableNodes[i].parentNode.removeChild(sqlCmdVariableNodes[i]); + } + } + } + private addSystemDatabaseReferenceToProjFile(entry: SystemDatabaseReferenceProjectEntry): void { const systemDbReferenceNode = this.projFileXmlDoc.createElement(constants.ArtifactReference); @@ -495,6 +515,54 @@ export class Project { } } + public addSqlCmdVariableToProjFile(entry: SqlCmdVariableProjectEntry): void { + // Remove any entries with the same variable name. It'll be replaced with a new one + this.removeFromProjFile(entry); + + const sqlCmdVariableNode = this.projFileXmlDoc.createElement(constants.SqlCmdVariable); + sqlCmdVariableNode.setAttribute(constants.Include, entry.variableName); + this.addSqlCmdVariableChildren(sqlCmdVariableNode, entry); + this.findOrCreateItemGroup(constants.SqlCmdVariable).appendChild(sqlCmdVariableNode); + + // add to the project's loaded sqlcmd variables + this.sqlCmdVariables[entry.variableName] = entry.defaultValue; + } + + private addSqlCmdVariableChildren(sqlCmdVariableNode: any, entry: SqlCmdVariableProjectEntry): void { + // add default value + const defaultValueNode = this.projFileXmlDoc.createElement(constants.DefaultValue); + const defaultValueText = this.projFileXmlDoc.createTextNode(entry.defaultValue); + defaultValueNode.appendChild(defaultValueText); + sqlCmdVariableNode.appendChild(defaultValueNode); + + // add value node which is in the format $(SqlCmdVar__x) + const valueNode = this.projFileXmlDoc.createElement(constants.Value); + const valueText = this.projFileXmlDoc.createTextNode(`$(SqlCmdVar__${this.getNextSqlCmdVariableCounter()})`); + valueNode.appendChild(valueText); + sqlCmdVariableNode.appendChild(valueNode); + } + + /** + * returns the next number that should be used for the new SqlCmd Variable. Old numbers don't get reused even if a SqlCmd Variable + * gets removed from the project + */ + private getNextSqlCmdVariableCounter(): number { + const sqlCmdVariableNodes = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.SqlCmdVariable); + let highestNumber = 1; + + for (let i = 0; i < sqlCmdVariableNodes.length; i++) { + const value: string = sqlCmdVariableNodes[i].getElementsByTagName(constants.Value)[0].childNodes[0].nodeValue; + const number = parseInt(value.substring(13).slice(0, -1)); // want the number x in $(SqlCmdVar__x) + + // incremement the counter if there's already a variable with the same number or greater + if (number > highestNumber) { + highestNumber = number; + } + } + + return highestNumber + 1; + } + private async updateImportedTargetsToProjFile(condition: string, projectAttributeVal: string, oldImportNode?: any): Promise { const importNode = this.projFileXmlDoc.createElement(constants.Import); importNode.setAttribute(constants.Condition, condition); @@ -570,13 +638,16 @@ export class Project { private async addToProjFile(entry: ProjectEntry, xmlTag?: string) { switch (entry.type) { case EntryType.File: - this.addFileToProjFile(entry.relativePath, xmlTag ? xmlTag : constants.Build); + this.addFileToProjFile((entry).relativePath, xmlTag ? xmlTag : constants.Build); break; case EntryType.Folder: - this.addFolderToProjFile(entry.relativePath); + this.addFolderToProjFile((entry).relativePath); break; case EntryType.DatabaseReference: this.addDatabaseReferenceToProjFile(entry); + break; + case EntryType.SqlCmdVariable: + this.addSqlCmdVariableToProjFile(entry); break; // not required but adding so that we dont miss when we add new items } @@ -591,12 +662,15 @@ export class Project { for (const entry of entries) { switch (entry.type) { case EntryType.File: - this.removeFileFromProjFile(entry.relativePath); + this.removeFileFromProjFile((entry).relativePath); break; case EntryType.Folder: - this.removeFolderFromProjFile(entry.relativePath); + this.removeFolderFromProjFile((entry).relativePath); break; case EntryType.DatabaseReference: + break; + case EntryType.SqlCmdVariable: + this.removeSqlCmdVariableFromProjFile((entry).variableName); break; // not required but adding so that we dont miss when we add new items } } @@ -638,18 +712,25 @@ export class Project { /** * Represents an entry in a project file */ -export class ProjectEntry { +export abstract class ProjectEntry { + type: EntryType; + + constructor(type: EntryType) { + this.type = type; + } +} + +export class FileProjectEntry extends ProjectEntry { /** * Absolute file system URI */ fsUri: Uri; relativePath: string; - type: EntryType; constructor(uri: Uri, relativePath: string, type: EntryType) { + super(type); this.fsUri = uri; this.relativePath = relativePath; - this.type = type; } public toString(): string { @@ -665,12 +746,12 @@ export class ProjectEntry { * Represents a database reference entry in a project file */ -export interface IDatabaseReferenceProjectEntry extends ProjectEntry { +export interface IDatabaseReferenceProjectEntry extends FileProjectEntry { databaseName: string; databaseVariableLiteralValue?: string; } -export class DacpacReferenceProjectEntry extends ProjectEntry implements IDatabaseReferenceProjectEntry { +export class DacpacReferenceProjectEntry extends FileProjectEntry implements IDatabaseReferenceProjectEntry { databaseLocation: DatabaseReferenceLocation; databaseVariableLiteralValue?: string; @@ -688,7 +769,7 @@ export class DacpacReferenceProjectEntry extends ProjectEntry implements IDataba } } -class SystemDatabaseReferenceProjectEntry extends ProjectEntry implements IDatabaseReferenceProjectEntry { +class SystemDatabaseReferenceProjectEntry extends FileProjectEntry implements IDatabaseReferenceProjectEntry { constructor(uri: Uri, public ssdtUri: Uri, public databaseVariableLiteralValue: string) { super(uri, '', EntryType.DatabaseReference); } @@ -711,7 +792,7 @@ class SystemDatabaseReferenceProjectEntry extends ProjectEntry implements IDatab } } -export class SqlProjectReferenceProjectEntry extends ProjectEntry implements IDatabaseReferenceProjectEntry { +export class SqlProjectReferenceProjectEntry extends FileProjectEntry implements IDatabaseReferenceProjectEntry { projectName: string; constructor(uri: Uri, name: string) { @@ -724,10 +805,17 @@ export class SqlProjectReferenceProjectEntry extends ProjectEntry implements IDa } } +export class SqlCmdVariableProjectEntry extends ProjectEntry { + constructor(public variableName: string, public defaultValue: string) { + super(EntryType.SqlCmdVariable); + } +} + export enum EntryType { File, Folder, - DatabaseReference + DatabaseReference, + SqlCmdVariable } export enum DatabaseReferenceLocation { diff --git a/extensions/sql-database-projects/src/models/tree/projectTreeItem.ts b/extensions/sql-database-projects/src/models/tree/projectTreeItem.ts index 9925aaeb7e..2c02b2e54e 100644 --- a/extensions/sql-database-projects/src/models/tree/projectTreeItem.ts +++ b/extensions/sql-database-projects/src/models/tree/projectTreeItem.ts @@ -8,7 +8,7 @@ import * as path from 'path'; import { DataSourcesTreeItem } from './dataSourceTreeItem'; import { BaseProjectTreeItem } from './baseTreeItem'; import * as fileTree from './fileFolderTreeItem'; -import { Project, ProjectEntry, EntryType } from '../project'; +import { Project, EntryType, FileProjectEntry } from '../project'; import * as utils from '../../common/utils'; import { DatabaseReferencesTreeItem } from './databaseReferencesTreeItem'; import { DatabaseProjectItemType, RelativeOuterPath } from '../../common/constants'; @@ -92,7 +92,7 @@ export class ProjectRootTreeItem extends BaseProjectTreeItem { /** * Gets the immediate parent tree node for an entry in a project file */ - private getEntryParentNode(entry: ProjectEntry): fileTree.FolderNode | ProjectRootTreeItem { + private getEntryParentNode(entry: FileProjectEntry): fileTree.FolderNode | ProjectRootTreeItem { const relativePathParts = utils.trimChars(utils.trimUri(vscode.Uri.file(this.project.projectFilePath), entry.fsUri), '/').split('/').slice(0, -1); // remove the last part because we only care about the parent if (relativePathParts.length === 0) { diff --git a/extensions/sql-database-projects/src/test/baselines/baselines.ts b/extensions/sql-database-projects/src/test/baselines/baselines.ts index 005e1412c4..5630234200 100644 --- a/extensions/sql-database-projects/src/test/baselines/baselines.ts +++ b/extensions/sql-database-projects/src/test/baselines/baselines.ts @@ -20,6 +20,7 @@ export let publishProfileIntegratedSecurityBaseline: string; export let publishProfileSqlLoginBaseline: string; export let openProjectWithProjectReferencesBaseline: string; export let openSqlProjectWithPrePostDeploymentError: string; +export let openSqlProjectWithAdditionalSqlCmdVariablesBaseline: string; const baselineFolderPath = __dirname; @@ -37,6 +38,7 @@ export async function loadBaselines() { publishProfileSqlLoginBaseline = await loadBaseline(baselineFolderPath, 'publishProfileSqlLoginBaseline.publish.xml'); openProjectWithProjectReferencesBaseline = await loadBaseline(baselineFolderPath, 'openSqlProjectWithProjectReferenceBaseline.xml'); openSqlProjectWithPrePostDeploymentError = await loadBaseline(baselineFolderPath, 'openSqlProjectWithPrePostDeploymentError.xml'); + openSqlProjectWithAdditionalSqlCmdVariablesBaseline = await loadBaseline(baselineFolderPath, 'openSqlProjectWithAdditionalSqlCmdVariablesBaseline.xml'); } async function loadBaseline(baselineFolderPath: string, fileName: string): Promise { diff --git a/extensions/sql-database-projects/src/test/baselines/openSqlProjectWithAdditionalSqlCmdVariablesBaseline.xml b/extensions/sql-database-projects/src/test/baselines/openSqlProjectWithAdditionalSqlCmdVariablesBaseline.xml new file mode 100644 index 0000000000..edf5c08e40 --- /dev/null +++ b/extensions/sql-database-projects/src/test/baselines/openSqlProjectWithAdditionalSqlCmdVariablesBaseline.xml @@ -0,0 +1,112 @@ + + + + Debug + AnyCPU + TestProjectName + 2.0 + 4.1 + {BA5EBA11-C0DE-5EA7-ACED-BABB1E70A575} + Microsoft.Data.Tools.Schema.Sql.Sql130DatabaseSchemaProvider + Database + + + TestProjectName + TestProjectName + 1033, CI + BySchemaAndSchemaType + True + v4.5 + CS + Properties + False + True + True + + + bin\Release\ + $(MSBuildProjectName).sql + False + pdbonly + true + false + true + prompt + 4 + + + bin\Debug\ + $(MSBuildProjectName).sql + false + true + full + false + true + true + prompt + 4 + + + 11.0 + + True + 11.0 + + + + + + + + + + + + + + + + + + + + + + + + + + MyBackupDatabase + $(SqlCmdVar__2) + + + TestDb + $(SqlCmdVar__3) + + + NewProdName + $(SqlCmdVar__4) + + + + + False + master + + + False + master + + + + + + + + + + + + + + diff --git a/extensions/sql-database-projects/src/test/project.test.ts b/extensions/sql-database-projects/src/test/project.test.ts index 3e6b479c89..2c35877810 100644 --- a/extensions/sql-database-projects/src/test/project.test.ts +++ b/extensions/sql-database-projects/src/test/project.test.ts @@ -291,6 +291,31 @@ describe('Project: sqlproj content operations', function (): void { }); }); +describe('Project: add SQLCMD Variables', function (): void { + before(async function (): Promise { + await baselines.loadBaselines(); + }); + + it('Should update .sqlproj with new sqlcmd variables', async function (): Promise { + projFilePath = await testUtils.createTestSqlProjFile(baselines.openProjectFileBaseline); + const project = await Project.openProject(projFilePath); + should(Object.keys(project.sqlCmdVariables).length).equal(2); + + // add a new variable + await project.addSqlCmdVariable('TestDatabaseName', 'TestDb'); + + // add a variable with the same name as an existing sqlcmd variable and the old entry should be replaced with the new one + await project.addSqlCmdVariable('ProdDatabaseName', 'NewProdName'); + + should(Object.keys(project.sqlCmdVariables).length).equal(3); + should(project.sqlCmdVariables['TestDatabaseName']).equal('TestDb'); + should(project.sqlCmdVariables['ProdDatabaseName']).equal('NewProdName', 'ProdDatabaseName value should have been updated to the new value'); + + const projFileText = (await fs.readFile(projFilePath)).toString(); + should(projFileText).equal(baselines.openSqlProjectWithAdditionalSqlCmdVariablesBaseline.trim()); + }); +}); + describe('Project: round trip updates', function (): void { before(async function (): Promise { await baselines.loadBaselines(); diff --git a/extensions/sql-database-projects/src/test/projectController.test.ts b/extensions/sql-database-projects/src/test/projectController.test.ts index cde0e1d310..a04dff9d89 100644 --- a/extensions/sql-database-projects/src/test/projectController.test.ts +++ b/extensions/sql-database-projects/src/test/projectController.test.ts @@ -19,7 +19,7 @@ import { SqlDatabaseProjectTreeViewProvider } from '../controllers/databaseProje import { ProjectsController } from '../controllers/projectController'; import { promises as fs } from 'fs'; import { createContext, TestContext, mockDacFxResult } from './testContext'; -import { Project, ProjectEntry, reservedProjectFolders, SystemDatabase } from '../models/project'; +import { Project, reservedProjectFolders, SystemDatabase, FileProjectEntry } from '../models/project'; import { PublishDatabaseDialog } from '../dialogs/publishDatabaseDialog'; import { IPublishSettings, IGenerateScriptSettings } from '../models/IPublishSettings'; import { exists } from '../common/utils'; @@ -584,7 +584,7 @@ describe.skip('ProjectsController: round trip feature with SSDT', function (): v }); -async function setupDeleteExcludeTest(proj: Project): Promise<[ProjectEntry, ProjectRootTreeItem]> { +async function setupDeleteExcludeTest(proj: Project): Promise<[FileProjectEntry, ProjectRootTreeItem]> { await proj.addFolderItem('UpperFolder'); await proj.addFolderItem('UpperFolder/LowerFolder'); const scriptEntry = await proj.addScriptItem('UpperFolder/LowerFolder/someScript.sql', 'not a real script'); diff --git a/extensions/sql-database-projects/src/test/projectTree.test.ts b/extensions/sql-database-projects/src/test/projectTree.test.ts index 9c61d464d1..33d6f19e98 100644 --- a/extensions/sql-database-projects/src/test/projectTree.test.ts +++ b/extensions/sql-database-projects/src/test/projectTree.test.ts @@ -52,19 +52,19 @@ describe.skip('Project Tree tests', function (): void { // nested entries before explicit top-level folder entry // also, ordering of files/folders at all levels - proj.files.push(proj.createProjectEntry(path.join('someFolder', 'bNestedTest.sql'), EntryType.File)); - proj.files.push(proj.createProjectEntry(path.join('someFolder', 'bNestedFolder'), EntryType.Folder)); - proj.files.push(proj.createProjectEntry(path.join('someFolder', 'aNestedTest.sql'), EntryType.File)); - proj.files.push(proj.createProjectEntry(path.join('someFolder', 'aNestedFolder'), EntryType.Folder)); - proj.files.push(proj.createProjectEntry('someFolder', EntryType.Folder)); + proj.files.push(proj.createFileProjectEntry(path.join('someFolder', 'bNestedTest.sql'), EntryType.File)); + proj.files.push(proj.createFileProjectEntry(path.join('someFolder', 'bNestedFolder'), EntryType.Folder)); + proj.files.push(proj.createFileProjectEntry(path.join('someFolder', 'aNestedTest.sql'), EntryType.File)); + proj.files.push(proj.createFileProjectEntry(path.join('someFolder', 'aNestedFolder'), EntryType.Folder)); + proj.files.push(proj.createFileProjectEntry('someFolder', EntryType.Folder)); // duplicate files - proj.files.push(proj.createProjectEntry('duplicate.sql', EntryType.File)); - proj.files.push(proj.createProjectEntry('duplicate.sql', EntryType.File)); + proj.files.push(proj.createFileProjectEntry('duplicate.sql', EntryType.File)); + proj.files.push(proj.createFileProjectEntry('duplicate.sql', EntryType.File)); // duplicate folders - proj.files.push(proj.createProjectEntry('duplicateFolder', EntryType.Folder)); - proj.files.push(proj.createProjectEntry('duplicateFolder', EntryType.Folder)); + proj.files.push(proj.createFileProjectEntry('duplicateFolder', EntryType.Folder)); + proj.files.push(proj.createFileProjectEntry('duplicateFolder', EntryType.Folder)); const tree = new ProjectRootTreeItem(proj); should(tree.children.map(x => x.uri.path)).deepEqual([ @@ -100,9 +100,9 @@ describe.skip('Project Tree tests', function (): void { // nested entries before explicit top-level folder entry // also, ordering of files/folders at all levels - proj.files.push(proj.createProjectEntry('someFolder1\\MyNestedFolder1\\MyFile1.sql', EntryType.File)); - proj.files.push(proj.createProjectEntry('someFolder1\\MyNestedFolder2', EntryType.Folder)); - proj.files.push(proj.createProjectEntry('someFolder1\\MyFile2.sql', EntryType.File)); + proj.files.push(proj.createFileProjectEntry('someFolder1\\MyNestedFolder1\\MyFile1.sql', EntryType.File)); + proj.files.push(proj.createFileProjectEntry('someFolder1\\MyNestedFolder2', EntryType.Folder)); + proj.files.push(proj.createFileProjectEntry('someFolder1\\MyFile2.sql', EntryType.File)); const tree = new ProjectRootTreeItem(proj); should(tree.children.map(x => x.uri.path)).deepEqual([ @@ -123,9 +123,9 @@ describe.skip('Project Tree tests', function (): void { // nested entries before explicit top-level folder entry // also, ordering of files/folders at all levels - proj.files.push(proj.createProjectEntry('..\\someFolder1\\MyNestedFolder1\\MyFile1.sql', EntryType.File)); - proj.files.push(proj.createProjectEntry('..\\..\\someFolder2\\MyFile2.sql', EntryType.File)); - proj.files.push(proj.createProjectEntry('..\\..\\someFolder3', EntryType.Folder)); // folder should not be counted (same as SSDT) + proj.files.push(proj.createFileProjectEntry('..\\someFolder1\\MyNestedFolder1\\MyFile1.sql', EntryType.File)); + proj.files.push(proj.createFileProjectEntry('..\\..\\someFolder2\\MyFile2.sql', EntryType.File)); + proj.files.push(proj.createFileProjectEntry('..\\..\\someFolder3', EntryType.Folder)); // folder should not be counted (same as SSDT) const tree = new ProjectRootTreeItem(proj); should(tree.children.map(x => x.uri.path)).deepEqual([