Skip to content

Commit

Permalink
feat: sort projects in project view (#1137)
Browse files Browse the repository at this point in the history
  • Loading branch information
peterblazejewicz authored Sep 24, 2021
1 parent fc4caea commit 7cc9ebe
Show file tree
Hide file tree
Showing 6 changed files with 224 additions and 0 deletions.
5 changes: 5 additions & 0 deletions libs/server/src/lib/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,11 @@ export function toWorkspaceFormat(w: any): WorkspaceJsonConfiguration {
});
});

const sortedProjects = Object.entries(w.projects || {}).sort(
(projectA, projectB) => projectA[0].localeCompare(projectB[0])
);
w.projects = Object.fromEntries(sortedProjects);

if (w.schematics) {
renameProperty(w, 'schematics', 'generators');
}
Expand Down
22 changes: 22 additions & 0 deletions libs/vscode/nx-workspace/__mocks__/@nx-console/server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const cacheJson = jest.fn();

const fileExistsSync = jest.fn();

const getOutputChannel = jest.fn(() => ({
appendLine: jest.fn(),
show: jest.fn(),
}));

const getTelemetry = jest.fn(() => ({
exception: jest.fn(),
}));

const toWorkspaceFormat = jest.fn();

export {
cacheJson,
fileExistsSync,
getOutputChannel,
getTelemetry,
toWorkspaceFormat,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const WorkspaceConfigurationStore = {
instance: {
get: jest.fn(),
},
};

export { WorkspaceConfigurationStore };
9 changes: 9 additions & 0 deletions libs/vscode/nx-workspace/__mocks__/vscode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/// <reference types="jest" />

const window = {
showErrorMessage: jest.fn(),
};

export = {
window,
};
3 changes: 3 additions & 0 deletions libs/vscode/nx-workspace/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ module.exports = {
'^.+\\.[tj]sx?$': 'ts-jest',
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
moduleNameMapper: {
'^@nx-console/vscode/(.+)$': '<rootDir>/libs/vscode/$1/src/index.ts',
},
coverageDirectory: '../../../coverage/libs/vscode/nx-workspace',
testEnvironment: 'node',
};
178 changes: 178 additions & 0 deletions libs/vscode/nx-workspace/src/lib/verify-workspace.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
import { verifyWorkspace } from './verify-workspace';
import { WorkspaceConfigurationStore } from '@nx-console/vscode/configuration';
import * as server from '@nx-console/server';
import {
cacheJson,
fileExistsSync,
getOutputChannel,
getTelemetry,
} from '@nx-console/server';
import type { WorkspaceJsonConfiguration } from '@nrwl/devkit';
import * as vscode from 'vscode';

const mockCacheJsonFn = cacheJson as jest.MockedFunction<typeof cacheJson>;
mockCacheJsonFn.mockImplementation((filePath) => ({
json: mockWorkspace,
path: filePath,
}));

const mockStoreInstanceGetFn = WorkspaceConfigurationStore.instance
.get as jest.MockedFunction<typeof WorkspaceConfigurationStore.instance.get>;
mockStoreInstanceGetFn.mockImplementation(() => workspacePath);

const mockFileExistsSyncFn = fileExistsSync as jest.MockedFunction<
typeof fileExistsSync
>;

const originalNxConsoleServerModule = jest.requireActual('@nx-console/server');
(server.toWorkspaceFormat as unknown) =
originalNxConsoleServerModule.toWorkspaceFormat;

const mockWorkspace: WorkspaceJsonConfiguration = {
version: 2,
projects: {
Project3: {
root: 'project-three',
},
Project1: {
root: 'project-one',
},
Project2: {
root: 'project-two',
},
},
defaultProject: undefined,
generators: undefined,
cli: undefined,
};

const DefaultWorkspaceInformation = {
validWorkspaceJson: false,
workspaceType: 'nx',
json: {
projects: {},
version: 2,
},
configurationFilePath: '',
};

const workspacePath = './test/fixtures/workspace/';

describe(verifyWorkspace.name, () => {
afterEach(() => {
mockFileExistsSyncFn.mockClear();
});

describe('when Nx workspace exists', () => {
it('returns information about Nx workspace', async () => {
// arrange
mockFileExistsSyncFn.mockImplementation((filePath) =>
/workspace.json$/i.test(filePath)
);

// act
const { validWorkspaceJson, json, workspaceType, configurationFilePath } =
await verifyWorkspace();

// assert
expect(mockFileExistsSyncFn).toHaveBeenCalledTimes(1);
expect(mockFileExistsSyncFn).toHaveLastReturnedWith(true);
expect(mockStoreInstanceGetFn).toHaveBeenCalledWith(
'nxWorkspaceJsonPath',
''
);
expect(mockCacheJsonFn).toHaveBeenCalled();
expect(validWorkspaceJson).toBe(true);
expect(json).toBeTruthy();
expect(json).toEqual(mockWorkspace);
expect(workspaceType).toBe('nx');
expect(configurationFilePath).toMatch(/workspace.json$/i);
});
});

describe('when Ng workspace exists', () => {
it('returns information about Ng workspace', async () => {
// arrange
mockFileExistsSyncFn.mockImplementation((filePath) =>
/angular.json$/i.test(filePath)
);

// act
const { validWorkspaceJson, json, workspaceType, configurationFilePath } =
await verifyWorkspace();

// assert
expect(mockFileExistsSyncFn).toHaveBeenCalledTimes(2);
expect(mockFileExistsSyncFn).toHaveNthReturnedWith(1, false);
expect(mockFileExistsSyncFn).toHaveNthReturnedWith(2, true);
expect(mockStoreInstanceGetFn).toHaveBeenCalledWith(
'nxWorkspaceJsonPath',
''
);
expect(mockCacheJsonFn).toHaveBeenCalled();
expect(validWorkspaceJson).toBe(true);
expect(json).toBeTruthy();
expect(json).toEqual(mockWorkspace);
expect(workspaceType).toBe('ng');
expect(configurationFilePath).toMatch(/angular.json$/i);
});
});

describe('when workspace json does not exist', () => {
it('it shows error dialog and returns default workspace information', async () => {
// arrange
mockFileExistsSyncFn.mockImplementation(
(filePath) => !/(angular|workspace).json$/i.test(filePath)
);

(vscode.window.showErrorMessage as unknown) = jest
.fn()
.mockResolvedValue('Show Error');

// act
const result = await verifyWorkspace();

// assert
expect(mockFileExistsSyncFn).toHaveBeenCalledTimes(2);
expect(mockFileExistsSyncFn).toHaveNthReturnedWith(1, false);
expect(mockFileExistsSyncFn).toHaveNthReturnedWith(2, false);
expect(vscode.window.showErrorMessage).toHaveBeenCalledWith(
expect.any(String),
'Show Error'
);
expect(getOutputChannel).toHaveBeenCalledTimes(3);
expect(getTelemetry).toHaveBeenCalledTimes(1);
expect(result).toEqual(DefaultWorkspaceInformation);
});
});

describe('when workspace information is found', () => {
it('projects entries are sorted by entry key', async () => {
// arrange
mockFileExistsSyncFn.mockImplementationOnce(() => true);
const sortedProject = {
Project1: {
root: 'project-one',
},
Project2: {
root: 'project-two',
},
Project3: {
root: 'project-three',
},
};

// act
const {
json: { projects },
} = await verifyWorkspace();
const [project1, project2, project3] = Object.keys(projects);
const [sorted1, sorted2, sorted3] = Object.keys(sortedProject);

// assert
expect(project1).toBe(sorted1); // should be 'Project1'
expect(project2).toBe(sorted2); // should be 'Project2'
expect(project3).toBe(sorted3); // should be 'Project3'
});
});
});

0 comments on commit 7cc9ebe

Please sign in to comment.