Skip to content

Commit

Permalink
fix(tests): add many more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
djMax committed Oct 17, 2023
1 parent ca2fb35 commit 725376b
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 188 deletions.
1 change: 1 addition & 0 deletions __tests__/malformed/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{
4 changes: 2 additions & 2 deletions src/Factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ import path from 'path';

import caller from 'caller';

import { BaseConfitType, ConfitOptions, IntermediateConfigValue, ShortstopHandler } from './types';
import { BaseConfitType, ConfitOptions, IntermediateConfigValue } from './types';
import { Config } from './Config';
import { isAbsolutePath, loadJsonc, merge } from './common';
import { argv, convenience, environmentVariables } from './provider';
import { resolveConfig, resolveCustom, resolveImport } from './handlers';

export class Factory<ConfigurationType extends object> {
private basedir: string;
private protocols: Record<string, ShortstopHandler | ShortstopHandler[]>;
private protocols: ConfitOptions['protocols'];
private promise: Promise<ConfigurationType & BaseConfitType>;

constructor(options: ConfitOptions) {
Expand Down
4 changes: 1 addition & 3 deletions src/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,7 @@ export async function resolveCustom(
for (const protocol of Object.keys(protocols)) {
const impls = protocols[protocol];
if (Array.isArray(impls)) {
for (const impl of impls) {
shorty.use(protocol, impl);
}
impls.forEach((impl) => shorty.use(protocol, impl));
} else {
shorty.use(protocol, impls);
}
Expand Down
295 changes: 114 additions & 181 deletions src/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -299,198 +299,131 @@ describe('confit', () => {
expect(config.get('tic:tac')).toBe('toe');
expect(config.get('blue')).toBe(true);
});
});

/*
t.test('protocols', function (t) {
var basedir, options;
process.env.NODE_ENV = 'dev';
basedir = path.join(__dirname, 'fixtures', 'defaults');
options = {
basedir: basedir,
protocols: {
path: function (value) {
return path.join(basedir, value);
}
}
};
confit(options).create(function (err, config) {
t.error(err);
// Ensure handler was run correctly on default file
t.equal(config.get('misc'), path.join(basedir, 'config.json'));
t.equal(config.get('path'), path.join(basedir, 'development.json'));
config.use({ path: __filename });
t.equal(config.get('path'), __filename);
t.end();
});
});
t.test('protocols (array)', function (t) {
var basedir, options;
process.env.NODE_ENV = 'dev';
basedir = path.join(__dirname, 'fixtures', 'defaults');
options = {
basedir: basedir,
protocols: {
path: [
function (value) {
return path.join(basedir, value);
},
function (value) {
return value + '!';
}
]
}
};
confit(options).create(function (err, config) {
t.error(err);
// Ensure handler was run correctly on default file
t.equal(config.get('misc'), path.join(basedir, 'config.json!'));
t.equal(config.get('path'), path.join(basedir, 'development.json!'));
config.use({ path: __filename });
t.equal(config.get('path'), __filename);
t.end();
});
});
t.test('error', function (t) {
var basedir, options;
process.env.NODE_ENV = 'dev';
basedir = path.join(__dirname, 'fixtures', 'defaults');
options = {
basedir: basedir,
protocols: {
path: function (value) {
throw new Error('path');
}
}
};
confit(options).create(function (err, config) {
t.ok(err);
t.notOk(config);
t.end();
});
});
t.test('malformed', function (t) {
var basedir = path.join(__dirname, 'fixtures', 'malformed');
confit(basedir).create(function (err, config) {
t.ok(err);
t.notOk(config);
t.end();
});
});
t.test('addOverride', function (t) {
var basedir, factory;
process.env.NODE_ENV = 'test';
basedir = path.join(__dirname, 'fixtures', 'defaults');
factory = confit(basedir);
factory.addOverride('development.json');
factory.addOverride(path.join(basedir, 'supplemental.json'));
factory.create(function (err, config) {
t.error(err);
t.ok(config);
t.equal(config.get('default'), 'config');
t.equal(config.get('override'), 'supplemental');
t.end();
});
});

test('protocols', async () => {
process.env.NODE_ENV = 'dev';
const basedir = path.join(__dirname, '..', '__tests__', 'defaults');
const config = await confit<{
misc: string;
path: string;
}>({
basedir,
protocols: {
path: (value: string) => path.join(basedir, value),
},
}).create();
expect(config.get('misc')).toBe(path.join(basedir, 'config.json'));
expect(config.get('path')).toBe(path.join(basedir, 'development.json'));

config.use({ path: __filename });
expect(config.get('path')).toBe(__filename);
});

t.test('addOverride error', function (t) {
var basedir;
test('protocols (array)', async () => {
process.env.NODE_ENV = 'dev';
const basedir = path.join(__dirname, '..', '__tests__', 'defaults');
const options = {
basedir,
protocols: {
path: [(value: string) => path.join(basedir, value), (value: string) => value + '!'],
},
};

const config = await confit<{
misc: string;
path: string;
}>(options).create();
expect(config.get('misc')).toBe(path.join(basedir, 'config.json!'));
expect(config.get('path')).toBe(path.join(basedir, 'development.json!'));

config.use({ path: __filename });
expect(config.get('path')).toBe(__filename);
});

t.throws(function () {
confit(path.join(__dirname, 'fixtures', 'defaults'))
.addOverride('nonexistent.json');
});
test('error', async () => {
process.env.NODE_ENV = 'dev';
const basedir = path.join(__dirname, '..', '__tests__', 'defaults');
const options = {
basedir,
protocols: {
path: () => {
throw new Error('path');
},
},
};
await expect(confit(options).create()).rejects.toThrow();
});

t.throws(function () {
confit(path.join(__dirname, 'fixtures', 'defaults'))
.addOverride('malformed.json');
});
test('malformed', async () => {
const basedir = path.join(__dirname, '..', '__tests__', 'malformed');
await expect(confit({ basedir }).create()).rejects.toThrow();
});

t.end();
});
test('addOverride', async () => {
process.env.NODE_ENV = 'test';
const basedir = path.join(__dirname, '..', '__tests__', 'defaults');
const config = await confit<{
default: string;
override: string;
}>({ basedir })
.addOverride('development.json')
.addOverride(path.join(basedir, 'supplemental.json'))
.create();

t.test('import: with merging objects in imported files', function(t) {
expect(config.get('default')).toBe('config');
expect(config.get('override')).toBe('supplemental');
});

var basedir = path.join(__dirname, 'fixtures', 'import');
var factory = confit(basedir);
factory.addDefault('override.json');
test('addOverride error', () => {
const basedir = path.join(__dirname, '..', '__tests__', 'defaults');
expect(() => confit({ basedir }).addOverride('nonexistent.json').create()).rejects.toThrow();
expect(() => confit({ basedir }).addOverride('malformed.json').create()).rejects.toThrow();
});

factory.create(function(err, config) {
t.error(err);
t.ok(config);
t.equal(config.get('child:grandchild:secret'), 'santa');
t.equal(config.get('child:grandchild:name'), 'grandchild');
t.equal(config.get('child:grandchild:another'), 'claus');
t.end();
});
});
test('import: with merging objects in imported files', async () => {
const basedir = path.join(__dirname, '..', '__tests__', 'import');
const config = await confit({ basedir }).addDefault('override.json').create();

t.test('precedence', function (t) {
var factory;
var argv = process.argv;
var env = process.env;
expect(config.getUntypedValue('child:grandchild:secret')).toBe('santa');
expect(config.getUntypedValue('child:grandchild:name')).toBe('grandchild');
expect(config.getUntypedValue('child:grandchild:another')).toBe('claus');
});

process.argv = [ 'node', __filename, '--override=argv'];
process.env = {
NODE_ENV: 'development',
override: 'env',
misc: 'env'
};
test('precedence', async () => {
const argv = process.argv;
const env = process.env;
process.argv = ['node', __filename, '--override=argv'];
process.env = {
NODE_ENV: 'development',
override: 'env',
misc: 'env',
};

factory = confit(path.join(__dirname, 'fixtures', 'defaults'));
factory.create(function (err, config) {
t.error(err);
t.ok(config);
t.equal(config.get('override'), 'argv');
t.equal(config.get('misc'), 'env');
process.argv = argv;
process.env = env;
t.end();
});
});
t.test('env ignore', function (t) {
var basedir, options;
var env = process.env = {
NODE_ENV: 'development',
fromlocal: 'config:local',
local: 'motion',
ignoreme: 'file:./path/to/mindyourbusiness'
};
basedir = path.join(__dirname, 'fixtures', 'defaults');
options = {
basedir: basedir,
envignore: ['ignoreme']
};
const basedir = path.join(__dirname, '..', '__tests__', 'defaults');
const factory = confit<{ override: string; misc: string }>({ basedir });
const config = await factory.create();
expect(config.get('override')).toBe('argv');
expect(config.get('misc')).toBe('env');
process.argv = argv;
process.env = env;
});

confit(options).create(function (err, config) {
t.error(err);
// Ensure env is read except for the desired ignored property
t.equal(config.get('fromlocal'), env.local);
t.equal(config.get('ignoreme'), undefined);
t.end();
});
test('env ignore', async () => {
const env = (process.env = {
NODE_ENV: 'development',
fromlocal: 'config:local',
local: 'motion',
ignoreme: 'file:./path/to/mindyourbusiness',
});
t.end();
});*/
const basedir = path.join(__dirname, '..', '__tests__', 'defaults');
const config = await confit<{
fromlocal: string;
ignoreme?: string;
}>({
basedir,
excludeEnvVariables: ['ignoreme'],
}).create();
expect(config.get('fromlocal')).toBe(env.local);
expect(config.get('ignoreme')).toBeUndefined();
});
});
2 changes: 2 additions & 0 deletions src/shortstop/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class ShortstopHandlers {
}

handler.stack.push(implementation as ShortstopHandler);

let removed = false;
return function unuse() {
let idx;
Expand Down Expand Up @@ -109,6 +110,7 @@ class ShortstopHandlers {
if (!handler) {
return data;
}

const stack = this.getStack(handler.protocol);
if (!stack) {
return data;
Expand Down
14 changes: 12 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ export type ShortstopHandler<Input = unknown, Output = unknown> = (
export interface ConfitOptions {
defaults?: string;
basedir?: string;
protocols?: Record<string, ShortstopHandler | ShortstopHandler[]>;
protocols?: Record<
string,
ShortstopHandler | ShortstopHandler[] | ShortstopHandler<string> | ShortstopHandler<string>[]
>;
excludeEnvVariables?: string[];
}

Expand All @@ -20,4 +23,11 @@ export interface BaseConfitType {
};
}

export type IntermediateConfigValue = object | string | number | boolean | null | undefined | IntermediateConfigValue[];
export type IntermediateConfigValue =
| object
| string
| number
| boolean
| null
| undefined
| IntermediateConfigValue[];

0 comments on commit 725376b

Please sign in to comment.