-
Notifications
You must be signed in to change notification settings - Fork 159
/
addContext.js
117 lines (104 loc) · 3.24 KB
/
addContext.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
const isObject = require('lodash/isObject');
const isEmpty = require('lodash/isEmpty');
const chalk = require('chalk');
const stringify = require('json-stringify-safe');
const errorPrefix = 'Error adding context:';
const ERRORS = {
INVALID_ARGS: `${errorPrefix} Invalid arguments.`,
INVALID_TEST: `${errorPrefix} Invalid test object.`,
INVALID_CONTEXT: ctx => {
const expected = 'Expected a string or an object of shape { title: string, value: any } but saw:';
return `${errorPrefix} ${expected}\n${stringify(ctx, (key, val) => (val === undefined ? 'undefined' : val), 2)}`;
}
};
/**
* HELPER FUNCTIONS
*/
/* istanbul ignore next */
function log(msg, level) {
const logMethod = console[level] || console.log;
let out = msg;
if (typeof msg === 'object') {
out = stringify(msg, null, 2);
}
logMethod(`[${chalk.gray('mochawesome')}] ${out}\n`);
}
function _isValidContext(ctx) {
/*
* Context is valid if any of the following are true:
* 1. Type is string and it is not empty
* 2. Type is object and it has properties `title` and `value` and `title` is not empty
*/
if (!ctx) return false;
return ((typeof ctx === 'string') && !isEmpty(ctx))
|| (Object.hasOwnProperty.call(ctx, 'title') && !isEmpty(ctx.title) && Object.hasOwnProperty.call(ctx, 'value'));
}
/**
* Add context to the test object so it can
* be displayed in the mochawesome report
*
* @param {Object} test object
* @param {String|Object} context to add
* If context is an object, it must have the shape:
* {
* title: string that is used as context title in the report
* value: the context that is to be added
* }
*
* Usage:
*
* it('should test something', function () {
* someFunctionThatTestsCode();
*
* addContext(this, 'some context to add');
*
* addContext(this, {
* title: 'Expected number of something'
* value: 42
* });
*
* assert('something');
* });
*
*/
const addContext = function (...args) {
// Check args to see if we should bother continuing
if ((args.length !== 2) || !isObject(args[0])) {
log(ERRORS.INVALID_ARGS, 'error');
return;
}
const ctx = args[1];
// Ensure that context meets the requirements
if (!_isValidContext(ctx)) {
log(ERRORS.INVALID_CONTEXT(ctx), 'error');
return;
}
/* Context is valid, now get the test object
* If `addContext` is called from inside a `beforeEach` or `afterEach`
* the test object will be `.currentTest`, otherwise just `.test`
*/
const test = args[0].currentTest || args[0].test;
if (!test) {
log(ERRORS.INVALID_TEST, 'error');
return;
}
/* If context is an object, and value is `undefined`
* change it to 'undefined' so it can be displayed
* correctly in the report
*/
if (ctx.title && ctx.value === undefined) {
ctx.value = 'undefined';
}
// Test doesn't already have context -> set it
if (!test.context) {
test.context = ctx;
} else if (Array.isArray(test.context)) {
// Test has context and context is an array -> push new context
test.context.push(ctx);
} else {
// Test has context and it is not an array -> make it an array, then push new context
test.context = [ test.context ];
test.context.push(ctx);
}
};
module.exports = addContext;