mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-18 01:25:37 -05:00
Feature/outer paths for project (#11445)
* allow relative paths in project file outside of project folder * Adding some tests * Adding error string to loc strings * Fixed test * fix error message * PR comments and some more fixes
This commit is contained in:
@@ -68,6 +68,7 @@
|
||||
<Build Include="Tables\Users.sql" />
|
||||
<Build Include="Tables\Action History.sql" />
|
||||
<Build Include="Views\Maintenance\Database Performance.sql" />
|
||||
<Build Include="..\Test\Test.sql" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Views\User" />
|
||||
|
||||
@@ -9,7 +9,7 @@ import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as vscode from 'vscode';
|
||||
import { NetCoreTool, DBProjectConfigurationKey, NetCoreInstallLocationKey, NextCoreNonWindowsDefaultPath } from '../tools/netcoreTool';
|
||||
import { getSafePath } from '../common/utils';
|
||||
import { getQuotedPath } from '../common/utils';
|
||||
import { isNullOrUndefined } from 'util';
|
||||
import { generateTestFolderPath } from './testUtils';
|
||||
|
||||
@@ -52,7 +52,7 @@ describe.skip('NetCoreTool: Net core tests', function (): void {
|
||||
const outputChannel = vscode.window.createOutputChannel('db project test');
|
||||
|
||||
try {
|
||||
await netcoreTool.runStreamedCommand('echo test > ' + getSafePath(dummyFile), outputChannel, undefined);
|
||||
await netcoreTool.runStreamedCommand('echo test > ' + getQuotedPath(dummyFile), outputChannel, undefined);
|
||||
const text = await fs.promises.readFile(dummyFile);
|
||||
should(text.toString().trim()).equal('test');
|
||||
}
|
||||
|
||||
@@ -29,11 +29,12 @@ describe('Project: sqlproj content operations', function (): void {
|
||||
const project: Project = await Project.openProject(projFilePath);
|
||||
|
||||
// Files and folders
|
||||
should(project.files.filter(f => f.type === EntryType.File).length).equal(4);
|
||||
should(project.files.filter(f => f.type === EntryType.File).length).equal(5);
|
||||
should(project.files.filter(f => f.type === EntryType.Folder).length).equal(4);
|
||||
|
||||
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
|
||||
should(project.files.find(f => f.type === EntryType.File && f.relativePath === '..\\Test\\Test.sql')).not.equal(undefined); // mixed ItemGroup file
|
||||
|
||||
// SqlCmdVariables
|
||||
should(Object.keys(project.sqlCmdVariables).length).equal(2);
|
||||
|
||||
@@ -24,7 +24,7 @@ import { PublishDatabaseDialog } from '../dialogs/publishDatabaseDialog';
|
||||
import { IPublishSettings, IGenerateScriptSettings } from '../models/IPublishSettings';
|
||||
import { exists } from '../common/utils';
|
||||
import { ProjectRootTreeItem } from '../models/tree/projectTreeItem';
|
||||
import { FolderNode } from '../models/tree/fileFolderTreeItem';
|
||||
import { FolderNode, FileNode } from '../models/tree/fileFolderTreeItem';
|
||||
import { BaseProjectTreeItem } from '../models/tree/baseTreeItem';
|
||||
|
||||
let testContext: TestContext;
|
||||
@@ -46,9 +46,12 @@ const mockConnectionProfile: azdata.IConnectionProfile = {
|
||||
options: undefined as any
|
||||
};
|
||||
|
||||
describe('ProjectsController', function (): void {
|
||||
before(async function (): Promise<void> {
|
||||
await templates.loadTemplates(path.join(__dirname, '..', '..', 'resources', 'templates'));
|
||||
await baselines.loadBaselines();
|
||||
});
|
||||
|
||||
|
||||
describe ('ProjectsController', function(): void {
|
||||
beforeEach(function (): void {
|
||||
testContext = createContext();
|
||||
});
|
||||
@@ -58,11 +61,6 @@ describe ('ProjectsController', function(): void {
|
||||
});
|
||||
|
||||
describe('project controller operations', function (): void {
|
||||
before(async function (): Promise<void> {
|
||||
await templates.loadTemplates(path.join(__dirname, '..', '..', 'resources', 'templates'));
|
||||
await baselines.loadBaselines();
|
||||
});
|
||||
|
||||
describe('Project file operations and prompting', function (): void {
|
||||
it('Should create new sqlproj file with correct values', async function (): Promise<void> {
|
||||
const projController = new ProjectsController(new SqlDatabaseProjectTreeViewProvider());
|
||||
@@ -85,7 +83,7 @@ describe ('ProjectsController', function(): void {
|
||||
|
||||
const project = await projController.openProject(vscode.Uri.file(sqlProjPath));
|
||||
|
||||
should(project.files.length).equal(8); // detailed sqlproj tests in their own test file
|
||||
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
|
||||
});
|
||||
|
||||
@@ -201,6 +199,7 @@ describe ('ProjectsController', function(): void {
|
||||
const projController = new ProjectsController(new SqlDatabaseProjectTreeViewProvider());
|
||||
|
||||
await projController.delete(projTreeRoot.children.find(x => x.friendlyName === 'UpperFolder')!.children[0] /* LowerFolder */);
|
||||
await projController.delete(projTreeRoot.children.find(x => x.friendlyName === 'anotherScript.sql')!);
|
||||
|
||||
proj = await Project.openProject(proj.projectFilePath); // reload edited sqlproj from disk
|
||||
|
||||
@@ -219,6 +218,7 @@ describe ('ProjectsController', function(): void {
|
||||
const projController = new ProjectsController(new SqlDatabaseProjectTreeViewProvider());
|
||||
|
||||
await projController.exclude(<FolderNode>projTreeRoot.children.find(x => x.friendlyName === 'UpperFolder')!.children[0] /* LowerFolder */);
|
||||
await projController.exclude(<FileNode>projTreeRoot.children.find(x => x.friendlyName === 'anotherScript.sql')!);
|
||||
|
||||
proj = await Project.openProject(proj.projectFilePath); // reload edited sqlproj from disk
|
||||
|
||||
@@ -447,11 +447,11 @@ describe ('ProjectsController', function(): void {
|
||||
|
||||
let result = await projController.getModelFromContext(undefined);
|
||||
|
||||
should(result).deepEqual({database: mockDbSelection, serverId: connectionId});
|
||||
should(result).deepEqual({ database: mockDbSelection, serverId: connectionId });
|
||||
|
||||
// test launch via Object Explorer context
|
||||
result = await projController.getModelFromContext(mockConnectionProfile);
|
||||
should(result).deepEqual({database: 'My Database', serverId: 'My Id'});
|
||||
should(result).deepEqual({ database: 'My Database', serverId: 'My Id' });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -575,12 +575,13 @@ async function setupDeleteExcludeTest(proj: Project): Promise<[ProjectEntry, Pro
|
||||
await proj.addFolderItem('UpperFolder/LowerFolder');
|
||||
const scriptEntry = await proj.addScriptItem('UpperFolder/LowerFolder/someScript.sql', 'not a real script');
|
||||
await proj.addScriptItem('UpperFolder/LowerFolder/someOtherScript.sql', 'Also not a real script');
|
||||
await proj.addScriptItem('../anotherScript.sql', 'Also not a real script');
|
||||
|
||||
const projTreeRoot = new ProjectRootTreeItem(proj);
|
||||
sinon.stub(vscode.window, 'showWarningMessage').returns(<any>Promise.resolve(constants.yesString));
|
||||
|
||||
// confirm setup
|
||||
should(proj.files.length).equal(4, 'number of file/folder entries');
|
||||
should(proj.files.length).equal(5, 'number of file/folder entries');
|
||||
should(path.parse(scriptEntry.fsUri.fsPath).base).equal('someScript.sql');
|
||||
should((await fs.readFile(scriptEntry.fsUri.fsPath)).toString()).equal('not a real script');
|
||||
|
||||
|
||||
@@ -116,4 +116,22 @@ describe.skip('Project Tree tests', function (): void {
|
||||
'MyNestedFolder2',
|
||||
'MyFile2.sql']);
|
||||
});
|
||||
|
||||
it('Should be able to parse and include relative paths outside project folder', function (): void {
|
||||
const root = os.platform() === 'win32' ? 'Z:\\Level1\\Level2\\' : '/Root/Level1/Level2';
|
||||
const proj = new Project(vscode.Uri.file(`${root}TestProj.sqlproj`).fsPath);
|
||||
|
||||
// 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)
|
||||
|
||||
const tree = new ProjectRootTreeItem(proj);
|
||||
should(tree.children.map(x => x.uri.path)).deepEqual([
|
||||
'/TestProj.sqlproj/Data Sources',
|
||||
'/TestProj.sqlproj/Database References',
|
||||
'/TestProj.sqlproj/MyFile1.sql',
|
||||
'/TestProj.sqlproj/MyFile2.sql']);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,10 +5,12 @@
|
||||
|
||||
import * as should from 'should';
|
||||
import * as path from 'path';
|
||||
import {createDummyFileStructure} from './testUtils';
|
||||
import { exists} from '../common/utils';
|
||||
import * as os from 'os';
|
||||
import { createDummyFileStructure } from './testUtils';
|
||||
import { exists, trimUri } from '../common/utils';
|
||||
import { Uri } from 'vscode';
|
||||
|
||||
describe('Tests to verify exists function', function (): void {
|
||||
describe('Tests to verify utils functions', function (): void {
|
||||
it('Should determine existence of files/folders', async () => {
|
||||
let testFolderPath = await createDummyFileStructure();
|
||||
|
||||
@@ -16,8 +18,25 @@ describe('Tests to verify exists function', function (): void {
|
||||
should(await exists(path.join(testFolderPath, 'file1.sql'))).equal(true);
|
||||
should(await exists(path.join(testFolderPath, 'folder2'))).equal(true);
|
||||
should(await exists(path.join(testFolderPath, 'folder4'))).equal(false);
|
||||
should(await exists(path.join(testFolderPath, 'folder2','file4.sql'))).equal(true);
|
||||
should(await exists(path.join(testFolderPath, 'folder4','file2.sql'))).equal(false);
|
||||
should(await exists(path.join(testFolderPath, 'folder2', 'file4.sql'))).equal(true);
|
||||
should(await exists(path.join(testFolderPath, 'folder4', 'file2.sql'))).equal(false);
|
||||
});
|
||||
|
||||
it('Should get correct relative paths of files/folders', async () => {
|
||||
const root = os.platform() === 'win32' ? 'Z:\\' : '/';
|
||||
let projectUri = Uri.file(path.join(root, 'project', 'folder', 'project.sqlproj'));
|
||||
let fileUri = Uri.file(path.join(root, 'project', 'folder', 'file.sql'));
|
||||
should(trimUri(projectUri, fileUri)).equal('file.sql');
|
||||
|
||||
fileUri = Uri.file(path.join(root, 'project', 'file.sql'));
|
||||
let urifile = trimUri(projectUri, fileUri);
|
||||
should(urifile).equal('../file.sql');
|
||||
|
||||
fileUri = Uri.file(path.join(root, 'project', 'forked', 'file.sql'));
|
||||
should(trimUri(projectUri, fileUri)).equal('../forked/file.sql');
|
||||
|
||||
fileUri = Uri.file(path.join(root, 'forked', 'from', 'top', 'file.sql'));
|
||||
should(trimUri(projectUri, fileUri)).equal('../../forked/from/top/file.sql');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user