From 4a05fcdba22bafc305cf84e7436e7aaf43fa6a1e Mon Sep 17 00:00:00 2001 From: ssube Date: Mon, 28 Oct 2019 22:41:52 -0500 Subject: [PATCH] fix(config/include): handle more errors in include --- src/config/type/Include.ts | 13 +++++++++---- test/config/TestConfig.ts | 17 +++++++++++++++++ test/config/type/TestEnv.ts | 22 ++++++++++++++++++++++ test/config/type/TestInclude.ts | 31 +++++++++++++++++++++++++++++++ test/config/type/TestRegexp.ts | 19 +++++++++++++++++++ test/config/type/include.yml | 1 + 6 files changed, 99 insertions(+), 4 deletions(-) create mode 100644 test/config/TestConfig.ts create mode 100644 test/config/type/TestEnv.ts create mode 100644 test/config/type/TestInclude.ts create mode 100644 test/config/type/TestRegexp.ts create mode 100644 test/config/type/include.yml diff --git a/src/config/type/Include.ts b/src/config/type/Include.ts index d21df55..daa11ba 100644 --- a/src/config/type/Include.ts +++ b/src/config/type/Include.ts @@ -13,10 +13,15 @@ export const includeSchema = { export const includeType = new YamlType('!include', { kind: 'scalar', resolve(path: string) { - const canonical = resolvePath(path); - if (existsSync(canonical)) { - return true; - } else { + try { + const canonical = resolvePath(path); + // throws in node 11+ + if (existsSync(canonical)) { + return true; + } else { + throw new NotFoundError('included file does not exist'); + } + } catch (err) { throw new NotFoundError('included file does not exist'); } }, diff --git a/test/config/TestConfig.ts b/test/config/TestConfig.ts new file mode 100644 index 0000000..217747e --- /dev/null +++ b/test/config/TestConfig.ts @@ -0,0 +1,17 @@ +import { expect } from 'chai'; +import { join } from 'path'; + +import { loadConfig } from '../../src/config'; +import { NotFoundError } from '../../src/error/NotFoundError'; +import { describeLeaks, itLeaks } from '../helpers/async'; + +describeLeaks('load config helper', async () => { + itLeaks('should load an existing config', async () => { + const config = await loadConfig('config-stderr.yml', join(__dirname, '..', 'docs')); + expect(config.data.logger.name).to.equal('salty-dog'); + }); + + itLeaks('should throw when config is missing', async () => { + return expect(loadConfig('missing.yml', join(__dirname, '..', 'docs'))).to.eventually.be.rejectedWith(NotFoundError); + }); +}); diff --git a/test/config/type/TestEnv.ts b/test/config/type/TestEnv.ts new file mode 100644 index 0000000..4c0bd8b --- /dev/null +++ b/test/config/type/TestEnv.ts @@ -0,0 +1,22 @@ +import { expect } from 'chai'; + +import { envType } from '../../../src/config/type/Env'; +import { NotFoundError } from '../../../src/error/NotFoundError'; +import { VERSION_INFO } from '../../../src/version'; +import { describeLeaks, itLeaks } from '../../helpers/async'; + +describeLeaks('env config type', async () => { + itLeaks('should throw on missing variables', async () => { + expect(() => { + envType.resolve('DOES_NOT_EXIST_'); + }).to.throw(NotFoundError); + }); + + itLeaks('should resolve existing variables', async () => { + expect(envType.resolve('CI_COMMIT_SHA')).to.equal(true); + }); + + itLeaks('should construct a value from variables', async () => { + expect(envType.construct('CI_COMMIT_SHA')).to.equal(VERSION_INFO.git.commit); + }); +}); diff --git a/test/config/type/TestInclude.ts b/test/config/type/TestInclude.ts new file mode 100644 index 0000000..3025098 --- /dev/null +++ b/test/config/type/TestInclude.ts @@ -0,0 +1,31 @@ +import { expect } from 'chai'; +import { BaseError } from 'noicejs'; +import { join } from 'path'; + +import { includeType } from '../../../src/config/type/Include'; +import { NotFoundError } from '../../../src/error/NotFoundError'; +import { describeLeaks, itLeaks } from '../../helpers/async'; + +const TEST_ROOT = '../test/config/type'; + +describeLeaks('include config type', async () => { + itLeaks('should resolve existing files', async () => { + expect(includeType.resolve(join(TEST_ROOT, 'include.yml'))).to.equal(true); + }); + + itLeaks('should throw when resolving missing files', async () => { + expect(() => { + includeType.resolve(join(TEST_ROOT, 'missing.yml')); + }).to.throw(NotFoundError); + }); + + itLeaks('should construct data from file', async () => { + expect(includeType.construct(join(TEST_ROOT, 'include.yml'))).to.equal('test'); + }); + + itLeaks('should throw when constructing missing files', async () => { + expect(() => { + includeType.construct(join(TEST_ROOT, 'missing.yml')); + }).to.throw(BaseError); + }); +}); diff --git a/test/config/type/TestRegexp.ts b/test/config/type/TestRegexp.ts new file mode 100644 index 0000000..9720197 --- /dev/null +++ b/test/config/type/TestRegexp.ts @@ -0,0 +1,19 @@ +import { expect } from 'chai'; + +import { regexpType } from '../../../src/config/type/Regexp'; +import { describeLeaks, itLeaks } from '../../helpers/async'; + +describeLeaks('regexp config type', async () => { + itLeaks('match slashed strings', async () => { + expect(regexpType.resolve('/foo/')).to.equal(true); + }); + + itLeaks('should match flags', async () => { + const regexp: RegExp = regexpType.construct('/foo/g'); + expect(regexp.flags).to.equal('g'); + }); + + itLeaks('should not match bare strings', async () => { + expect(regexpType.resolve('foo')).to.equal(false); + }); +}); diff --git a/test/config/type/include.yml b/test/config/type/include.yml new file mode 100644 index 0000000..30d74d2 --- /dev/null +++ b/test/config/type/include.yml @@ -0,0 +1 @@ +test \ No newline at end of file