particle-commands
Version:
Library of UX-neutral commands that provide key functionality for developer tools
124 lines (107 loc) • 4.93 kB
JavaScript
import path from 'path';
import { expect, sinon } from '../test-setup';
import { ProjectInitCommand } from '../../src/cmd/project_init';
import { ProjectInitCommandSite } from '../../src/cmd/project_init';
import ProjectProperties from '../../src/cmd/project_properties';
import underscore from 'underscore';
const fs = require('fs');
const mockfs = require('mock-fs');
describe('project_init', () => {
function addFile(target, filename) {
const content = fs.readFileSync(filename, 'utf-8');
target[filename] = content;
}
beforeEach(() => {
const fs = {};
addFile(fs, ProjectInitCommand.templateFile('gitignorefile'));
addFile(fs, ProjectInitCommand.templateFile('README.md'));
addFile(fs, ProjectInitCommand.templateFile('src/project.cpp'));
addFile(fs, ProjectInitCommand.templateFile('.github/workflows/main.yaml'));
mockfs(fs);
});
afterEach(() => {
return mockfs.restore();
});
describe('run', () => {
function createProject({ directory, name, allowDirectoryCreate }) {
const cmd = new ProjectInitCommand();
const site = new ProjectInitCommandSite();
site.notifyProjectNotCreated = sinon.stub();
site.directory = sinon.stub().resolves(directory);
site.name = sinon.stub().resolves(name);
if (allowDirectoryCreate !== undefined) {
site.notifyDirectoryExists = () => allowDirectoryCreate;
}
return cmd.run({}, site).then(() => site);
}
function expectTemplate(targetFile, templateName, properties) {
const templateFile = ProjectInitCommand.templateFile(templateName);
const expectedContent = underscore.template(fs.readFileSync(templateFile, 'utf-8'))(properties);
const actualContent = fs.readFileSync(targetFile, 'utf-8');
expect(actualContent).to.equal(expectedContent);
}
function expectProject(directory, properties) {
expect(fs.existsSync(directory), 'expected project directory to exist').to.be.true;
expect(fs.existsSync(path.join(directory, 'src')), 'expected src directory to exist').to.be.true;
expect(fs.existsSync(path.join(directory, 'project.properties')), 'expected project.properties to exist').to.be.true;
expectTemplate(path.join(directory, '.gitignore'), 'gitignorefile', properties);
expectTemplate(path.join(directory, '.github', 'workflows', 'main.yaml'), '.github/workflows/main.yaml', properties);
expectTemplate(path.join(directory, 'README.md'), 'README.md', properties);
expectTemplate(path.join(directory, 'src', properties.name + '.cpp'), 'src/project.cpp', properties);
const project = new ProjectProperties(directory, { fs:ProjectProperties.buildFs(fs) });
return project.load()
.then(() => {
for (const propName in properties) {
expect(project.getField(propName)).to.equal(properties[propName]);
}
return project;
});
}
function expectCreateProject({ directory, allowDirectoryCreate, name }) {
return createProject({ directory, allowDirectoryCreate, name })
.then((_site) => {
return expectProject(directory, { name });
});
}
it('creates the project when the directory does not exist', () => {
return expectCreateProject({ directory:'dir', name:'name1' });
});
it('creates the project when the directory exists and is empty', () => {
fs.mkdirSync('dir2');
return expectCreateProject({ directory:'dir2', name:'name2' });
});
it('creates the project when the directory exists and is not empty and the site returns true', () => {
fs.mkdirSync('dir4');
fs.writeFileSync('dir4/file', 'hi');
return expectCreateProject({ directory:'dir4', allowDirectoryCreate:true, name:'name4' });
});
it('does not create the project when the directory exists, contains files and the site returns false', () => {
fs.mkdirSync('dir3');
fs.writeFileSync('dir3/file', 'hi');
return createProject({ directory:'dir3', allowDirectoryCreate:false, name:'name3' })
.then((site) => {
expect(site.notifyProjectNotCreated).to.have.been.calledWith('dir3');
expect(fs.existsSync(path.join('dir3', 'project.properties')), 'expected project.properties to not exist').to.be.false;
});
});
it('fails with a validation error when the name is not valid', () => {
return createProject({ directory:'dir5', name:'$$invalid$$' })
.then(() => {
throw Error('expected exception');
})
.catch(error => {
expect(error.message).to.contain('name: must only contain letters, numbers');
});
});
it('preserves existing fields within project.properties', () => {
fs.mkdirSync('dir');
fs.writeFileSync(path.join('dir','project.properties'), 'wookie_meat_can_be=chewy');
return createProject({ directory:'dir', name:'badass', allowDirectoryCreate:true })
.then(() => expectProject('dir', { name:'badass' }))
.then((project) => {
expect(project.getField('wookie_meat_can_be')).to.equal('chewy');
});
});
// todo - preserve comments and field order
});
});