Load all data workspace projects directly from workspace (#15921)

* Load all projects directly from workspace

* fixes

* Remove relativity and fix tests

* fix compile

* PR comments

* remove unused

* distro
This commit is contained in:
Charles Gagnon
2021-06-30 10:58:34 -07:00
committed by GitHub
parent 66c1fdc457
commit 7ce791d826
30 changed files with 124 additions and 1113 deletions

View File

@@ -1,66 +0,0 @@
/*---------------------------------------------------------------------------------------------
* 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 TypeMoq from 'typemoq';
import * as os from 'os';
import * as path from 'path';
import * as sinon from 'sinon';
import * as utils from '../../common/utils';
import * as constants from '../../common/constants';
import { NewProjectDialog } from '../../dialogs/newProjectDialog';
import { WorkspaceService } from '../../services/workspaceService';
import { testProjectType } from '../testUtils';
suite('DialogBase - workspace validation', function (): void {
// DialogBase is an abstract class, so we'll just use a NewProjectDialog to test the common base class functions
let dialog: NewProjectDialog;
this.beforeEach(async () => {
const workspaceServiceMock = TypeMoq.Mock.ofType<WorkspaceService>();
workspaceServiceMock.setup(x => x.getAllProjectTypes()).returns(() => Promise.resolve([testProjectType]));
dialog = new NewProjectDialog(workspaceServiceMock.object);
await dialog.open();
dialog.model.name = `TestProject_${new Date().getTime()}`;
dialog.model.location = os.tmpdir();
});
this.afterEach(() => {
sinon.restore();
});
test('Should validate new workspace location missing file extension', async function (): Promise<void> {
dialog.workspaceInputBox!.value = 'test';
await should(dialog.validateNewWorkspace(false)).be.rejectedWith(constants.WorkspaceFileInvalidError(dialog.workspaceInputBox!.value));
});
test('Should validate new workspace location with invalid location', async function (): Promise<void> {
// use invalid folder
dialog.workspaceInputBox!.value = 'invalidLocation/test.code-workspace';
await should(dialog.validateNewWorkspace(false)).be.rejectedWith(constants.WorkspaceParentDirectoryNotExistError(path.dirname(dialog.workspaceInputBox!.value)));
});
test('Should validate new workspace location that already exists', async function (): Promise<void> {
// use already existing workspace
const fileExistStub = sinon.stub(utils, 'fileExist');
fileExistStub.resolves(true);
const existingWorkspaceFilePath = path.join(os.tmpdir(), `${dialog.model.name}.code-workspace`);
dialog.workspaceInputBox!.value = existingWorkspaceFilePath;
await should(dialog.validateNewWorkspace(false)).be.rejectedWith(constants.WorkspaceFileAlreadyExistsError(existingWorkspaceFilePath));
});
test('Should validate new workspace location that is valid', async function (): Promise<void> {
// same folder as the project should be valid even if the project folder isn't created yet
dialog.workspaceInputBox!.value = path.join(dialog.model.location, dialog.model.name, 'test.code-workspace');
await should(dialog.validateNewWorkspace(true)).not.be.rejected();
// a workspace not in the same folder as the project should also be valid
dialog.workspaceInputBox!.value = path.join(os.tmpdir(), `TestWorkspace_${new Date().getTime()}.code-workspace`);
await should(dialog.validateNewWorkspace(false)).not.be.rejected();
});
});

View File

@@ -7,7 +7,6 @@ import * as should from 'should';
import * as TypeMoq from 'typemoq';
import * as os from 'os';
import * as path from 'path';
import * as vscode from 'vscode';
import * as sinon from 'sinon';
import { promises as fs } from 'fs';
import { NewProjectDialog } from '../../dialogs/newProjectDialog';
@@ -28,7 +27,6 @@ suite('New Project Dialog', function (): void {
dialog.model.name = 'TestProject';
dialog.model.location = '';
dialog.workspaceInputBox!.value = 'test.code-workspace';
should.equal(await dialog.validate(), false, 'Validation should fail because the parent directory does not exist');
// create a folder with the same name
@@ -41,24 +39,5 @@ suite('New Project Dialog', function (): void {
dialog.model.name = `TestProject_${new Date().getTime()}`;
should.equal(await dialog.validate(), true, 'Validation should pass because name is unique and parent directory exists');
});
test('Should validate workspace in onComplete', async function (): Promise<void> {
const workspaceServiceMock = TypeMoq.Mock.ofType<WorkspaceService>();
workspaceServiceMock.setup(x => x.validateWorkspace()).returns(() => Promise.resolve(true));
workspaceServiceMock.setup(x => x.getAllProjectTypes()).returns(() => Promise.resolve([testProjectType]));
const dialog = new NewProjectDialog(workspaceServiceMock.object);
await dialog.open();
dialog.model.name = 'TestProject';
dialog.model.location = '';
should.doesNotThrow(async () => await dialog.onComplete());
workspaceServiceMock.setup(x => x.validateWorkspace()).throws(new Error('test error'));
const spy = sinon.spy(vscode.window, 'showErrorMessage');
should.doesNotThrow(async () => await dialog.onComplete(), 'Error should be caught');
should(spy.calledOnce).be.true();
});
});

View File

@@ -12,23 +12,19 @@ import * as constants from '../../common/constants';
import * as utils from '../../common/utils';
import { WorkspaceService } from '../../services/workspaceService';
import { OpenExistingDialog } from '../../dialogs/openExistingDialog';
import { createProjectFile, generateUniqueProjectFilePath, generateUniqueWorkspaceFilePath, testProjectType } from '../testUtils';
import { createProjectFile, generateUniqueProjectFilePath, testProjectType } from '../testUtils';
suite('Open Existing Dialog', function (): void {
const mockExtensionContext = TypeMoq.Mock.ofType<vscode.ExtensionContext>();
this.afterEach(() => {
sinon.restore();
});
test('Should validate project file exists', async function (): Promise<void> {
const workspaceServiceMock = TypeMoq.Mock.ofType<WorkspaceService>();
const dialog = new OpenExistingDialog(workspaceServiceMock.object, mockExtensionContext.object);
const dialog = new OpenExistingDialog(workspaceServiceMock.object);
await dialog.open();
dialog.targetTypeRadioCardGroup?.updateProperty( 'selectedCardId', constants.Project);
dialog.filePathTextBox!.value = 'nonExistentProjectFile';
dialog.workspaceInputBox!.value = 'test.code-workspace';
const validateResult = await dialog.validate();
@@ -41,32 +37,12 @@ suite('Open Existing Dialog', function (): void {
should.equal(await dialog.validate(), true, `Validation should pass because project file exists, but failed with: ${dialog.dialogObject.message.text}`);
});
test('Should validate workspace file exists', async function (): Promise<void> {
const workspaceServiceMock = TypeMoq.Mock.ofType<WorkspaceService>();
const dialog = new OpenExistingDialog(workspaceServiceMock.object, mockExtensionContext.object);
await dialog.open();
dialog.targetTypeRadioCardGroup?.updateProperty( 'selectedCardId', constants.Workspace);
dialog.filePathTextBox!.value = 'nonExistentWorkspaceFile';
const fileExistStub = sinon.stub(utils, 'fileExist').resolves(false);
const validateResult = await dialog.validate();
const msg = constants.FileNotExistError('workspace', 'nonExistentWorkspaceFile');
should.equal(dialog.dialogObject.message.text, msg);
should.equal(validateResult, false, 'Validation should fail because workspace file does not exist, but passed');
// validation should pass if workspace file exists
dialog.filePathTextBox!.value = generateUniqueWorkspaceFilePath();
fileExistStub.resolves(true);
should.equal(await dialog.validate(), true, `Validation should pass because workspace file exists, but failed with: ${dialog.dialogObject.message.text}`);
});
test('Should validate workspace git clone location', async function (): Promise<void> {
const workspaceServiceMock = TypeMoq.Mock.ofType<WorkspaceService>();
const dialog = new OpenExistingDialog(workspaceServiceMock.object, mockExtensionContext.object);
const dialog = new OpenExistingDialog(workspaceServiceMock.object);
await dialog.open();
dialog.targetTypeRadioCardGroup?.updateProperty( 'selectedCardId', constants.Workspace);
dialog.localRadioButton!.checked = false;
dialog.remoteGitRepoRadioButton!.checked = true;
dialog.localClonePathTextBox!.value = 'invalidLocation';
@@ -74,7 +50,7 @@ suite('Open Existing Dialog', function (): void {
const validateResult = await dialog.validate();
const msg = constants.CloneParentDirectoryNotExistError(dialog.localClonePathTextBox!.value);
should.equal(dialog.dialogObject.message.text, msg);
should.equal(dialog.dialogObject.message.text, msg, 'Dialog message should be correct');
should.equal(validateResult, false, 'Validation should fail because clone directory does not exist, but passed');
// validation should pass if directory exists
@@ -83,58 +59,22 @@ suite('Open Existing Dialog', function (): void {
should.equal(await dialog.validate(), true, `Validation should pass because clone directory exists, but failed with: ${dialog.dialogObject.message.text}`);
});
test('Should validate workspace in onComplete when opening project', async function (): Promise<void> {
const workspaceServiceMock = TypeMoq.Mock.ofType<WorkspaceService>();
workspaceServiceMock.setup(x => x.validateWorkspace()).returns(() => Promise.resolve(true));
workspaceServiceMock.setup(x => x.addProjectsToWorkspace(TypeMoq.It.isAny())).returns(() => Promise.resolve());
const dialog = new OpenExistingDialog(workspaceServiceMock.object, mockExtensionContext.object);
await dialog.open();
dialog.filePathTextBox!.value = generateUniqueProjectFilePath('testproj');
should.doesNotThrow(async () => await dialog.onComplete());
workspaceServiceMock.setup(x => x.validateWorkspace()).throws(new Error('test error'));
const spy = sinon.spy(vscode.window, 'showErrorMessage');
should.doesNotThrow(async () => await dialog.onComplete(), 'Error should be caught');
should(spy.calledOnce).be.true();
});
test('workspace browse', async function (): Promise<void> {
const workspaceServiceMock = TypeMoq.Mock.ofType<WorkspaceService>();
sinon.stub(vscode.window, 'showOpenDialog').returns(Promise.resolve([]));
const dialog = new OpenExistingDialog(workspaceServiceMock.object, mockExtensionContext.object);
await dialog.open();
should.equal(dialog.filePathTextBox!.value, '');
await dialog.workspaceBrowse();
should.equal(dialog.filePathTextBox!.value, '', 'Workspace file should not be set when no file is selected');
sinon.restore();
const workspaceFile = vscode.Uri.file(generateUniqueWorkspaceFilePath());
sinon.stub(vscode.window, 'showOpenDialog').returns(Promise.resolve([workspaceFile]));
await dialog.workspaceBrowse();
should.equal(dialog.filePathTextBox!.value, workspaceFile.fsPath, 'Workspace file should get set');
should.equal(dialog.filePathTextBox?.value, workspaceFile.fsPath);
});
test('project browse', async function (): Promise<void> {
const workspaceServiceMock = TypeMoq.Mock.ofType<WorkspaceService>();
workspaceServiceMock.setup(x => x.getAllProjectTypes()).returns(() => Promise.resolve([testProjectType]));
sinon.stub(vscode.window, 'showOpenDialog').returns(Promise.resolve([]));
const dialog = new OpenExistingDialog(workspaceServiceMock.object, mockExtensionContext.object);
const dialog = new OpenExistingDialog(workspaceServiceMock.object);
await dialog.open();
should.equal(dialog.filePathTextBox!.value, '');
should.equal(dialog.filePathTextBox!.value ?? '', '', 'Project file should initially be empty');
await dialog.projectBrowse();
should.equal(dialog.filePathTextBox!.value, '', 'Project file should not be set when no file is selected');
should.equal(dialog.filePathTextBox!.value ?? '', '', 'Project file should not be set when no file is selected');
sinon.restore();
const projectFile = vscode.Uri.file(generateUniqueProjectFilePath('testproj'));
sinon.stub(vscode.window, 'showOpenDialog').returns(Promise.resolve([projectFile]));
await dialog.projectBrowse();
should.equal(dialog.filePathTextBox!.value, projectFile.fsPath, 'Project file should be set');
should.equal(dialog.filePathTextBox?.value, projectFile.fsPath);
});
});