Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/1.0.0/code coverage #107

Merged
merged 9 commits into from
Jan 5, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/output/couchbase.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export default class Couchbase extends Base {
const { server, bucket, password, timeout } = this.output_options;
return new Promise((resolve, reject) => {
this.bucket = this.cluster.openBucket(bucket, password, (err) => {
/* istanbul ignore if : to hard to test since this is a third party function */
if (err) return reject(err);

this.log('verbose', `Connection to '${bucket}' bucket at '${server}' was successful`);
Expand Down
27 changes: 10 additions & 17 deletions app/output/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -142,15 +142,13 @@ export default class Output extends Base {
///# @description This is used to validate the output options
///# @throws {error} - If an option that was passed is invalid.
validateOutputOptions() {
for (let option in this.output_options) {
if (this.output_options.hasOwnProperty(option)) {
try {
validate[option](this.output_options[option], this.output_options);
} catch (e) {
this.log('error', e);
}
to.each(this.output_options, ({ key, value }) => {
try {
validate[key](value, this.output_options);
} catch (e) {
this.log('error', e);
}
}
});
}
}

Expand Down Expand Up @@ -206,10 +204,9 @@ export const validate = {
///# @arg {number} option - The option to validate against
///# @throws {error} - If the limit option that was pass was invalid
limit(option) {
if (is.number(option)) {
return;
if (!is.number(option)) {
throw new Error('The limit option must be a number');
}
throw new Error('The limit option must be a number');
},

///# @name archive
Expand Down Expand Up @@ -245,7 +242,6 @@ export const validate = {

if (archive === true) {
throw new Error(`The archive option can't be used with ${option}`);
return;
}

isString(option, 'server');
Expand Down Expand Up @@ -292,10 +288,9 @@ export const validate = {
///# @arg {number} option - The option to validate against
///# @throws {error} - If the limit option that was pass was invalid
timeout(option) {
if (is.number(option)) {
return;
if (!is.number(option)) {
throw new Error('The timeout option must be a number');
}
throw new Error('The timeout option must be a number');
},
};

Expand All @@ -321,13 +316,11 @@ export function isString(option, name = '') {
}
if (!is.string(option)) {
throw new Error(`The${name}option must be a string`);
return false;
} else if (
is.string(option) &&
!option.length
) {
throw new Error(`The${name}option must have a length`);
return false;
}
return true;
}
4 changes: 3 additions & 1 deletion app/output/sync-gateway.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default class SyncGateway extends Base {
///# wait for it to be done before it starts saving data.
///# @returns {promise} - The setup function that was called
///# @async
/* istanbul ignore next */
prepare() {
this.preparing = true;
this.preparing = this.setup();
Expand All @@ -38,6 +39,7 @@ export default class SyncGateway extends Base {
///# @description
///# This is used to setup the saving function that will be used.
///# @async
/* istanbul ignore next */
setup() {
// if this.prepare hasn't been called then run it first.
if (this.preparing == null) {
Expand Down Expand Up @@ -141,8 +143,8 @@ export default class SyncGateway extends Base {
export function request(options = {}) {
return new Promise((resolve, reject) => {
req(options, (err, res, body) => {
/* istanbul ignore next : to hard to mock test */
if (err) return reject(err);

resolve([ res, body ]);
});
});
Expand Down
68 changes: 20 additions & 48 deletions app/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ export function objectSearch(data, pattern, current_path, paths = []) {
}
if (Array.isArray(data)) {
for (let i = 0; i < data.length; i++) {
let test_path = appendPath(current_path, i);
const test_path = appendPath(current_path, i);
if (
test_path.match(pattern) &&
paths.indexOf(test_path) === -1
!paths.includes(test_path)
) {
paths.push(test_path);
}
Expand All @@ -44,10 +44,10 @@ export function objectSearch(data, pattern, current_path, paths = []) {
) {
for (let key in data) {
if (data.hasOwnProperty(key)) {
let test_path = appendPath(current_path, key);
const test_path = appendPath(current_path, key);
if (
test_path.match(pattern) &&
paths.indexOf(test_path) === -1
!paths.includes(test_path)
) {
paths.push(test_path);
}
Expand Down Expand Up @@ -242,6 +242,7 @@ parsers.cson = {
parse: (obj) => {
return new Promise((resolve, reject) => {
cson.parse(obj, {}, (err, result) => {
/* istanbul ignore next */
if (err) {
return reject(err);
}
Expand Down Expand Up @@ -272,12 +273,14 @@ parsers.csv = {
// `"{\"latitude\":-6.081689835,\"longitude\":145.3919983,\"level-2\":{\"level-3\":\"woohoo\"}}"`
// it also doesn't handle numbers correctly so this fixes those instances as well
function fix(a, b) {
/* istanbul ignore if : too hard to create a test case for it */
if (!a || !b) {
return a;
}

for (let k in b) { // eslint-disable-line
if (b.hasOwnProperty(k)) {
/* istanbul ignore if : too hard to create a test case for it */
if (is.plainObject(b[k])) {
a[k] = is.plainObject(a[k]) ? fix(a[k], b[k]) : b[k];
} else if (is.string(b[k]) && /^[0-9]+$/.test(b[k])) {
Expand Down Expand Up @@ -377,6 +380,7 @@ export class Logger {
args.unshift(type);
type = 'log';
}
args = args.join('\n');

if (type === 'verbose') {
if (!this.options.verbose) return;
Expand All @@ -390,10 +394,10 @@ export class Logger {
process.stdout.write(stamp);
}

console[type](...args);
console.log(args);

if (type === 'error') {
throw new Error(args.join('\n'));
throw new Error(args);
}
}
return this;
Expand All @@ -411,57 +415,21 @@ export class Logger {
if (symbols[type]) {
stamp += `${symbols[type]} `;
}
if ([ 'error', 'warning', 'warn', 'info' ].includes(type)) {
if ([ 'error', 'warning', 'info' ].includes(type)) {
stamp += `${chalk[color](type)}: `;
}

return stamp;
}

///# @name error
///# @description This is an alias for `this.log('error', 'message.....')
///# @arg {*} ...args - The message that should be passed
///# @chainable
error(...args) {
this.log('error', ...args);
return this;
}

///# @name warn
///# @description This is an alias for `this.log('warn', 'message.....')
///# @arg {*} ...args - The message that should be passed
///# @chainable
warn(...args) {
this.log('warning', ...args);
return this;
}

///# @name info
///# @description This is an alias for `this.log('info', 'message.....')
///# @arg {*} ...args - The message that should be passed
///# @chainable
info(...args) {
this.log('info', ...args);
return this;
}

///# @name verbose
///# @description This is an alias for `this.log('verbose', 'message.....')
///# @arg {*} ...args - The message that should be passed
///# @chainable
verbose(...args) {
this.log('info', ...args);
return this;
}

///# @name time
///# @description
///# This does the same thing as `console.time`.
///# @arg {string} label - This is the label for your timed event
///# @chainable
time(label) {
if (!label) {
return this.error('You must pass in a label for `Logger.prototype.time`', (new Error()).trace);
return this.log('error', 'You must pass in a label for `Logger.prototype.time`');
}
perfy.start(label);
return this;
Expand All @@ -474,15 +442,19 @@ export class Logger {
///# @returns {string} - The total time it took to run the process
timeEnd(label) {
if (!label) {
return this.error('You must pass in a label for `Logger.prototype.timeEnd`', (new Error()).trace);
return this.log('error', 'You must pass in a label for `Logger.prototype.timeEnd`');
}
let time = perfy.end(label).time;
const result = perfy.end(label);
let suffix = 's';
let time;
// convert to milliseconds
if (time < 1) {
time *= Math.pow(10, 1);
if (result.time < 1) {
time = result.milliseconds;
suffix = 'ms';
} else {
time = result.time;
}

time = `+${time.toFixed(2)}${suffix}`;
return `${chalk.cyan(time)}`;
}
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@
"joi": "~10.0.5",
"jsondiffpatch": "~0.2.4",
"lint-rules": "github:ma-shop/lint-rules",
"nock": "~9.0.2",
"nyc": "~9.0.1",
"proxyquire": "~1.7.10",
"test-console": "~1.0.0"
Expand Down
36 changes: 26 additions & 10 deletions test/output/couchbase.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ test('without args', (t) => {
t.is(t.context.prepared, false);
t.is(typeof t.context.prepare, 'function');
t.is(typeof t.context.output, 'function');
t.is(t.context.cluster.constructor.name, 'MockCluster');
});

test('prepare', async (t) => {
Expand All @@ -36,16 +37,18 @@ test('prepare', async (t) => {
t.is(t.context.bucket.connected, true);
});

test('setup', async (t) => {
t.is(t.context.prepared, false);
t.is(t.context.preparing, undefined);
const preparing = t.context.setup();
t.is(typeof t.context.preparing.then, 'function');
t.is(t.context.prepared, false);
await preparing;
t.is(t.context.prepared, true);
t.is(to.type(t.context.bucket), 'object');
t.is(t.context.bucket.connected, true);
test.group('setup', (test) => {
test(async (t) => {
t.is(t.context.prepared, false);
t.is(t.context.preparing, undefined);
const preparing = t.context.setup();
t.is(typeof t.context.preparing.then, 'function');
t.is(t.context.prepared, false);
t.falsy(await preparing);
t.is(t.context.prepared, true);
t.is(to.type(t.context.bucket), 'object');
t.is(t.context.bucket.connected, true);
});
});

test.group('output', (test) => {
Expand Down Expand Up @@ -130,6 +133,19 @@ test.group('output', (test) => {
t.deepEqual(document.value, data);
});
}

test('prepare has started but isn\'t complete', async (t) => {
const language = 'json';
const data = languages[language];
t.context.output_options.bucket = `output-${language}`;
const id = `1234567890-${language}`;
t.context.output_options.format = language;
t.context.prepare();
await t.context.output(id, data);
const document = await t.context.bucket.getAsync(id);
t.not(document, null);
t.deepEqual(document.value, data);
});
});

test.group('finalize', (test) => {
Expand Down
40 changes: 29 additions & 11 deletions test/output/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,13 +204,33 @@ test.group('validation', (test) => {
t.throws(validateArchive);
t.throws(t.context.validateOutputOptions);
});

test.serial('failing output because `archive` isn\'t a `.zip` file', (t) => {
t.context.output_options.archive = 'somefile.woohoo';
t.context.output_options.output = 'somefolder';
const validateArchive = () => validate.archive(t.context.output_options.archive, t.context.output_options);
const validateOutputOptions = () => t.context.validateOutputOptions();
const inspect = stdout.inspect();
t.throws(validateArchive);
t.throws(validateOutputOptions);
inspect.restore();
});

test('failing output is console', (t) => {
t.context.output_options.output = 'console';
t.context.output_options.archive = 'somefile.zip';
const validateArchive = () => validate.archive(t.context.output_options.archive, t.context.output_options);
t.throws(validateArchive);
t.throws(t.context.validateOutputOptions);
});

test('failing output a string wasn\'t passed as the option', (t) => {
t.context.output_options.output = 'test-folder';
t.context.output_options.archive = [];
const validateArchive = () => validate.archive(t.context.output_options.archive, t.context.output_options);
t.throws(validateArchive);
t.throws(t.context.validateOutputOptions);
});
});

test.group('server', (test) => {
Expand Down Expand Up @@ -249,6 +269,7 @@ test.group('validation', (test) => {
t.context.output_options.output = 'couchbase';
t.context.output_options.archive = true;
t.context.output_options.server = '127.0.0.1';

const validateServer = () => validate.server(t.context.output_options.server, t.context.output_options);
t.throws(validateServer);
t.throws(t.context.validateOutputOptions);
Expand Down Expand Up @@ -582,21 +603,18 @@ test.group('output', (test) => {
});
}));


test.group('couchbase', (test) => {
test.todo();
});

test.group('sync-gateway', (test) => {
test.todo();
});
// These are too difficult to unit test but they are tested else where
// test.group('couchbase', (test) => {
// test.todo();
// });
//
// test.group('sync-gateway', (test) => {
// test.todo();
// });

test.after.always(() => fs.remove(root));
});


test.todo('finalize');

// This will loop through each of the languages to run tests for each one.
// It makes it easier to test each language for each type of output rather
// than duplicating the loop on each test
Expand Down
Loading