ask-cli
Version:
Alexa Skills Kit (ASK) Command Line Interfaces
331 lines (307 loc) • 13.2 kB
JavaScript
const { expect } = require('chai');
const sinon = require('sinon');
const path = require('path');
const fs = require('fs-extra');
const jsonfile = require('jsonfile');
const ConfigFile = require('@src/model/abstract-config-file');
const yaml = require('@src/model/yaml-parser');
const jsonView = require('@src/view/json-view');
describe('Model test - abstract config file test', () => {
const FIXTURE_PATH = path.join(process.cwd(), 'test', 'unit', 'fixture', 'model');
const JSON_CONFIG_PATH = path.join(FIXTURE_PATH, 'json-config.json');
const YAML_CONFIG_PATH = path.join(FIXTURE_PATH, 'json-config-yaml.yaml');
const CONFIG_FILE = path.join(FIXTURE_PATH, 'cli_config');
describe('# inspect correctness for constructor and content loading', () => {
const NOT_EXISTING_CONFIG_PATH = path.join(FIXTURE_PATH, 'out-of-noWhere.json');
const INVALID_JSON_CONFIG_PATH = path.join(FIXTURE_PATH, 'invalid-json.json');
const INVALID_YAML_CONFIG_PATH = path.join(FIXTURE_PATH, 'invalid-yaml.yaml');
const NOT_SUPPORTED_FILE_PATH = path.join(FIXTURE_PATH, 'unsupported-file-type.notsupport');
it('| init with valid config file name, expect to create a ConfigFile instance successfully', () => {
let configContent, jsonContent;
try {
// call
configContent = new ConfigFile(CONFIG_FILE);
configContent.read();
jsonContent = jsonfile.readFileSync(CONFIG_FILE);
} catch (err) {
expect(err).equal(null);
}
// verify
expect(configContent).to.be.instanceOf(ConfigFile);
expect(configContent.fileType).equal('JSON');
expect(configContent.content).deep.eq(jsonContent);
});
it('| init with valid JSON file path, expect to create a ConfigFile instance successfully', () => {
let configContent, jsonContent;
try {
// call
configContent = new ConfigFile(JSON_CONFIG_PATH);
configContent.read();
jsonContent = jsonfile.readFileSync(JSON_CONFIG_PATH);
} catch (err) {
expect(err).equal(null);
}
// verify
expect(configContent).to.be.instanceOf(ConfigFile);
expect(configContent.fileType).equal('JSON');
expect(configContent.content).deep.eq(jsonContent);
});
it('| init with valid YAML file path, expect to create a ConfigFile instance successfully', () => {
let yamlContent, jsonContent;
try {
// call
yamlContent = new ConfigFile(YAML_CONFIG_PATH);
yamlContent.read();
jsonContent = jsonfile.readFileSync(JSON_CONFIG_PATH);
} catch (err) {
expect(err).equal(null);
}
// verify
expect(yamlContent).to.be.instanceOf(ConfigFile);
expect(yamlContent.fileType).equal('YAML');
expect(yamlContent.content).deep.eq(jsonContent);
});
it('| init with a file path not existing, expect correct error message thrown', () => {
try {
// call
const config = new ConfigFile(NOT_EXISTING_CONFIG_PATH);
config.read();
throw new Error('No error caught but supposed to throw an error when new.');
} catch (err) {
// verify
const expectedError = `File ${NOT_EXISTING_CONFIG_PATH} not exists.`;
expect(err.message.indexOf(expectedError) !== -1).equal(true);
}
});
it('| init with a file path without access permission, expect correct error message thrown', () => {
// setup
fs.chmodSync(JSON_CONFIG_PATH, 0o111);
try {
// call
const config = new ConfigFile(JSON_CONFIG_PATH);
config.read();
throw new Error('No error caught but supposed to throw an error when new.');
} catch (err) {
// verify
const expectedError = `No access to read/write file ${JSON_CONFIG_PATH}.`;
expect(err.message.indexOf(expectedError) !== -1).equal(true);
} finally {
// clear
fs.chmodSync(JSON_CONFIG_PATH, 0o644);
}
});
it('| init with an invalid json file, expect correct error message thrown', () => {
try {
const config = new ConfigFile(INVALID_JSON_CONFIG_PATH);
config.read();
throw new Error('No error caught but supposed to throw an error when new.');
} catch (err) {
const expectedError = `Failed to parse JSON file ${INVALID_JSON_CONFIG_PATH}.`;
expect(err.message.indexOf(expectedError) !== -1).equal(true);
}
});
it('| init with an invalid yaml file, expect correct error message thrown', () => {
try {
const config = new ConfigFile(INVALID_YAML_CONFIG_PATH);
config.read();
throw new Error('No error caught but supposed to throw an error when new.');
} catch (err) {
const expectedError = `Failed to parse YAML file ${INVALID_YAML_CONFIG_PATH}.`;
expect(err.message.indexOf(expectedError) !== -1).equal(true);
}
});
it('| init with a non-supported file type, expect correct error message thrown', () => {
try {
const config = new ConfigFile(NOT_SUPPORTED_FILE_PATH);
config.read();
throw new Error('No error caught but supposed to throw an error when new.');
} catch (err) {
expect(err.message).to.equal(`File type for ${NOT_SUPPORTED_FILE_PATH} is not supported. Only JSON and YAML files are supported.`);
}
});
});
describe('# inspect correctness for withContent method', () => {
const TEST_FILE_PATH = 'any path';
const TEST_CONTENT = { key: 'any content' };
beforeEach(() => {
sinon.stub(fs, 'existsSync');
sinon.stub(fs, 'ensureDirSync');
sinon.stub(fs, 'writeFileSync');
sinon.stub(path, 'dirname');
});
afterEach(() => {
sinon.restore();
});
it('| if file does exist, it is logical error to call this method, throw error out', () => {
// setup
fs.existsSync.returns(true);
path.dirname.returns(TEST_FILE_PATH);
// call
try {
ConfigFile.withContent(TEST_FILE_PATH, TEST_CONTENT);
throw 'Expect this line is not called as it should have failed before this line.';
} catch (e) {
// verify
expect(e.message).equal(`Failed to create file ${TEST_FILE_PATH} as it already exists.`);
}
});
it('| with content of JSON file, expect it will write to file correctly', () => {
// setup
fs.existsSync.returns(false);
path.dirname.returns(JSON_CONFIG_PATH);
// call
try {
ConfigFile.withContent(JSON_CONFIG_PATH, TEST_CONTENT);
} catch (e) {
expect(e).equal(undefined);
}
// verify
expect(fs.writeFileSync.args[0][0]).equal(JSON_CONFIG_PATH);
expect(fs.writeFileSync.args[0][1]).equal(jsonView.toString(TEST_CONTENT));
});
});
describe('# inspect correctness for getProperty method', () => {
const json = new ConfigFile(JSON_CONFIG_PATH);
json.read();
[
{
testCase: 'get property value at first level correctly',
input: ['simpleKey'],
expectation: 'simpleValue'
},
{
testCase: 'get property value in an object correctly',
input: ['objectField', 'internalKey'],
expectation: 'internalValue'
},
{
testCase: 'get property value in an array correctly',
input: ['arrayField', 1],
expectation: 2
},
{
testCase: 'get property value in nested level correctly',
input: ['nested', 'innerArray', 0, 'innerKey'],
expectation: 'treasure'
},
{
testCase: 'get property value which does not exist',
input: ['nested', 5],
expectation: undefined
},
].forEach(({ testCase, input, expectation }) => {
it(`| ${testCase}`, () => {
expect(json.getProperty(input)).equal(expectation);
});
});
});
describe('# inspect correctness for setProperty method', () => {
const json = new ConfigFile(JSON_CONFIG_PATH);
json.read();
[
{
testCase: 'set value for property correctly',
inputPath: ['simpleKey'],
inputValue: 'dummy'
},
{
testCase: 'set value for property inside an object correctly',
inputPath: ['objectField', 'internalKey'],
inputValue: 'dummy'
},
{
testCase: 'set value for property inside an array correctly',
inputPath: ['arrayField', 0],
inputValue: 'dummy'
},
{
testCase: 'set value for property in nested level correctly',
inputPath: ['nested', 'innerArray', 0, 'innerKey'],
inputValue: 'dummy'
},
{
testCase: 'set value for property not existing',
inputPath: ['newField'],
inputValue: 'dummy'
},
].forEach(({ testCase, inputPath, inputValue }) => {
it(`| ${testCase}`, () => {
const copy = json.getProperty(inputPath);
json.setProperty(inputPath, inputValue);
expect(json.getProperty(inputPath)).equal(inputValue);
json.setProperty(inputPath, copy);
expect(json.getProperty(inputPath)).equal(copy);
});
});
});
describe('# inspect correctness for write method', () => {
it('| write to JSON file successfully', () => {
// setup
const jsonConfig = new ConfigFile(JSON_CONFIG_PATH);
jsonConfig.read();
const propertyPath = ['simpleKey'];
const copy = jsonConfig.getProperty(propertyPath);
jsonConfig.setProperty(propertyPath, 'notSimpleValue');
// call
jsonConfig.write();
// verify
const verifyConfig = new ConfigFile(JSON_CONFIG_PATH);
verifyConfig.read();
expect(verifyConfig.getProperty(propertyPath)).equal('notSimpleValue');
// clear
jsonConfig.setProperty(propertyPath, copy);
jsonConfig.write();
});
it('| write to YAML file successfully', () => {
// setup
const yamlConfig = new ConfigFile(YAML_CONFIG_PATH);
yamlConfig.read();
const propertyPath = ['simpleKey'];
const copy = yamlConfig.getProperty(propertyPath);
yamlConfig.setProperty(propertyPath, 'notSimpleValue');
// call
yamlConfig.write();
// verify
const verifyConfig = new ConfigFile(YAML_CONFIG_PATH);
verifyConfig.read();
expect(verifyConfig.getProperty(propertyPath)).equal('notSimpleValue');
// clear
yamlConfig.setProperty(propertyPath, copy);
yamlConfig.write();
});
it('| expect error thrown when fs writeFileSync fails', () => {
// setup
sinon.stub(fs, 'writeFileSync');
fs.writeFileSync.throws('error');
try {
// call
const json = new ConfigFile(JSON_CONFIG_PATH);
json.read();
json.write();
} catch (err) {
// verify
expect(err).match(/error/);
} finally {
// clear
sinon.restore();
}
});
it('| expect error thrown when yaml dump fails', () => {
// setup
sinon.stub(yaml, 'dump');
yaml.dump.throws(new Error('load error'));
try {
// call
const yamlConfig = new ConfigFile(YAML_CONFIG_PATH);
yamlConfig.read();
yamlConfig.write();
} catch (err) {
// verify
expect(err.message).equal('load error');
} finally {
// clear
sinon.restore();
}
});
});
});