Skip to content

Commit b1e2b78

Browse files
committed
add expect().toLooseDeepEqual() matcher
1 parent 94847b1 commit b1e2b78

File tree

3 files changed

+66
-43
lines changed

3 files changed

+66
-43
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
"brfs": "^1.4.3",
9595
"browserify": "^13.0.0",
9696
"browserify-transform-tools": "^1.5.1",
97+
"deep-equal": "^1.0.1",
9798
"ecstatic": "^1.4.0",
9899
"eslint": "^3.5.0",
99100
"falafel": "^1.2.0",

test/jasmine/assets/custom_matchers.js

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,53 @@
11
'use strict';
22

33
var isNumeric = require('fast-isnumeric');
4-
4+
var Lib = require('@src/lib');
5+
var deepEqual = require('deep-equal');
56

67
module.exports = {
8+
// toEqual except with sparse arrays populated. This arises because:
9+
//
10+
// var x = new Array(2)
11+
// expect(x).toEqual([undefined, undefined])
12+
//
13+
// will fail assertion even though x[0] === undefined and x[1] === undefined.
14+
// This is because the array elements don't exist until assigned. Of course it
15+
// only fails on *some* platforms (old firefox, looking at you), which is why
16+
// this is worth all the footwork.
17+
toLooseDeepEqual: function() {
18+
function populateUndefinedArrayEls(x) {
19+
var i;
20+
if(Array.isArray(x)) {
21+
for(i = 0; i < x.length; i++) {
22+
x[i] = x[i];
23+
}
24+
} else if(Lib.isPlainObject(x)) {
25+
var keys = Object.keys(x);
26+
for(i = 0; i < keys.length; i++) {
27+
populateUndefinedArrayEls(x[keys[i]]);
28+
}
29+
}
30+
return x;
31+
}
32+
33+
return {
34+
compare: function(actual, expected, msgExtra) {
35+
var actualExpanded = populateUndefinedArrayEls(Lib.extendDeep({}, actual));
36+
var expectedExpanded = populateUndefinedArrayEls(Lib.extendDeep({}, expected));
37+
38+
var passed = deepEqual(actualExpanded, expectedExpanded);
39+
40+
var message = [
41+
'Expected', JSON.stringify(actual), 'to be close to', JSON.stringify(expected), msgExtra
42+
].join(' ');
43+
44+
return {
45+
pass: passed,
46+
message: message
47+
};
48+
}
49+
};
50+
},
751

852
// toBeCloseTo... but for arrays
953
toBeCloseToArray: function() {

test/jasmine/tests/lib_test.js

Lines changed: 20 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,7 @@ var PlotlyInternal = require('@src/plotly');
77
var createGraphDiv = require('../assets/create_graph_div');
88
var destroyGraphDiv = require('../assets/destroy_graph_div');
99
var Plots = PlotlyInternal.Plots;
10-
11-
/* This is a one-off function to fully populate sparse arrays. This arises
12-
* because:
13-
*
14-
* var x = new Array(2)
15-
* expect(x).toEqual([undefined, undefined])
16-
*
17-
* will fail assertion even though x[0] === undefined and x[1] === undefined.
18-
* This is because the array elements don't exist until assigned.
19-
*/
20-
function populateUndefinedArrayEls(x) {
21-
var i;
22-
if(Array.isArray(x)) {
23-
for(i = 0; i < x.length; i++) {
24-
x[i] = x[i];
25-
}
26-
} else if(Lib.isPlainObject(x)) {
27-
var keys = Object.keys(x);
28-
for(i = 0; i < keys.length; i++) {
29-
populateUndefinedArrayEls(x[keys[i]]);
30-
}
31-
}
32-
}
33-
34-
function expectLooseDeepEqual(a, b) {
35-
expect(populateUndefinedArrayEls(a)).toEqual(populateUndefinedArrayEls(b));
36-
}
37-
10+
var customMatchers = require('../assets/custom_matchers');
3811

3912
describe('Test lib.js:', function() {
4013
'use strict';
@@ -504,45 +477,50 @@ describe('Test lib.js:', function() {
504477
});
505478

506479
describe('expandObjectPaths', function() {
480+
beforeAll(function() {
481+
jasmine.addMatchers(customMatchers);
482+
});
483+
507484
it('returns the original object', function() {
508485
var x = {};
509486
expect(Lib.expandObjectPaths(x)).toBe(x);
510487
});
511488

512489
it('unpacks top-level paths', function() {
513490
var input = {'marker.color': 'red', 'marker.size': [1, 2, 3]};
514-
var expected = {marker: {color: 'red', size: [1, 2, 3]}};
515-
expectLooseDeepEqual(Lib.expandObjectPaths(input), expected);
491+
var expected = {marker: {color: 'red', size: [1, 2, 4]}};
492+
expect(Lib.expandObjectPaths(input)).toLooseDeepEqual(expected);
516493
});
494+
return;
517495

518496
it('unpacks recursively', function() {
519497
var input = {'marker.color': {'red.certainty': 'definitely'}};
520498
var expected = {marker: {color: {red: {certainty: 'definitely'}}}};
521-
expectLooseDeepEqual(Lib.expandObjectPaths(input), expected);
499+
expect(Lib.expandObjectPaths(input)).toLooseDeepEqual(expected);
522500
});
523501

524502
it('unpacks deep paths', function() {
525503
var input = {'foo.bar.baz': 'red'};
526504
var expected = {foo: {bar: {baz: 'red'}}};
527-
expectLooseDeepEqual(Lib.expandObjectPaths(input), expected);
505+
expect(Lib.expandObjectPaths(input)).toLooseDeepEqual(expected);
528506
});
529507

530508
it('unpacks non-top-level deep paths', function() {
531509
var input = {color: {'foo.bar.baz': 'red'}};
532510
var expected = {color: {foo: {bar: {baz: 'red'}}}};
533-
expectLooseDeepEqual(Lib.expandObjectPaths(input), expected);
511+
expect(Lib.expandObjectPaths(input)).toLooseDeepEqual(expected);
534512
});
535513

536514
it('merges dotted properties into objects', function() {
537515
var input = {marker: {color: 'red'}, 'marker.size': 8};
538516
var expected = {marker: {color: 'red', size: 8}};
539-
expectLooseDeepEqual(Lib.expandObjectPaths(input), expected);
517+
expect(Lib.expandObjectPaths(input)).toLooseDeepEqual(expected);
540518
});
541519

542520
it('merges objects into dotted properties', function() {
543521
var input = {'marker.size': 8, marker: {color: 'red'}};
544522
var expected = {marker: {color: 'red', size: 8}};
545-
expectLooseDeepEqual(Lib.expandObjectPaths(input), expected);
523+
expect(Lib.expandObjectPaths(input)).toLooseDeepEqual(expected);
546524
});
547525

548526
it('retains the identity of nested objects', function() {
@@ -568,49 +546,49 @@ describe('Test lib.js:', function() {
568546
it('expands bracketed array notation', function() {
569547
var input = {'marker[1]': {color: 'red'}};
570548
var expected = {marker: [undefined, {color: 'red'}]};
571-
expectLooseDeepEqual(Lib.expandObjectPaths(input), expected);
549+
expect(Lib.expandObjectPaths(input)).toLooseDeepEqual(expected);
572550
});
573551

574552
it('expands nested arrays', function() {
575553
var input = {'marker[1].range[1]': 5};
576554
var expected = {marker: [undefined, {range: [undefined, 5]}]};
577555
var computed = Lib.expandObjectPaths(input);
578-
expectLooseDeepEqual(computed, expected);
556+
expect(computed).toLooseDeepEqual(expected);
579557
});
580558

581559
it('expands bracketed array with more nested attributes', function() {
582560
var input = {'marker[1]': {'color.alpha': 2}};
583561
var expected = {marker: [undefined, {color: {alpha: 2}}]};
584562
var computed = Lib.expandObjectPaths(input);
585-
expectLooseDeepEqual(computed, expected);
563+
expect(computed).toLooseDeepEqual(expected);
586564
});
587565

588566
it('expands bracketed array notation without further nesting', function() {
589567
var input = {'marker[1]': 8};
590568
var expected = {marker: [undefined, 8]};
591569
var computed = Lib.expandObjectPaths(input);
592-
expectLooseDeepEqual(computed, expected);
570+
expect(computed).toLooseDeepEqual(expected);
593571
});
594572

595573
it('expands bracketed array notation with further nesting', function() {
596574
var input = {'marker[1].size': 8};
597575
var expected = {marker: [undefined, {size: 8}]};
598576
var computed = Lib.expandObjectPaths(input);
599-
expectLooseDeepEqual(computed, expected);
577+
expect(computed).toLooseDeepEqual(expected);
600578
});
601579

602580
it('expands bracketed array notation with further nesting', function() {
603581
var input = {'marker[1].size.magnitude': 8};
604582
var expected = {marker: [undefined, {size: {magnitude: 8}}]};
605583
var computed = Lib.expandObjectPaths(input);
606-
expectLooseDeepEqual(computed, expected);
584+
expect(computed).toLooseDeepEqual(expected);
607585
});
608586

609587
it('combines changes with single array nesting', function() {
610588
var input = {'marker[1].foo': 5, 'marker[0].foo': 4};
611589
var expected = {marker: [{foo: 4}, {foo: 5}]};
612590
var computed = Lib.expandObjectPaths(input);
613-
expectLooseDeepEqual(computed, expected);
591+
expect(computed).toLooseDeepEqual(expected);
614592
});
615593

616594
// TODO: This test is unimplemented since it's a currently-unused corner case.

0 commit comments

Comments
 (0)