mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Drag and drop support for sql projects tree (#21956)
* Drag and drop working * update comment * move to projectController * remove registerTreeDataProvider * add tests * fix dragging to project root * cleanup * addressing comments
This commit is contained in:
@@ -21,6 +21,8 @@ export const noPreviousData = (tableName: string): string => { return localize('
|
|||||||
export const gitCloneMessage = (url: string): string => { return localize('gitCloneMessage', "Cloning git repository '{0}'...", url); };
|
export const gitCloneMessage = (url: string): string => { return localize('gitCloneMessage', "Cloning git repository '{0}'...", url); };
|
||||||
export const gitCloneError = localize('gitCloneError', "Error during git clone. View git output for more details");
|
export const gitCloneError = localize('gitCloneError', "Error during git clone. View git output for more details");
|
||||||
export const openedProjectsUndefinedAfterRefresh = localize('openedProjectsUndefinedAfterRefresh', "List of opened projects should not be undefined after refresh from disk.");
|
export const openedProjectsUndefinedAfterRefresh = localize('openedProjectsUndefinedAfterRefresh', "List of opened projects should not be undefined after refresh from disk.");
|
||||||
|
export const dragAndDropNotSupported = localize('dragAndDropNotSupported', "This project type does not support drag and drop.");
|
||||||
|
export const onlyMovingOneFileIsSupported = localize('onlyMovingOneFileIsSupported', "Only moving one file at a time is supported.");
|
||||||
|
|
||||||
// UI
|
// UI
|
||||||
export const OkButtonText = localize('dataworkspace.ok', "OK");
|
export const OkButtonText = localize('dataworkspace.ok', "OK");
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { IWorkspaceService } from './interfaces';
|
import { IWorkspaceService } from './interfaces';
|
||||||
import { ProjectsFailedToLoad, UnknownProjectsError } from './constants';
|
import { dragAndDropNotSupported, onlyMovingOneFileIsSupported, ProjectsFailedToLoad, UnknownProjectsError } from './constants';
|
||||||
import { WorkspaceTreeItem } from 'dataworkspace';
|
import { WorkspaceTreeItem } from 'dataworkspace';
|
||||||
import { TelemetryReporter } from './telemetry';
|
import { TelemetryReporter } from './telemetry';
|
||||||
import Logger from './logger';
|
import Logger from './logger';
|
||||||
@@ -14,11 +14,16 @@ import Logger from './logger';
|
|||||||
/**
|
/**
|
||||||
* Tree data provider for the workspace main view
|
* Tree data provider for the workspace main view
|
||||||
*/
|
*/
|
||||||
export class WorkspaceTreeDataProvider implements vscode.TreeDataProvider<WorkspaceTreeItem>{
|
export class WorkspaceTreeDataProvider implements vscode.TreeDataProvider<WorkspaceTreeItem>, vscode.TreeDragAndDropController<WorkspaceTreeItem> {
|
||||||
|
dropMimeTypes = ['application/vnd.code.tree.WorkspaceTreeDataProvider'];
|
||||||
|
dragMimeTypes = []; // The recommended mime type of the tree (`application/vnd.code.tree.WorkspaceTreeDataProvider`) is automatically added.
|
||||||
|
|
||||||
constructor(private _workspaceService: IWorkspaceService) {
|
constructor(private _workspaceService: IWorkspaceService) {
|
||||||
this._workspaceService.onDidWorkspaceProjectsChange(() => {
|
this._workspaceService.onDidWorkspaceProjectsChange(() => {
|
||||||
return this.refresh();
|
return this.refresh();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
vscode.window.createTreeView('dataworkspace.views.main', { canSelectMany: false, treeDataProvider: this, dragAndDropController: this });
|
||||||
}
|
}
|
||||||
|
|
||||||
private _onDidChangeTreeData: vscode.EventEmitter<void | WorkspaceTreeItem | null | undefined> | undefined = new vscode.EventEmitter<WorkspaceTreeItem | undefined | void>();
|
private _onDidChangeTreeData: vscode.EventEmitter<void | WorkspaceTreeItem | null | undefined> | undefined = new vscode.EventEmitter<WorkspaceTreeItem | undefined | void>();
|
||||||
@@ -108,4 +113,42 @@ export class WorkspaceTreeDataProvider implements vscode.TreeDataProvider<Worksp
|
|||||||
|
|
||||||
typeMetric[ext]++;
|
typeMetric[ext]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleDrag(treeItems: readonly WorkspaceTreeItem[], dataTransfer: vscode.DataTransfer): void | Thenable<void> {
|
||||||
|
dataTransfer.set('application/vnd.code.tree.WorkspaceTreeDataProvider', new vscode.DataTransferItem(treeItems.map(t => t.element)));
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleDrop(target: WorkspaceTreeItem | undefined, sources: vscode.DataTransfer): Promise<void> {
|
||||||
|
if (!target) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const transferItem = sources.get('application/vnd.code.tree.WorkspaceTreeDataProvider');
|
||||||
|
|
||||||
|
// Only support moving one file at a time
|
||||||
|
// canSelectMany is set to false for the WorkspaceTreeDataProvider, so this condition should never be true
|
||||||
|
if (transferItem?.value.length > 1) {
|
||||||
|
void vscode.window.showErrorMessage(onlyMovingOneFileIsSupported);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const projectUri = transferItem?.value[0].projectFileUri;
|
||||||
|
if (!projectUri) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const projectProvider = await this._workspaceService.getProjectProvider(projectUri);
|
||||||
|
if (!projectProvider) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!projectProvider?.supportsDragAndDrop || !projectProvider.moveFile) {
|
||||||
|
void vscode.window.showErrorMessage(dragAndDropNotSupported);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the file
|
||||||
|
await projectProvider!.moveFile(projectUri, transferItem?.value[0], target);
|
||||||
|
void this.refresh();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
13
extensions/data-workspace/src/dataworkspace.d.ts
vendored
13
extensions/data-workspace/src/dataworkspace.d.ts
vendored
@@ -121,6 +121,19 @@ declare module 'dataworkspace' {
|
|||||||
* Gets the project image to be used as background in dashboard container
|
* Gets the project image to be used as background in dashboard container
|
||||||
*/
|
*/
|
||||||
readonly image?: azdata.ThemedIconPath;
|
readonly image?: azdata.ThemedIconPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not the tree data provider supports drag and drop
|
||||||
|
*/
|
||||||
|
readonly supportsDragAndDrop?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves a file from the source to target location. Must be implemented if supportsDragAndDrop is true
|
||||||
|
* @param projectUri
|
||||||
|
* @param source
|
||||||
|
* @param target
|
||||||
|
*/
|
||||||
|
moveFile?(projectUri: vscode.Uri, source: any, target: WorkspaceTreeItem): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -42,10 +42,6 @@ export async function activate(context: vscode.ExtensionContext): Promise<IExten
|
|||||||
const dataWorkspaceExtension = new DataWorkspaceExtension(workspaceService);
|
const dataWorkspaceExtension = new DataWorkspaceExtension(workspaceService);
|
||||||
Logger.log(`DataWorkspaceExtension constructor took ${new Date().getTime() - dataWorkspaceExtensionStartTime}ms`);
|
Logger.log(`DataWorkspaceExtension constructor took ${new Date().getTime() - dataWorkspaceExtensionStartTime}ms`);
|
||||||
|
|
||||||
const registerTreeDataProvidertartTime = new Date().getTime();
|
|
||||||
context.subscriptions.push(vscode.window.registerTreeDataProvider('dataworkspace.views.main', workspaceTreeDataProvider));
|
|
||||||
Logger.log(`registerTreeDataProvider took ${new Date().getTime() - registerTreeDataProvidertartTime}ms`);
|
|
||||||
|
|
||||||
const settingProjectProviderContextStartTime = new Date().getTime();
|
const settingProjectProviderContextStartTime = new Date().getTime();
|
||||||
context.subscriptions.push(vscode.extensions.onDidChange(() => {
|
context.subscriptions.push(vscode.extensions.onDidChange(() => {
|
||||||
setProjectProviderContextValue(workspaceService);
|
setProjectProviderContextValue(workspaceService);
|
||||||
@@ -91,7 +87,7 @@ export async function activate(context: vscode.ExtensionContext): Promise<IExten
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
context.subscriptions.push(vscode.commands.registerCommand('projects.removeProject', async (treeItem: WorkspaceTreeItem) => {
|
context.subscriptions.push(vscode.commands.registerCommand('projects.removeProject', async (treeItem: WorkspaceTreeItem) => {
|
||||||
await workspaceService.removeProject(vscode.Uri.file(treeItem.element.project.projectFilePath));
|
await workspaceService.removeProject(treeItem.element.projectFileUri);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
context.subscriptions.push(vscode.commands.registerCommand('projects.manageProject', async (treeItem: WorkspaceTreeItem) => {
|
context.subscriptions.push(vscode.commands.registerCommand('projects.manageProject', async (treeItem: WorkspaceTreeItem) => {
|
||||||
|
|||||||
@@ -652,3 +652,10 @@ export function downloadingFromTo(from: string, to: string) { return localize('d
|
|||||||
export function extractingDacFxDlls(location: string) { return localize('extractingDacFxDlls', "Extracting DacFx build DLLs to {0}", location); }
|
export function extractingDacFxDlls(location: string) { return localize('extractingDacFxDlls', "Extracting DacFx build DLLs to {0}", location); }
|
||||||
export function errorDownloading(url: string, error: string) { return localize('errorDownloading', "Error downloading {0}. Error: {1}", url, error); }
|
export function errorDownloading(url: string, error: string) { return localize('errorDownloading', "Error downloading {0}. Error: {1}", url, error); }
|
||||||
export function errorExtracting(path: string, error: string) { return localize('errorExtracting', "Error extracting files from {0}. Error: {1}", path, error); }
|
export function errorExtracting(path: string, error: string) { return localize('errorExtracting', "Error extracting files from {0}. Error: {1}", path, error); }
|
||||||
|
|
||||||
|
// move
|
||||||
|
export const onlyMoveSqlFilesSupported = localize('onlyMoveSqlFilesSupported', "Only moving .sql files is supported");
|
||||||
|
export const movingFilesBetweenProjectsNotSupported = localize('movingFilesBetweenProjectsNotSupported', "Moving files between projects is not supported");
|
||||||
|
export function errorMovingFile(source: string, destination: string, error: string) { return localize('errorMovingFile', "Error when moving file from {0} to {1}. Error: {2}", source, destination, error); }
|
||||||
|
export function moveConfirmationPrompt(source: string, destination: string) { return localize('moveConfirmationPrompt', "Are you sure you want to move {0} to {1}?", source, destination); }
|
||||||
|
export const move = localize('Move', "Move");
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import * as vscode from 'vscode';
|
|||||||
import type * as azdataType from 'azdata';
|
import type * as azdataType from 'azdata';
|
||||||
import * as dataworkspace from 'dataworkspace';
|
import * as dataworkspace from 'dataworkspace';
|
||||||
import type * as mssqlVscode from 'vscode-mssql';
|
import type * as mssqlVscode from 'vscode-mssql';
|
||||||
|
import * as fse from 'fs-extra';
|
||||||
|
|
||||||
import { promises as fs } from 'fs';
|
import { promises as fs } from 'fs';
|
||||||
import { PublishDatabaseDialog } from '../dialogs/publishDatabaseDialog';
|
import { PublishDatabaseDialog } from '../dialogs/publishDatabaseDialog';
|
||||||
@@ -1824,6 +1825,68 @@ export class ProjectsController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move a file in the project tree
|
||||||
|
* @param projectUri URI of the project
|
||||||
|
* @param source
|
||||||
|
* @param target
|
||||||
|
*/
|
||||||
|
public async moveFile(projectUri: vscode.Uri, source: any, target: dataworkspace.WorkspaceTreeItem): Promise<void> {
|
||||||
|
const sourceFileNode = source as FileNode;
|
||||||
|
|
||||||
|
// only moving files is supported
|
||||||
|
if (!sourceFileNode || !(sourceFileNode instanceof FileNode)) {
|
||||||
|
void vscode.window.showErrorMessage(constants.onlyMoveSqlFilesSupported);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Moving files to the SQLCMD variables and Database references folders isn't allowed
|
||||||
|
// TODO: should there be an error displayed if a file attempting to move a file to sqlcmd variables or database references? Or just silently fail and do nothing?
|
||||||
|
if (!target.element.fileSystemUri) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: handle moving between different projects
|
||||||
|
if (projectUri.fsPath !== target.element.projectFileUri.fsPath) {
|
||||||
|
void vscode.window.showErrorMessage(constants.movingFilesBetweenProjectsNotSupported);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the new file path
|
||||||
|
let folderPath;
|
||||||
|
// target is the root of project, which is the .sqlproj
|
||||||
|
if (target.element.projectFileUri.fsPath === target.element.fileSystemUri.fsPath) {
|
||||||
|
folderPath = path.dirname(target.element.projectFileUri.fsPath!);
|
||||||
|
} else {
|
||||||
|
// target is another file or folder
|
||||||
|
folderPath = target.element.fileSystemUri.fsPath.endsWith(constants.sqlFileExtension) ? path.dirname(target.element.fileSystemUri.fsPath) : target.element.fileSystemUri.fsPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newPath = path.join(folderPath!, sourceFileNode.friendlyName);
|
||||||
|
|
||||||
|
// don't do anything if the path is the same
|
||||||
|
if (newPath === sourceFileNode.fileSystemUri.fsPath) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await vscode.window.showWarningMessage(constants.moveConfirmationPrompt(path.basename(sourceFileNode.fileSystemUri.fsPath), path.basename(folderPath)), { modal: true }, constants.move)
|
||||||
|
if (result !== constants.move) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the file
|
||||||
|
try {
|
||||||
|
const project = await Project.openProject(projectUri.fsPath);
|
||||||
|
|
||||||
|
// TODO: swap out with DacFx projects apis - currently moving pre/post deploy scripts don't work, but they should work after the swap
|
||||||
|
await fse.move(sourceFileNode.fileSystemUri.fsPath, newPath!);
|
||||||
|
await project.exclude(project.files.find(f => f.fsUri.fsPath === sourceFileNode.fileSystemUri.fsPath)!);
|
||||||
|
await project.addExistingItem(newPath!);
|
||||||
|
} catch (e) {
|
||||||
|
void vscode.window.showErrorMessage(constants.errorMovingFile(sourceFileNode.fileSystemUri.fsPath, newPath, utils.getErrorMessage(e)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface NewProjectParams {
|
export interface NewProjectParams {
|
||||||
|
|||||||
@@ -22,6 +22,18 @@ export class SqlDatabaseProjectProvider implements dataworkspace.IProjectProvide
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
supportsDragAndDrop: boolean = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move a file in the project tree
|
||||||
|
* @param projectUri
|
||||||
|
* @param source
|
||||||
|
* @param target
|
||||||
|
*/
|
||||||
|
public async moveFile(projectUri: vscode.Uri, source: any, target: dataworkspace.WorkspaceTreeItem): Promise<void> {
|
||||||
|
return this.projectController.moveFile(projectUri, source, target);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the project tree data provider
|
* Gets the project tree data provider
|
||||||
* @param projectFilePath The project file Uri
|
* @param projectFilePath The project file Uri
|
||||||
|
|||||||
@@ -810,6 +810,111 @@ describe('ProjectsController', function (): void {
|
|||||||
should(project.files.filter(f => f.type === EntryType.Folder).length).equal(expectedFolders.length, 'Unexpected number of folders in project');
|
should(project.files.filter(f => f.type === EntryType.Folder).length).equal(expectedFolders.length, 'Unexpected number of folders in project');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Move file', function (): void {
|
||||||
|
it('Should move a file to another folder', async function (): Promise<void> {
|
||||||
|
const spy = sinon.spy(vscode.window, 'showErrorMessage');
|
||||||
|
sinon.stub(vscode.window, 'showWarningMessage').returns(<any>Promise.resolve(constants.move));
|
||||||
|
|
||||||
|
let proj = await testUtils.createTestProject(baselines.openSdkStyleSqlProjectBaseline);
|
||||||
|
|
||||||
|
const projTreeRoot = await setupMoveTest(proj);
|
||||||
|
|
||||||
|
const projController = new ProjectsController(testContext.outputChannel);
|
||||||
|
|
||||||
|
// try to move a file from the root folder into the UpperFolder
|
||||||
|
const sqlFileNode = projTreeRoot.children.find(x => x.friendlyName === 'script1.sql');
|
||||||
|
const folderWorkspaceTreeItem = createWorkspaceTreeItem(projTreeRoot.children.find(x => x.friendlyName === 'UpperFolder')!);
|
||||||
|
await projController.moveFile(vscode.Uri.file(proj.projectFilePath), sqlFileNode, folderWorkspaceTreeItem);
|
||||||
|
|
||||||
|
should(spy.notCalled).be.true('showErrorMessage should not have been called');
|
||||||
|
|
||||||
|
// reload project and verify file was moved
|
||||||
|
proj = await Project.openProject(proj.projectFilePath);
|
||||||
|
should(proj.files.find(f => f.relativePath === 'UpperFolder\\script1.sql') !== undefined).be.true('The file path should have been updated');
|
||||||
|
should(await utils.exists(path.join(proj.projectFolderPath, 'UpperFolder', 'script1.sql'))).be.true('The moved file should exist');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should not allow moving a file to Database References or SQLCMD folder', async function (): Promise<void> {
|
||||||
|
const spy = sinon.spy(vscode.window, 'showErrorMessage');
|
||||||
|
sinon.stub(vscode.window, 'showWarningMessage').returns(<any>Promise.resolve(constants.move));
|
||||||
|
|
||||||
|
let proj = await testUtils.createTestProject(baselines.openSdkStyleSqlProjectBaseline);
|
||||||
|
const projTreeRoot = await setupMoveTest(proj);
|
||||||
|
const projController = new ProjectsController(testContext.outputChannel);
|
||||||
|
|
||||||
|
const foldersToTest = ['SQLCMD Variables', 'Database References'];
|
||||||
|
|
||||||
|
for (const folder of foldersToTest) {
|
||||||
|
// try to move a file from the root folder into the UpperFolder
|
||||||
|
const sqlFileNode = projTreeRoot.children.find(x => x.friendlyName === 'script1.sql');
|
||||||
|
const sqlCmdVariablesWorkspaceTreeItem = createWorkspaceTreeItem(projTreeRoot.children.find(x => x.friendlyName === folder)!);
|
||||||
|
await projController.moveFile(vscode.Uri.file(proj.projectFilePath), sqlFileNode, sqlCmdVariablesWorkspaceTreeItem);
|
||||||
|
|
||||||
|
// reload project and verify file was not moved
|
||||||
|
proj = await Project.openProject(proj.projectFilePath);
|
||||||
|
should(proj.files.find(f => f.relativePath === 'script1.sql') !== undefined).be.true(`The file path should not have been updated when trying to move script1.sql to ${folder}`);
|
||||||
|
should(spy.notCalled).be.true('showErrorMessage should not have been called.');
|
||||||
|
spy.restore();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should only allow moving files', async function (): Promise<void> {
|
||||||
|
const spy = sinon.spy(vscode.window, 'showErrorMessage');
|
||||||
|
let proj = await testUtils.createTestProject(baselines.openSdkStyleSqlProjectBaseline);
|
||||||
|
const projTreeRoot = await setupMoveTest(proj);
|
||||||
|
const projController = new ProjectsController(testContext.outputChannel);
|
||||||
|
|
||||||
|
// try to move sqlcmd variable
|
||||||
|
const sqlcmdVarNode = projTreeRoot.children.find(x => x.friendlyName === 'SQLCMD Variables')!.children[0];
|
||||||
|
const projectRootWorkspaceTreeItem = createWorkspaceTreeItem(projTreeRoot);
|
||||||
|
await projController.moveFile(vscode.Uri.file(proj.projectFilePath), sqlcmdVarNode, projectRootWorkspaceTreeItem);
|
||||||
|
|
||||||
|
should(spy.calledOnce).be.true('showErrorMessage should have been called exactly once when trying to move a sqlcmd variable');
|
||||||
|
should(spy.calledWith(constants.onlyMoveSqlFilesSupported)).be.true(`showErrorMessage not called with expected message '${constants.onlyMoveSqlFilesSupported}' Actual '${spy.getCall(0).args[0]}'`);
|
||||||
|
spy.restore();
|
||||||
|
|
||||||
|
// try moving a database reference
|
||||||
|
const dbRefNode = projTreeRoot.children.find(x => x.friendlyName === 'Database References')!.children[0];
|
||||||
|
await projController.moveFile(vscode.Uri.file(proj.projectFilePath), dbRefNode, projectRootWorkspaceTreeItem);
|
||||||
|
|
||||||
|
should(spy.calledOnce).be.true('showErrorMessage should have been called exactly once when trying to move a database reference');
|
||||||
|
should(spy.calledWith(constants.onlyMoveSqlFilesSupported)).be.true(`showErrorMessage not called with expected message '${constants.onlyMoveSqlFilesSupported}' Actual '${spy.getCall(0).args[0]}'`);
|
||||||
|
spy.restore();
|
||||||
|
|
||||||
|
// try moving a folder
|
||||||
|
const folderNode = projTreeRoot.children.find(x => x.friendlyName === 'UpperFolder');
|
||||||
|
await projController.moveFile(vscode.Uri.file(proj.projectFilePath), folderNode, projectRootWorkspaceTreeItem);
|
||||||
|
|
||||||
|
should(spy.calledOnce).be.true('showErrorMessage should have been called exactly once when trying to move a folder');
|
||||||
|
should(spy.calledWith(constants.onlyMoveSqlFilesSupported)).be.true(`showErrorMessage not called with expected message '${constants.onlyMoveSqlFilesSupported}' Actual '${spy.getCall(0).args[0]}'`);
|
||||||
|
spy.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should not allow moving files between projects', async function (): Promise<void> {
|
||||||
|
const spy = sinon.spy(vscode.window, 'showErrorMessage');
|
||||||
|
sinon.stub(vscode.window, 'showWarningMessage').returns(<any>Promise.resolve(constants.move));
|
||||||
|
|
||||||
|
let proj1 = await testUtils.createTestProject(baselines.openSdkStyleSqlProjectBaseline);
|
||||||
|
let proj2 = await testUtils.createTestProject(baselines.openSdkStyleSqlProjectBaseline);
|
||||||
|
|
||||||
|
const projTreeRoot1 = await setupMoveTest(proj1);
|
||||||
|
const projTreeRoot2 = await setupMoveTest(proj2);
|
||||||
|
const projController = new ProjectsController(testContext.outputChannel);
|
||||||
|
|
||||||
|
// try to move a file from the root folder of proj1 to the UpperFolder of proj2
|
||||||
|
const proj1SqlFileNode = projTreeRoot1.children.find(x => x.friendlyName === 'script1.sql');
|
||||||
|
const proj2FolderWorkspaceTreeItem = createWorkspaceTreeItem(projTreeRoot2.children.find(x => x.friendlyName === 'UpperFolder')!);
|
||||||
|
await projController.moveFile(vscode.Uri.file(proj1.projectFilePath), proj1SqlFileNode, proj2FolderWorkspaceTreeItem);
|
||||||
|
|
||||||
|
should(spy.called).be.true('showErrorMessage should have been called');
|
||||||
|
should(spy.calledWith(constants.movingFilesBetweenProjectsNotSupported)).be.true(`showErrorMessage not called with expected message '${constants.movingFilesBetweenProjectsNotSupported}' Actual '${spy.getCall(0).args[0]}'`);
|
||||||
|
|
||||||
|
// verify script1.sql was not moved
|
||||||
|
proj1 = await Project.openProject(proj1.projectFilePath);
|
||||||
|
should(proj1.files.find(f => f.relativePath === 'script1.sql') !== undefined).be.true(`The file path should not have been updated when trying to move script1.sql to proj2`);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
async function setupDeleteExcludeTest(proj: Project): Promise<[FileProjectEntry, ProjectRootTreeItem, FileProjectEntry, FileProjectEntry, FileProjectEntry]> {
|
async function setupDeleteExcludeTest(proj: Project): Promise<[FileProjectEntry, ProjectRootTreeItem, FileProjectEntry, FileProjectEntry, FileProjectEntry]> {
|
||||||
@@ -836,6 +941,18 @@ async function setupDeleteExcludeTest(proj: Project): Promise<[FileProjectEntry,
|
|||||||
return [scriptEntry, projTreeRoot, preDeployEntry, postDeployEntry, noneEntry];
|
return [scriptEntry, projTreeRoot, preDeployEntry, postDeployEntry, noneEntry];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function setupMoveTest(proj: Project): Promise<ProjectRootTreeItem> {
|
||||||
|
await proj.addFolderItem('UpperFolder');
|
||||||
|
await proj.addFolderItem('UpperFolder/LowerFolder');
|
||||||
|
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');
|
||||||
|
await proj.addScriptItem('script1.sql', 'Also not a real script');
|
||||||
|
|
||||||
|
const projTreeRoot = new ProjectRootTreeItem(proj);
|
||||||
|
return projTreeRoot;
|
||||||
|
}
|
||||||
|
|
||||||
function createWorkspaceTreeItem(node: BaseProjectTreeItem): dataworkspace.WorkspaceTreeItem {
|
function createWorkspaceTreeItem(node: BaseProjectTreeItem): dataworkspace.WorkspaceTreeItem {
|
||||||
return {
|
return {
|
||||||
element: node,
|
element: node,
|
||||||
|
|||||||
Reference in New Issue
Block a user