enb
Version:
Faster BEM/BEViS assembler
804 lines (596 loc) • 29.8 kB
JavaScript
var path = require('path');
var mockFs = require('mock-fs');
var ProjectConfig = require('../../../lib/config/project-config');
var NodeConfig = require('../../../lib/config/node-config');
var NodeMaskConfig = require('../../../lib/config/node-mask-config');
var TaskConfig = require('../../../lib/config/task-config');
var ModeConfig = require('../../../lib/config/mode-config');
var ModuleConfig = require('../../../lib/config/module-config');
describe('config/project-config', function () {
var projectRoot = path.resolve(__dirname);
var projectConfig;
beforeEach(function () {
projectConfig = new ProjectConfig(projectRoot);
});
describe('constructor', function () {
it('should set root path', function () {
expect(projectConfig.getRootPath()).to.be.equal(projectRoot);
});
it('should create container for node configs', function () {
expect(projectConfig.getNodeConfigs()).to.exist
.and.to.be.instanceOf(Object)
.and.to.be.empty;
});
it('should create container for tasks', function () {
expect(projectConfig.getTaskConfigs()).to.exist
.and.to.be.instanceOf(Object)
.and.to.be.empty;
});
it('shoud create container for node mask configs', function () {
expect(projectConfig.getNodeMaskConfigs()).to.exist
.and.to.be.instanceOf(Array)
.and.to.be.empty;
});
it('should define property for languages container', function () {
expect(projectConfig).to.have.property('_languages');
});
it('should not create container for languages', function () {
expect(projectConfig.getLanguages()).to.be.null;
});
it('should create container for level naming schemes', function () {
expect(projectConfig.getLevelNamingSchemes()).to.exist
.and.to.be.instanceOf(Array)
.and.to.be.empty;
});
it('should create container for registering modules', function () {
expect(projectConfig._modules).to.exist
.and.to.be.instanceOf(Object)
.and.to.be.empty;
});
it('should create container for mode configs', function () {
expect(projectConfig.getModeConfigs()).to.exist
.and.to.be.instanceOf(Object)
.and.to.be.empty;
});
it('should define container for environment variables', function () {
expect(projectConfig.getEnvValues()).to.exist
.and.to.be.instanceOf(Object);
});
it('should copy process environment variables to self environment variables container', function () {
var expectedEnvVariables = {};
Object.keys(process.env).forEach(function (key) {
expectedEnvVariables[key] = process.env[key];
});
expect(projectConfig.getEnvValues()).to.be.deep.equal(expectedEnvVariables);
});
});
describe('getLanguages', function () {
it('should return previously set languages', function () {
var languages = ['en', 'ru'];
projectConfig.setLanguages(languages);
expect(projectConfig.getLanguages()).to.be.deep.equal(languages);
});
it('should return null if no languages were set', function () {
expect(projectConfig.getLanguages()).to.be.null;
});
});
describe('setLanguages', function () {
it('should set languages', function () {
var languages = ['en', 'ru'];
projectConfig.setLanguages(languages);
expect(projectConfig.getLanguages()).to.be.deep.equal(languages);
});
it('should support method chaining pattern', function () {
var result = projectConfig.setLanguages();
expect(result).to.be.equal(projectConfig);
});
});
describe('getRootPath', function () {
it('should return root path', function () {
expect(projectConfig.getRootPath()).to.be.equal(projectRoot);
});
});
describe('resolvePath', function () {
it('should return root path if no path to resolve provided', function () {
expect(projectConfig.resolvePath()).to.be.equal(projectRoot);
});
it('should resolve source path passed as string', function () {
var sourcePath = 'path/to/level';
var expectedResolvedPath = path.resolve(projectRoot, sourcePath);
var result = projectConfig.resolvePath(sourcePath);
expect(result).to.be.equal(expectedResolvedPath);
});
it('should resolve path passed as object with property path', function () {
var sourcePath = { path: 'path/to/level' };
var expectedResolvedPath = { path: path.resolve(projectRoot, sourcePath.path) };
var result = projectConfig.resolvePath(sourcePath);
expect(result).to.be.deep.equal(expectedResolvedPath);
});
});
describe('node', function () {
var nodePath = 'path/to/node';
var configurator = function () {};
it('should add node config to node configs', function () {
projectConfig.node(nodePath, configurator);
expect(projectConfig.getNodeConfig(nodePath)).to.exist;
});
it('should add node config to node configs as NodeConfig instance', function () {
projectConfig.node(nodePath, configurator);
expect(projectConfig.getNodeConfig(nodePath)).to.be.instanceOf(NodeConfig);
});
it('should add configurator to node config', function () {
projectConfig.node(nodePath, configurator);
expect(projectConfig.getNodeConfig(nodePath)._chains).to.contain(configurator);
});
it('should not create new node config if adding multiple configurators for same node path', function () {
var anotherConfigurator = function () {};
var firstNodeConfig;
var secondNodeConfig;
projectConfig.node(nodePath, configurator);
firstNodeConfig = projectConfig.getNodeConfig(nodePath);
projectConfig.node(nodePath, anotherConfigurator);
secondNodeConfig = projectConfig.getNodeConfig(nodePath);
expect(firstNodeConfig).to.be.equal(secondNodeConfig);
});
it('should remove leading path separator from node path', function () {
var modifiedNodePath = path.sep + nodePath;
projectConfig.node(modifiedNodePath, configurator);
expect(projectConfig.getNodeConfigs()).to.have.property(nodePath);
});
it('should remove trailing path separator from node path', function () {
var modifiedNodePath = nodePath + path.sep;
projectConfig.node(modifiedNodePath, configurator);
expect(projectConfig.getNodeConfigs()).to.have.property(nodePath);
});
it('should remove leading and trailing path separators from node path', function () {
var modifiedNodePath = path.sep + nodePath + path.sep;
projectConfig.node(modifiedNodePath, configurator);
expect(projectConfig.getNodeConfigs()).to.have.property(nodePath);
});
it('should support method chaining pattern', function () {
var result = projectConfig.node(nodePath, configurator);
expect(result).to.be.equal(projectConfig);
});
});
describe('nodes', function () {
var configurator = function () {};
beforeEach(function () {
var config = {};
config[projectRoot] = {
blocks: {},
page: {}
};
mockFs(config);
});
afterEach(function () {
mockFs.restore();
});
it('should add configurator to node configs', function () {
var nodePath = 'path/to/node';
projectConfig.nodes(nodePath, configurator);
expect(projectConfig.getNodeConfig(nodePath)).to.exist
.and.to.be.instanceOf(NodeConfig);
});
it('should add node configs for multiple paths passed as relative paths', function () {
var nodePath = 'path/to/node';
var anotherNodePath = 'path/to/another/node';
projectConfig.nodes(nodePath, anotherNodePath, configurator);
expect(projectConfig.getNodeConfig(nodePath)).to.exist
.and.to.be.instanceOf(NodeConfig);
expect(projectConfig.getNodeConfig(anotherNodePath)).to.exist
.and.to.be.instanceOf(NodeConfig);
});
it('should add node configs for multiple paths passed as array of relative paths', function () {
var nodePath = 'path/to/node';
var anotherNodePath = 'path/to/another/node';
var paths = [nodePath, anotherNodePath];
projectConfig.nodes(paths, configurator);
expect(projectConfig.getNodeConfig(nodePath)).to.exist
.and.to.be.instanceOf(NodeConfig);
expect(projectConfig.getNodeConfig(anotherNodePath)).to.exist
.and.to.be.instanceOf(NodeConfig);
});
it('should add node configs for multiple paths passed as shell mask, adding node configs as relative paths ' +
'after resolving shell mask', function () {
var nodeMask = '/*';
var blocksNodePath = 'blocks'; // blocks and pages are directories in root of project fixture
var pageNodePath = 'page';
projectConfig.nodes(nodeMask, configurator);
expect(projectConfig.getNodeConfig(blocksNodePath)).to.exist
.and.to.be.instanceOf(NodeConfig);
expect(projectConfig.getNodeConfig(pageNodePath)).to.exist
.and.to.be.instanceOf(NodeConfig);
});
it('should add node configs for multiple paths passed in mixed manner: as relative path, array of relative ' +
'paths and shell mask', function () {
var nodePath = 'path/to/node';
var anotherNodePath = 'path/to/another/node';
var blocksNodePath = 'blocks'; // blocks and pages are directories in root of project fixture
var pageNodePath = 'page';
var nodeMask = '/*';
var pathsArray = [anotherNodePath];
var expectedPath = [nodePath, anotherNodePath, blocksNodePath, pageNodePath];
projectConfig.nodes(nodePath, pathsArray, nodeMask, configurator);
expectedPath.forEach(function (expectedPath) {
expect(projectConfig.getNodeConfig(expectedPath)).to.exist
.and.to.be.instanceOf(NodeConfig);
});
});
it('should support method chaining pattern', function () {
var nodePath = 'path/to/node';
var result = projectConfig.nodes(nodePath, configurator);
expect(result).to.be.equal(projectConfig);
});
});
describe('nodeMask', function () {
var mask = /\w*bundles/g;
var configurator = function () {};
it('should add node mask config', function () {
projectConfig.nodeMask(mask, configurator);
expect(projectConfig.getNodeMaskConfigs()).to.have.length(1);
expect(projectConfig.getNodeMaskConfigs()[0]).to.be.instanceOf(NodeMaskConfig);
});
it('should add configurator to created node mask config', function () {
projectConfig.nodeMask(mask, configurator);
expect(projectConfig.getNodeMaskConfigs()[0]._chains).to.contain(configurator);
});
it('should create different node mask configs for same masks', function () {
var anotherConfigurator = function () {};
var expectedConfigsAmount = 2;
projectConfig.nodeMask(mask, configurator);
projectConfig.nodeMask(mask, anotherConfigurator);
expect(projectConfig.getNodeMaskConfigs()).to.have.length(expectedConfigsAmount);
});
it('should support method chaining pattern', function () {
var result = projectConfig.nodeMask(mask, configurator);
expect(result).to.be.equal(projectConfig);
});
});
describe('task', function () {
var taskName = 'test_task';
var configurator = function () {};
it('should add task config', function () {
projectConfig.task(taskName, configurator);
expect(projectConfig.getTaskConfig(taskName)).to.exist
.and.to.be.instanceOf(TaskConfig);
});
it('should add configurator to created task config', function () {
projectConfig.task(taskName, configurator);
expect(projectConfig.getTaskConfig(taskName)._chains).to.contain(configurator);
});
it('should not create new task config if adding multiple configurators for same task name', function () {
var firstTaskConfig;
var secondTaskConfig;
var anotherConfigurator = function () {};
projectConfig.task(taskName, configurator);
firstTaskConfig = projectConfig.getTaskConfig(taskName);
projectConfig.task(taskName, anotherConfigurator);
secondTaskConfig = projectConfig.getTaskConfig(taskName);
expect(firstTaskConfig).to.be.equal(secondTaskConfig);
});
it('should support method chaining pattern', function () {
var result = projectConfig.task(taskName, configurator);
expect(result).to.be.equal(projectConfig);
});
});
describe('mode', function () {
var modeName = 'test_mode';
var configurator = function () {};
it('should add mode config', function () {
projectConfig.mode(modeName, configurator);
expect(projectConfig.getModeConfig(modeName)).to.exist
.and.to.be.instanceOf(ModeConfig);
});
it('should add configurator to created mode config', function () {
projectConfig.mode(modeName, configurator);
expect(projectConfig.getModeConfig(modeName)._chains).to.contain(configurator);
});
it('should not create new mode config if adding multiple configurators for same mode name', function () {
var firstModeConfig;
var secondModeConfig;
var anotherConfigurator = function () {};
projectConfig.mode(modeName, configurator);
firstModeConfig = projectConfig.getModeConfig(modeName);
projectConfig.mode(modeName, anotherConfigurator);
secondModeConfig = projectConfig.getModeConfig(modeName);
expect(firstModeConfig).to.be.equal(secondModeConfig);
});
it('should support method chaining pattern', function () {
var result = projectConfig.mode(modeName, configurator);
expect(result).to.be.equal(projectConfig);
});
});
describe('registerModule', function () {
var moduleName = 'test_module';
var moduleConfig;
beforeEach(function () {
moduleConfig = new ModuleConfig();
});
it('should register module', function () {
projectConfig.registerModule(moduleName, moduleConfig);
expect(projectConfig.module(moduleName)).to.be.equal(moduleConfig);
});
it('should not allow registering multiple modules for same name', function () {
var anotherModuleConfig = new ModuleConfig();
var expectedExcMessage = 'Module "' + moduleName + '" is already registered';
var func = function () {
projectConfig.registerModule(moduleName, moduleConfig);
projectConfig.registerModule(moduleName, anotherModuleConfig);
};
expect(func).to.throw(expectedExcMessage);
});
it('should allow registering same module for different names', function () {
var anotherModuleName = 'another_test_module';
var func = function () {
projectConfig.registerModule(moduleName, moduleConfig);
projectConfig.registerModule(anotherModuleName, moduleConfig);
};
expect(func).to.not.throw();
});
});
describe('module', function () {
var moduleName = 'test_module';
var configurator = function () {};
var moduleConfig;
beforeEach(function () {
moduleConfig = new ModuleConfig();
projectConfig.registerModule(moduleName, moduleConfig);
});
it('should add configurator to registered module', function () {
projectConfig.module(moduleName, configurator);
expect(projectConfig.module(moduleName)._chains).to.contain(configurator);
});
it('should throw error on attempt to configure non-registered module', function () {
var nonRegisteredModuleName = 'non_registered_module';
var expectedErrorMessage = 'Module "' + nonRegisteredModuleName + '" is not registered.';
var func = function () { projectConfig.module(nonRegisteredModuleName, configurator); };
expect(func).to.throw(expectedErrorMessage);
});
it('should return module if configurator is not provided', function () {
expect(projectConfig.module(moduleName)).to.be.equal(moduleConfig);
});
it('should return self if configurator provided', function () {
expect(projectConfig.module(moduleName, configurator)).to.be.equal(projectConfig);
});
});
describe('getTaskConfigs', function () {
var taskName = 'test_task';
var configurator = function () {};
it('should return tasks', function () {
projectConfig.task(taskName, configurator);
expect(projectConfig.getTaskConfigs()).to.be.instanceOf(Object)
.and.to.have.property(taskName);
});
});
describe('getTaskConfig', function () {
var taskName = 'test_task';
var configurator = function () {};
it('should return task config if it was added to project config', function () {
projectConfig.task(taskName, configurator);
expect(projectConfig.getTaskConfig(taskName)).to.exist
.and.to.be.instanceOf(TaskConfig);
});
it('should return undefined if task config is missing in project config', function () {
var missedTaskName = 'missed_task';
expect(projectConfig.getTaskConfig(missedTaskName)).to.be.undefined;
});
});
describe('getModeConfigs', function () {
var modeName = 'test_mode';
var configurator = function () {};
it('should return mode configs', function () {
projectConfig.mode(modeName, configurator);
expect(projectConfig.getModeConfigs()).to.be.instanceOf(Object)
.and.to.have.property(modeName);
});
});
describe('getModeConfig', function () {
var modeName = 'test_mode';
var configurator = function () {};
it('should return mode config if mode was added to project config', function () {
projectConfig.mode(modeName, configurator);
expect(projectConfig.getModeConfig(modeName)).to.exist
.and.to.be.instanceOf(ModeConfig);
});
it('should return undefined if mode was not added to project config', function () {
var missedModeName = 'missed_mode';
expect(projectConfig.getModeConfig(missedModeName)).to.be.undefined;
});
});
describe('getNodeConfigs', function () {
var nodePath = 'path/to/node';
var configurator = function () {};
it('should return node configs', function () {
projectConfig.node(nodePath, configurator);
expect(projectConfig.getNodeConfigs()).to.be.instanceOf(Object)
.and.to.have.property(nodePath);
});
});
describe('getNodeConfig', function () {
var nodePath = 'path/to/node';
var configurator = function () {};
it('should return node config if it was added to project config', function () {
projectConfig.node(nodePath, configurator);
expect(projectConfig.getNodeConfig(nodePath)).to.exist
.and.to.be.instanceOf(NodeConfig);
});
it('should return undefined if node config was not added for requested path', function () {
var wrongNodePath = 'path/to/missing/node';
expect(projectConfig.getNodeConfig(wrongNodePath)).to.be.undefined;
});
});
describe('getNodeMaskConfigs', function () {
var mask = /\w*bundles/g;
var configurator = function () {};
it('should return all node mask configs if no node path specified', function () {
projectConfig.nodeMask(mask, configurator);
expect(projectConfig.getNodeMaskConfigs()).to.be.instanceOf(Array)
.and.to.have.length(1);
expect(projectConfig.getNodeMaskConfigs()[0]).to.be.instanceOf(NodeMaskConfig);
});
it('should return mask config if it\'s mask matches with path', function () {
var nodePath = 'path/to/desktop.bundles';
var anotherMask = /\w*nodes/g;
var result;
projectConfig.nodeMask(mask, configurator);
projectConfig.nodeMask(anotherMask, configurator);
result = projectConfig.getNodeMaskConfigs(nodePath);
expect(result).to.be.instanceOf(Array)
.and.to.have.length(1);
expect(result[0]).to.be.instanceOf(NodeMaskConfig);
expect(result[0].getMask()).to.be.equal(mask);
});
});
describe('getEnv', function () {
it('should return env option if it was set', function () {
var optionName = 'option_name';
var optionValue = 'option_value';
projectConfig.setEnv(optionName, optionValue);
expect(projectConfig.getEnv(optionName)).to.be.equal(optionValue);
});
it('should return undefined if env option was not set', function () {
var optionName = 'option_name';
expect(projectConfig.getEnv(optionName)).to.be.undefined;
});
});
describe('setEnv', function () {
it('should set env variable passed as key and value strings', function () {
var optionName = 'option_name';
var optionValue = 'option_value';
projectConfig.setEnv(optionName, optionValue);
expect(projectConfig.getEnv(optionName)).to.be.equal(optionValue);
});
it('should set env variable value as undefined if only variable name provided', function () {
var optionName = 'option_name';
var env;
projectConfig.setEnv(optionName);
env = projectConfig.getEnvValues();
expect(env).to.have.property(optionName);
expect(env[optionName]).to.be.undefined;
});
it('should set env variables passed as env variables hash', function () {
var options = {
foo: 'bar',
fizz: 'buzz'
};
var env;
projectConfig.setEnv(options);
env = projectConfig.getEnvValues();
Object.keys(options).forEach(function (key) {
expect(env).to.have.property(key, options[key]);
});
});
});
describe('getEnvValues', function () {
it('should return env values', function () {
var expectedEnv = {};
var env;
Object.keys(process.env).forEach(function (key) {
expectedEnv[key] = process.env[key];
});
env = projectConfig.getEnvValues();
expect(env).to.be.deep.equal(expectedEnv);
});
});
describe('includeConfig', function () {
var configPath = path.join(__dirname, '../../fixtures/project-configs/project-config.js');
it('should resolve config path before using it', function () {
var nonResolvedConfigPath = '../../fixtures/project-configs/project-config.js';
var expectedPath = configPath;
projectConfig.includeConfig(nonResolvedConfigPath);
expect(projectConfig.getIncludedConfigFilenames()).to.contain(expectedPath);
});
it('should drop require cache for config file before including it', function () {
var expectedModule = { foo: 'bar' };
require.cache[configPath] = expectedModule;
projectConfig.includeConfig(configPath);
expect(require.cache[configPath]).to.exist
.and.to.be.not.equal(expectedModule);
});
it('should require config file and execute it passing self', function () {
projectConfig.includeConfig(configPath);
expect(require(configPath).lastCallParam).to.exist
.and.to.be.equal(projectConfig);
});
it('should add included config filename to included config filenames', function () {
projectConfig.includeConfig(configPath);
expect(projectConfig.getIncludedConfigFilenames()).to.contain(configPath);
});
it('should support method chaining pattern', function () {
var result = projectConfig.includeConfig(configPath);
expect(result).to.be.equal(projectConfig);
});
});
describe('getIncludedConfigFilenames', function () {
var configPath = path.join(__dirname, '../../fixtures/project-configs/project-config.js');
it('should return array containing included config filenames if any configs were included', function () {
projectConfig.includeConfig(configPath);
expect(projectConfig.getIncludedConfigFilenames()).to.be.instanceOf(Array)
.and.to.have.length(1)
.and.to.contain(configPath);
});
it('should return empty array if no configs were included', function () {
expect(projectConfig.getIncludedConfigFilenames()).to.be.instanceOf(Array)
.and.to.be.empty;
});
});
describe('setLevelNamingScheme', function () {
var levelPath = 'level/path';
var schemeBuilder = function () {};
var resolvePathSpy;
beforeEach(function () {
resolvePathSpy = new sinon.spy(projectConfig, 'resolvePath');
});
afterEach(function () {
resolvePathSpy.reset();
});
after(function () {
resolvePathSpy.restore();
});
it('should add level naming scheme to level naming schemes if level path passed as string', function () {
var expectedLevelNamingSchemeName = projectConfig.resolvePath(levelPath);
projectConfig.setLevelNamingScheme(levelPath, schemeBuilder);
expect(projectConfig.getLevelNamingSchemes())
.to.have.property(expectedLevelNamingSchemeName, schemeBuilder);
});
it('should add level naming scheme to level naming schemes if level path passed as array', function () {
var expectedLevelNamingSchemeName = projectConfig.resolvePath(levelPath);
projectConfig.setLevelNamingScheme([levelPath], schemeBuilder);
expect(projectConfig.getLevelNamingSchemes())
.to.have.property(expectedLevelNamingSchemeName, schemeBuilder);
});
it('should add multiple level naming schemes to level naming schemes if level paths passed as ' +
'array', function () {
var anotherLevelPath = 'another/level/path';
var paths = [levelPath, anotherLevelPath];
projectConfig.setLevelNamingScheme(paths, schemeBuilder);
paths.forEach(function (levelPath) {
expect(projectConfig.getLevelNamingSchemes())
.to.have.property(projectConfig.resolvePath(levelPath), schemeBuilder);
});
});
it('should resolve relative level path', function () {
projectConfig.setLevelNamingScheme(levelPath, schemeBuilder);
expect(resolvePathSpy).to.be.calledWith(levelPath);
});
it('should not resolve absolute level path', function () {
var absoluteLevelPath = '/' + levelPath;
projectConfig.setLevelNamingScheme(absoluteLevelPath, schemeBuilder);
expect(resolvePathSpy).to.be.not.called;
});
it('should support method chaining pattern', function () {
var result = projectConfig.setLevelNamingScheme(levelPath, schemeBuilder);
expect(result).to.be.equal(projectConfig);
});
});
describe('getLevelNamingSchemes', function () {
it('should return level naming schemes', function () {
var levelPath = 'level/path';
var expectedLevelPath = projectConfig.resolvePath(levelPath);
var schemeBuilder = function () {};
projectConfig.setLevelNamingScheme(levelPath, schemeBuilder);
expect(projectConfig.getLevelNamingSchemes()).to.be.instanceOf(Object)
.and.to.have.property(expectedLevelPath, schemeBuilder);
});
});
});