-
Notifications
You must be signed in to change notification settings - Fork 13
/
data-provider.js
178 lines (161 loc) · 6.36 KB
/
data-provider.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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/**
* Code lifted from Leche because I didn't get it to work with Karma.
*
* See https://github.com/box/leche#mocha-data-provider for usage instructions.
*
* LIMITATION:
*
* - You can't use data in your dataSets which is created or populated in an outer before() or beforeEach() hook. The
* hooks run _after_ withData() has been invoked.
*
* Tests contained in the withData callback are executed in order, though, so you can use data from outer before() and
* beforeEach() hooks in there.
*
* To clarify the execution order, consider this setup:
*
* var foo=0;
*
* beforeEach( function () { foo = 10 } );
*
* withData( [foo], function ( importedFoo ) {
*
* console.log( foo ); // => prints 0, beforeEach hasn't run yet
* console.log( importedFoo ); // => prints 0, beforeEach hadn't run when the data set for withData
* // was created
*
* describe( "a suite", function () {
*
* console.log( foo ); // => prints 0, beforeEach hasn't run yet
*
* beforeEach( function () {
* console.log( foo ); // => prints 10, beforeEach has run
* } );
*
* it( "is a test", function () {
* console.log( foo ); // => prints 10, beforeEach has run
* } );
*
* } );
*
* } );
*
* tldr; before/beforeEach cannot be used for withData itself, or its data sets. Refer to it only inside tests or
* hooks.
*
* Legal
* -----
*
* Original file available at https://github.com/box/leche
*
* Copyright
* (c) 2014 Box, Inc.
* (c) 2015-2017 Michael Heim, Zeilenwechsel.de
*
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
/**
* A data provider for use with Mocha or Jasmine. Generates describe() blocks. Use this around a call to it() to run the
* test over a series of data.
*
* @throws {Error} if dataset is missing or an empty array
* @param {Object|Array} dataset the data to test
* @param {Function} testFunction the function to call for each piece of data
*/
function describeWithData ( dataset, testFunction ) {
_withData( describe, dataset, testFunction );
}
/**
* A data provider for use with Mocha or Jasmine. Generates it() blocks. Use this around test code which would normally
* be placed into it(). Each key in the data set becomes the name of a test.
*
* @throws {Error} if dataset is missing or an empty array
* @param {Object|Array} dataset the data to test
* @param {Function} testFunction the function to call for each piece of data
*/
function itWithData ( dataset, testFunction ) {
_withData( it, dataset, testFunction );
}
/**
* A data provider for use with Mocha or Jasmine. Use this to run tests over a series of data.
*
* @throws {Error} if dataset is missing or an empty array
* @param {Function} blockFunction the Mocha/Jasmine function to use for generating the block, ie `describe` or `it`
* @param {Object|Array} dataset the data to test
* @param {Function} testFunction the function to call for each piece of data
* @param {string} [prefix=""] prefix for each dataset name (when turned into the test name)
* @param {string} [suffix=""] prefix for each dataset name (when turned into the test name)
*/
function _withData ( blockFunction, dataset, testFunction, prefix, suffix ) {
prefix || ( prefix = "" );
suffix || ( suffix = "" );
// check for missing or null argument
if ( typeof dataset !== 'object' || dataset === null ) {
throw new Error( 'First argument must be an object or non-empty array.' );
}
/*
* The dataset needs to be normalized so it looks like:
* {
* "name1": [ "data1", "data2" ],
* "name2": [ "data3", "data4" ],
* }
*/
var namedDataset = dataset;
if ( dataset instanceof Array ) {
// arrays must have at least one item
if ( dataset.length ) {
namedDataset = createNamedDataset( dataset );
} else {
throw new Error( 'First argument must be an object or non-empty array.' );
}
}
/*
* For each name, create a new describe() or it() block containing the name.
* This causes the dataset info to be output into the console, making
* it easier to determine which dataset caused a problem when there's an
* error.
*/
for ( var name in namedDataset ) {
if ( namedDataset.hasOwnProperty( name ) ) {
//jshint loopfunc:true
blockFunction( prefix + name + suffix, (function ( name ) {
return function () {
var args = namedDataset[name];
if ( !(args instanceof Array) ) {
args = [args];
}
testFunction.apply( this, args );
};
}( name )) );
}
}
}
/**
* Converts an array into an object whose keys are a string representation of the each array item and whose values are
* each array item. This is to normalize the information into an object so that other operations can assume objects are
* always used. For an array like this:
*
* [ "foo", "bar" ]
*
* It creates an object like this:
*
* { "foo": "foo", "bar": "bar" }
*
* If there are duplicate values in the array, only the last value is represented in the resulting object.
*
* @param {Array} array the array to convert
* @returns {Object} an object representing the array
* @private
*/
function createNamedDataset ( array ) {
var result = {};
for ( var i = 0, len = array.length; i < len; i++ ) {
result[array[i].toString()] = array[i];
}
return result;
}