test/pad/nestjsDetection.test.ts
/* eslint-disable prefer-arrow-callback */
/* eslint-disable no-unused-expressions */
import { expect } from 'chai';
import * as sinon from 'sinon';
import * as fsAsync from '../../src/common/fsAsync';
import { ConfigManager } from '../../src/configuration/configManager';
import { ManifestReader } from '../../src/iconsManifest';
import {
IConfigManager,
IProjectAutoDetectionManager,
IVSCodeManager,
LangResourceKeys,
Projects,
} from '../../src/models';
import { ProjectAutoDetectionManager } from '../../src/pad/projectAutoDetectionManager';
import { Utils } from '../../src/utils';
import { VSCodeManager } from '../../src/vscode/vscodeManager';
import { vsicons } from '../fixtures/vsicons';
describe('ProjectAutoDetectionManager: NestJS project tests', function () {
context('ensures that', function () {
let sandbox: sinon.SinonSandbox;
let configManagerStub: sinon.SinonStubbedInstance<IConfigManager>;
let vscodeManagerStub: sinon.SinonStubbedInstance<IVSCodeManager>;
let findFilesStub: sinon.SinonStub;
let getPresetStub: sinon.SinonStub;
let parseJSONStub: sinon.SinonStub;
let padManager: IProjectAutoDetectionManager;
beforeEach(() => {
sandbox = sinon.createSandbox();
configManagerStub =
sandbox.createStubInstance<IConfigManager>(ConfigManager);
sandbox.stub(configManagerStub, 'vsicons').get(() => vsicons);
// eslint-disable-next-line @typescript-eslint/unbound-method
getPresetStub = configManagerStub.getPreset;
vscodeManagerStub =
sandbox.createStubInstance<IVSCodeManager>(VSCodeManager);
findFilesStub = sandbox.stub();
sandbox.stub(vscodeManagerStub, 'workspace').get(() => ({
findFiles: findFilesStub,
}));
padManager = new ProjectAutoDetectionManager(
vscodeManagerStub,
configManagerStub,
);
parseJSONStub = sandbox.stub(Utils, 'parseJSONSafe');
});
afterEach(function () {
padManager = null;
sandbox.restore();
});
context('when detection is enabled', function () {
let readFileAsyncStub: sinon.SinonStub;
let iconsDisabledStub: sinon.SinonStub;
let packageJsonPath = 'package.json';
beforeEach(function () {
vsicons.projectDetection.disableDetect = false;
findFilesStub.resolves([{ fsPath: packageJsonPath }]);
readFileAsyncStub = sandbox.stub(fsAsync, 'readFileAsync');
iconsDisabledStub = sandbox.stub(ManifestReader, 'iconsDisabled');
});
context(`detects a 'package.json' file`, function () {
beforeEach(function () {
parseJSONStub.returns({ name: 'project' });
});
it('on the root directory', async function () {
getPresetStub.returns({ workspaceValue: undefined });
iconsDisabledStub.resolves(true);
const res = await padManager.detectProjects([Projects.nestjs]);
const firstResult = res[0];
expect(
readFileAsyncStub.calledOnceWithExactly(packageJsonPath, 'utf8'),
).to.be.true;
expect(res).to.be.an('array');
expect(firstResult).to.be.an('object');
expect(Reflect.ownKeys(firstResult)).to.have.lengthOf(1);
expect(firstResult).to.have.all.keys('apply').and.ownProperty('apply')
.to.be.false;
});
it('in a sub folder', async function () {
packageJsonPath = 'f1/f2/f3/package.json';
findFilesStub.resolves([{ fsPath: packageJsonPath }]);
getPresetStub.returns({ workspaceValue: undefined });
iconsDisabledStub.resolves(true);
const res = await padManager.detectProjects([Projects.nestjs]);
const firstResult = res[0];
expect(
readFileAsyncStub.calledOnceWithExactly(packageJsonPath, 'utf8'),
).to.be.true;
expect(res).to.be.an('array');
expect(firstResult).to.be.an('object');
expect(Reflect.ownKeys(firstResult)).to.have.lengthOf(1);
expect(firstResult).to.have.all.keys('apply').and.ownProperty('apply')
.to.be.false;
});
});
context(`detects a NestJS project from`, function () {
it('dependencies', async function () {
parseJSONStub.returns({ dependencies: { '@nestjs/core': '1.0.0' } });
getPresetStub.returns({ workspaceValue: undefined });
iconsDisabledStub.resolves(true);
const res = await padManager.detectProjects([Projects.nestjs]);
const firstResult = res[0];
expect(readFileAsyncStub.calledWithExactly(packageJsonPath, 'utf8'))
.to.be.true;
expect(res).to.be.an('array');
expect(firstResult).to.be.an('object');
expect(Reflect.ownKeys(firstResult)).to.have.lengthOf(5);
expect(firstResult).to.have.all.keys(
'apply',
'project',
'conflictingProjects',
'langResourceKey',
'value',
);
expect(firstResult).ownProperty('apply').to.be.true;
expect(firstResult).ownProperty('project').to.equal(Projects.nestjs);
expect(firstResult).ownProperty('conflictingProjects').to.be.empty;
expect(firstResult)
.ownProperty('langResourceKey')
.to.equal(LangResourceKeys.nestDetected);
expect(firstResult).ownProperty('value').to.be.true;
});
it('devDependencies', async function () {
parseJSONStub.returns({
devDependencies: { '@nestjs/core': '1.0.0' },
});
getPresetStub.returns({ workspaceValue: undefined });
iconsDisabledStub.resolves(true);
const res = await padManager.detectProjects([Projects.nestjs]);
const firstResult = res[0];
expect(readFileAsyncStub.calledWithExactly(packageJsonPath, 'utf8'))
.to.be.true;
expect(res).to.be.an('array');
expect(firstResult).to.be.an('object');
expect(Reflect.ownKeys(firstResult)).to.have.lengthOf(5);
expect(firstResult).to.have.all.keys(
'apply',
'project',
'conflictingProjects',
'langResourceKey',
'value',
);
expect(firstResult).ownProperty('apply').to.be.true;
expect(firstResult).ownProperty('project').to.equal(Projects.nestjs);
expect(firstResult).ownProperty('conflictingProjects').to.be.empty;
expect(firstResult)
.ownProperty('langResourceKey')
.to.equal(LangResourceKeys.nestDetected);
expect(firstResult).ownProperty('value').to.be.true;
});
});
context(`detects a non NestJS project from`, function () {
beforeEach(function () {
parseJSONStub.returns({ dependencies: { vscode: '' } });
});
it('dependencies', async function () {
getPresetStub.returns({ workspaceValue: undefined });
iconsDisabledStub.resolves(true);
const res = await padManager.detectProjects([Projects.nestjs]);
const firstResult = res[0];
expect(readFileAsyncStub.calledOnceWith(packageJsonPath, 'utf8')).to
.be.true;
expect(res).to.be.an('array');
expect(firstResult).to.be.an('object');
expect(Reflect.ownKeys(firstResult)).to.have.lengthOf(1);
expect(firstResult).to.have.all.keys('apply').and.ownProperty('apply')
.to.be.false;
});
it('devDependencies', async function () {
getPresetStub.returns({ workspaceValue: undefined });
iconsDisabledStub.resolves(true);
const res = await padManager.detectProjects([Projects.nestjs]);
const firstResult = res[0];
expect(readFileAsyncStub.calledOnceWith(packageJsonPath, 'utf8')).to
.be.true;
expect(res).to.be.an('array');
expect(firstResult).to.be.an('object');
expect(Reflect.ownKeys(firstResult)).to.have.lengthOf(1);
expect(firstResult).to.have.all.keys('apply').and.ownProperty('apply')
.to.be.false;
});
});
context(`does NOT detect a project when`, function () {
it('it does NOT exist', async function () {
parseJSONStub.returns({
dependencies: {
'@nestjs/core': '',
vscode: '',
},
});
getPresetStub.returns({ workspaceValue: undefined });
iconsDisabledStub.resolves(true);
const res = await padManager.detectProjects([Projects.nestjs]);
const firstResult = res[0];
expect(
readFileAsyncStub.calledOnceWithExactly(packageJsonPath, 'utf8'),
).to.be.true;
expect(res).to.be.an('array');
expect(firstResult).to.be.an('object');
expect(Reflect.ownKeys(firstResult)).to.have.lengthOf(1);
expect(firstResult).to.have.all.keys('apply').and.ownProperty('apply')
.to.be.false;
});
it('no project json object is provided', async function () {
parseJSONStub.returns(null);
getPresetStub.returns({ workspaceValue: undefined });
iconsDisabledStub.resolves(true);
const res = await padManager.detectProjects([Projects.nestjs]);
const firstResult = res[0];
expect(
readFileAsyncStub.calledOnceWithExactly(packageJsonPath, 'utf8'),
).to.be.true;
expect(res).to.be.an('array');
expect(firstResult).to.be.an('object');
expect(Reflect.ownKeys(firstResult)).to.have.lengthOf(1);
expect(firstResult).to.have.all.keys('apply').and.ownProperty('apply')
.to.be.false;
});
it('no dependencies and devDependecies exists', async function () {
parseJSONStub.returns({});
getPresetStub.returns({ workspaceValue: undefined });
iconsDisabledStub.resolves(true);
const res = await padManager.detectProjects([Projects.nestjs]);
const firstResult = res[0];
expect(
readFileAsyncStub.calledOnceWithExactly(packageJsonPath, 'utf8'),
).to.be.true;
expect(res).to.be.an('array');
expect(firstResult).to.be.an('object');
expect(Reflect.ownKeys(firstResult)).to.have.lengthOf(1);
expect(firstResult).to.have.all.keys('apply').and.ownProperty('apply')
.to.be.false;
});
it('project name does NOT exists', async function () {
parseJSONStub.returns({
dependencies: {
'@nestjs/core': '0.0.0',
},
});
getPresetStub.returns({ workspaceValue: undefined });
iconsDisabledStub.resolves(true);
const res = await padManager.detectProjects([Projects.angularjs]);
const firstResult = res[0];
expect(readFileAsyncStub.calledOnceWith(packageJsonPath, 'utf8')).to
.be.true;
expect(res).to.be.an('array');
expect(firstResult).to.be.an('object');
expect(Reflect.ownKeys(firstResult)).to.have.lengthOf(1);
expect(firstResult).to.have.all.keys('apply').and.ownProperty('apply')
.to.be.false;
});
});
context('the icons gets enabled when', function () {
context(`the icons are disabled and the workspace is`, function () {
context('a NestJS project and', function () {
beforeEach(function () {
parseJSONStub.returns({
dependencies: { '@nestjs/core': '0.0.0' },
});
});
it(`preset is 'true'`, async function () {
getPresetStub.returns({ workspaceValue: true });
iconsDisabledStub.resolves(true);
const res = await padManager.detectProjects([Projects.nestjs]);
const firstResult = res[0];
expect(readFileAsyncStub.calledOnceWith(packageJsonPath, 'utf8'))
.to.be.true;
expect(res).to.be.an('array');
expect(firstResult).to.be.an('object');
expect(Reflect.ownKeys(firstResult)).to.have.lengthOf(5);
expect(firstResult).to.have.all.keys(
'apply',
'project',
'conflictingProjects',
'langResourceKey',
'value',
);
expect(firstResult).ownProperty('apply').to.be.true;
expect(firstResult)
.ownProperty('project')
.to.equal(Projects.nestjs);
expect(firstResult).ownProperty('conflictingProjects').to.be
.empty;
expect(firstResult)
.ownProperty('langResourceKey')
.to.equal(LangResourceKeys.nonNestDetectedPresetTrue);
expect(firstResult).ownProperty('value').to.be.true;
});
it(`preset is 'undefined'`, async function () {
getPresetStub.returns({ workspaceValue: undefined });
iconsDisabledStub.resolves(true);
const res = await padManager.detectProjects([Projects.nestjs]);
const firstResult = res[0];
expect(
readFileAsyncStub.calledWithExactly(packageJsonPath, 'utf8'),
).to.be.true;
expect(res).to.be.an('array');
expect(firstResult).to.be.an('object');
expect(Reflect.ownKeys(firstResult)).to.have.lengthOf(5);
expect(firstResult).to.have.all.keys(
'apply',
'project',
'conflictingProjects',
'langResourceKey',
'value',
);
expect(firstResult).ownProperty('apply').to.be.true;
expect(firstResult)
.ownProperty('project')
.to.equal(Projects.nestjs);
expect(firstResult).ownProperty('conflictingProjects').to.be
.empty;
expect(firstResult)
.ownProperty('langResourceKey')
.to.equal(LangResourceKeys.nestDetected);
expect(firstResult).ownProperty('value').to.be.true;
});
});
context('not a NestJS project and', function () {
beforeEach(function () {
parseJSONStub.returns({ dependencies: { vscode: '0.0.0' } });
});
it(`preset is 'true'`, async function () {
getPresetStub.returns({ workspaceValue: true });
iconsDisabledStub.resolves(true);
const res = await padManager.detectProjects([Projects.nestjs]);
const firstResult = res[0];
expect(readFileAsyncStub.calledOnceWith(packageJsonPath, 'utf8'))
.to.be.true;
expect(res).to.be.an('array');
expect(firstResult).to.be.an('object');
expect(Reflect.ownKeys(firstResult)).to.have.lengthOf(5);
expect(firstResult).to.have.all.keys(
'apply',
'project',
'conflictingProjects',
'langResourceKey',
'value',
);
expect(firstResult).ownProperty('apply').to.be.true;
expect(firstResult)
.ownProperty('project')
.to.equal(Projects.nestjs);
expect(firstResult).ownProperty('conflictingProjects').to.be
.empty;
expect(firstResult)
.ownProperty('langResourceKey')
.to.equal(LangResourceKeys.nonNestDetectedPresetTrue);
expect(firstResult).ownProperty('value').to.be.true;
});
});
});
});
context('the icons get disabled when', function () {
context('the icons are enabled and the workspace is', function () {
context('not a NestJS project and', function () {
beforeEach(function () {
parseJSONStub.returns({ dependencies: { vscode: '0.0.0' } });
});
it(`preset is 'false'`, async function () {
getPresetStub.returns({ workspaceValue: false });
iconsDisabledStub.resolves(false);
const res = await padManager.detectProjects([Projects.nestjs]);
const firstResult = res[0];
expect(readFileAsyncStub.calledOnceWith(packageJsonPath, 'utf8'))
.to.be.true;
expect(res).to.be.an('array');
expect(firstResult).to.be.an('object');
expect(Reflect.ownKeys(firstResult)).to.have.lengthOf(5);
expect(firstResult).to.have.all.keys(
'apply',
'project',
'conflictingProjects',
'langResourceKey',
'value',
);
expect(firstResult).ownProperty('apply').to.be.true;
expect(firstResult)
.ownProperty('project')
.to.equal(Projects.nestjs);
expect(firstResult).ownProperty('conflictingProjects').to.be
.empty;
expect(firstResult)
.ownProperty('langResourceKey')
.to.equal(LangResourceKeys.nestDetectedPresetFalse);
expect(firstResult).ownProperty('value').to.be.false;
});
it(`preset is 'undefined'`, async function () {
getPresetStub.returns({ workspaceValue: undefined });
iconsDisabledStub.resolves(false);
const res = await padManager.detectProjects([Projects.nestjs]);
const firstResult = res[0];
expect(readFileAsyncStub.calledOnceWith(packageJsonPath, 'utf8'))
.to.be.true;
expect(res).to.be.an('array');
expect(firstResult).to.be.an('object');
expect(Reflect.ownKeys(firstResult)).to.have.lengthOf(5);
expect(firstResult).to.have.all.keys(
'apply',
'project',
'conflictingProjects',
'langResourceKey',
'value',
);
expect(firstResult).ownProperty('apply').to.be.true;
expect(firstResult)
.ownProperty('project')
.to.equal(Projects.nestjs);
expect(firstResult).ownProperty('conflictingProjects').to.be
.empty;
expect(firstResult)
.ownProperty('langResourceKey')
.to.equal(LangResourceKeys.nonNestDetected);
expect(firstResult).ownProperty('value').to.be.false;
});
});
context('a NestJS project and', function () {
beforeEach(function () {
parseJSONStub.returns({
dependencies: { '@nestjs/core': '0.0.0' },
});
});
it(`preset is 'false'`, async function () {
getPresetStub.returns({ workspaceValue: false });
iconsDisabledStub.resolves(false);
const res = await padManager.detectProjects([Projects.nestjs]);
const firstResult = res[0];
expect(readFileAsyncStub.calledOnceWith(packageJsonPath, 'utf8'))
.to.be.true;
expect(res).to.be.an('array');
expect(firstResult).to.be.an('object');
expect(Reflect.ownKeys(firstResult)).to.have.lengthOf(5);
expect(firstResult).to.have.all.keys(
'apply',
'project',
'conflictingProjects',
'langResourceKey',
'value',
);
expect(firstResult).ownProperty('apply').to.be.true;
expect(firstResult)
.ownProperty('project')
.to.equal(Projects.nestjs);
expect(firstResult).ownProperty('conflictingProjects').to.be
.empty;
expect(firstResult)
.ownProperty('langResourceKey')
.to.equal(LangResourceKeys.nestDetectedPresetFalse);
expect(firstResult).ownProperty('value').to.be.false;
});
});
});
});
context('does not toggle the icons when', function () {
context('the icons are enabled and the workspace is', function () {
beforeEach(function () {
iconsDisabledStub.resolves(false);
});
context('a NestJS project and', function () {
beforeEach(function () {
parseJSONStub.returns({
dependencies: { '@nestjs/core': '0.0.0' },
});
});
it(`preset is 'true'`, async function () {
getPresetStub.returns({ workspaceValue: true });
const res = await padManager.detectProjects([Projects.nestjs]);
const firstResult = res[0];
expect(readFileAsyncStub.called).to.be.false;
expect(res).to.be.an('array');
expect(firstResult).to.be.an('object');
expect(Reflect.ownKeys(firstResult)).to.have.lengthOf(1);
expect(firstResult)
.to.have.all.keys('apply')
.and.ownProperty('apply').to.be.false;
});
it(`preset is 'undefined'`, async function () {
getPresetStub.returns({ workspaceValue: undefined });
const res = await padManager.detectProjects([Projects.nestjs]);
const firstResult = res[0];
expect(readFileAsyncStub.calledOnceWith(packageJsonPath, 'utf8'))
.to.be.true;
expect(res).to.be.an('array');
expect(firstResult).to.be.an('object');
expect(Reflect.ownKeys(firstResult)).to.have.lengthOf(1);
expect(firstResult)
.to.have.all.keys('apply')
.and.ownProperty('apply').to.be.false;
});
});
context('not a NestJS project and', function () {
beforeEach(function () {
parseJSONStub.returns({ dependencies: { vscode: '0.0.0' } });
});
it(`preset is 'true'`, async function () {
getPresetStub.returns({ workspaceValue: true });
const res = await padManager.detectProjects([Projects.nestjs]);
const firstResult = res[0];
expect(readFileAsyncStub.called).to.be.false;
expect(res).to.be.an('array');
expect(firstResult).to.be.an('object');
expect(Reflect.ownKeys(firstResult)).to.have.lengthOf(1);
expect(firstResult)
.to.have.all.keys('apply')
.and.ownProperty('apply').to.be.false;
});
});
});
context('the icons are disabled and the workspace is', function () {
beforeEach(function () {
iconsDisabledStub.resolves(true);
});
context('not a NestJS project and', function () {
beforeEach(function () {
parseJSONStub.returns({ dependencies: { vscode: '0.0.0' } });
});
it(`preset is 'false'`, async function () {
getPresetStub.returns({ workspaceValue: false });
const res = await padManager.detectProjects([Projects.nestjs]);
const firstResult = res[0];
expect(readFileAsyncStub.called).to.be.false;
expect(res).to.be.an('array');
expect(firstResult).to.be.an('object');
expect(Reflect.ownKeys(firstResult)).to.have.lengthOf(1);
expect(firstResult)
.to.have.all.keys('apply')
.and.ownProperty('apply').to.be.false;
});
it(`preset is 'undefined'`, async function () {
getPresetStub.returns({ workspaceValue: undefined });
const res = await padManager.detectProjects([Projects.nestjs]);
const firstResult = res[0];
expect(readFileAsyncStub.calledOnceWith(packageJsonPath, 'utf8'))
.to.be.true;
expect(res).to.be.an('array');
expect(firstResult).to.be.an('object');
expect(Reflect.ownKeys(firstResult)).to.have.lengthOf(1);
expect(firstResult)
.to.have.all.keys('apply')
.and.ownProperty('apply').to.be.false;
});
});
context('a NestJS project and', function () {
beforeEach(function () {
parseJSONStub.returns({
dependencies: { '@nestjs/core': '0.0.0' },
});
});
it(`preset is 'false'`, async function () {
getPresetStub.returns({ workspaceValue: false });
const res = await padManager.detectProjects([Projects.nestjs]);
const firstResult = res[0];
expect(readFileAsyncStub.called).to.be.false;
expect(res).to.be.an('array');
expect(firstResult).to.be.an('object');
expect(Reflect.ownKeys(firstResult)).to.have.lengthOf(1);
expect(firstResult)
.to.have.all.keys('apply')
.and.ownProperty('apply').to.be.false;
});
});
});
context('conflicting project icons are enabled and', function () {
it('its preset is explicitly set', async function () {
parseJSONStub.returns({
dependencies: {
'@angular/core': '1.0.0',
'@nestjs/core': '1.0.0',
},
});
getPresetStub
.onSecondCall()
.returns({ workspaceValue: true })
.returns({ workspaceValue: undefined });
iconsDisabledStub.onSecondCall().resolves(false).resolves(true);
const res = await padManager.detectProjects([Projects.nestjs]);
const firstResult = res[0];
expect(iconsDisabledStub.callCount).to.be.equal(1);
expect(res).to.be.an('array');
expect(firstResult).to.be.an('object');
expect(Reflect.ownKeys(firstResult)).to.have.lengthOf(1);
expect(firstResult)
.to.have.all.keys('apply')
.and.ownProperty('apply').to.be.false;
});
});
});
});
});
});