Skip to content

Commit 8dc92d8

Browse files
rpgeeganagevieiralucas
authored andcommitted
Adding operator attribute to assertion error (#1257)
* feat: adding operator attribute to assertion error You can set the operator as mentioned below. flag(this, 'operator', MYOPERATOR). for example, flag(obj, 'operator', 'notEqual')
1 parent 1958341 commit 8dc92d8

File tree

5 files changed

+363
-2
lines changed

5 files changed

+363
-2
lines changed

lib/chai/assertion.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,21 @@ module.exports = function (_chai, util) {
138138
if (!ok) {
139139
msg = util.getMessage(this, arguments);
140140
var actual = util.getActual(this, arguments);
141-
throw new AssertionError(msg, {
141+
var assertionErrorObjectProperties = {
142142
actual: actual
143143
, expected: expected
144144
, showDiff: showDiff
145-
}, (config.includeStack) ? this.assert : flag(this, 'ssfi'));
145+
};
146+
147+
var operator = util.getOperator(this, arguments);
148+
if (operator) {
149+
assertionErrorObjectProperties.operator = operator;
150+
}
151+
152+
throw new AssertionError(
153+
msg,
154+
assertionErrorObjectProperties,
155+
(config.includeStack) ? this.assert : flag(this, 'ssfi'));
146156
}
147157
};
148158

lib/chai/utils/getOperator.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
var type = require('type-detect');
2+
3+
var flag = require('./flag');
4+
5+
function isObjectType(obj) {
6+
var objectType = type(obj);
7+
var objectTypes = ['Array', 'Object', 'function'];
8+
9+
return objectTypes.indexOf(objectType) !== -1;
10+
}
11+
12+
/**
13+
* ### .getOperator(message)
14+
*
15+
* Extract the operator from error message.
16+
* Operator defined is based on below link
17+
* https://nodejs.org/api/assert.html#assert_assert.
18+
*
19+
* Returns the `operator` or `undefined` value for an Assertion.
20+
*
21+
* @param {Object} object (constructed Assertion)
22+
* @param {Arguments} chai.Assertion.prototype.assert arguments
23+
* @namespace Utils
24+
* @name getOperator
25+
* @api public
26+
*/
27+
28+
module.exports = function getOperator(obj, args) {
29+
var operator = flag(obj, 'operator');
30+
var negate = flag(obj, 'negate');
31+
var expected = args[3];
32+
var msg = negate ? args[2] : args[1];
33+
34+
if (operator) {
35+
return operator;
36+
}
37+
38+
if (typeof msg === 'function') msg = msg();
39+
40+
msg = msg || '';
41+
if (!msg) {
42+
return undefined;
43+
}
44+
45+
if (/\shave\s/.test(msg)) {
46+
return undefined;
47+
}
48+
49+
var isObject = isObjectType(expected);
50+
if (/\snot\s/.test(msg)) {
51+
return isObject ? 'notDeepStrictEqual' : 'notStrictEqual';
52+
}
53+
54+
return isObject ? 'deepStrictEqual' : 'strictEqual';
55+
};

lib/chai/utils/index.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,9 @@ exports.isProxyEnabled = require('./isProxyEnabled');
170170
*/
171171

172172
exports.isNaN = require('./isNaN');
173+
174+
/*!
175+
* getOperator method
176+
*/
177+
178+
exports.getOperator = require('./getOperator');

test/globalErr.js

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,115 @@ describe('globalErr', function () {
4343
});
4444
});
4545

46+
it('should pass operator if possible during none object comparison', function () {
47+
err(function () {
48+
expect('cat').to.equal('dog');
49+
}, {
50+
message: 'expected \'cat\' to equal \'dog\''
51+
, expected: 'dog'
52+
, actual: 'cat'
53+
, operator: 'strictEqual'
54+
});
55+
56+
err(function () {
57+
expect('cat').to.not.equal('cat');
58+
}, {
59+
message: 'expected \'cat\' to not equal \'cat\''
60+
, expected: 'cat'
61+
, actual: 'cat'
62+
, operator: 'notStrictEqual'
63+
});
64+
});
65+
66+
it('should pass operator if possible during plain object comparison', function () {
67+
var val1 = {
68+
propVal1: 'val1'
69+
};
70+
71+
var val2 = {
72+
propVal2: 'val2'
73+
};
74+
75+
err(function () {
76+
expect(val1).to.equal(val2);
77+
}, {
78+
message: "expected { propVal1: 'val1' } to equal { propVal2: 'val2' }"
79+
, expected: val2
80+
, actual: val1
81+
, operator: 'deepStrictEqual'
82+
});
83+
84+
err(function () {
85+
expect(val1).to.not.equal(val1);
86+
}, {
87+
message: "expected { propVal1: 'val1' } to not equal { propVal1: 'val1' }"
88+
, expected: val1
89+
, actual: val1
90+
, operator: 'notDeepStrictEqual'
91+
});
92+
});
93+
94+
it('should pass operator if possible during function comparison', function () {
95+
function f1 () {
96+
this.propF1 = 'propF1';
97+
}
98+
99+
function f2 () {
100+
this.propF2 = 'propF2';
101+
}
102+
103+
err(function () {
104+
expect(f1).to.equal(f2);
105+
}, {
106+
message: "expected [Function: f1] to equal [Function: f2]"
107+
, expected: f2
108+
, actual: f1
109+
, operator: 'deepStrictEqual'
110+
});
111+
112+
err(function () {
113+
expect(f1).to.not.equal(f1);
114+
}, {
115+
message: "expected [Function: f1] to not equal [Function: f1]"
116+
, expected: f1
117+
, actual: f1
118+
, operator: 'notDeepStrictEqual'
119+
});
120+
});
121+
122+
it('should pass operator if possible during object comparison', function () {
123+
var val1 = [
124+
'string1'
125+
, 'string2'
126+
, 'string3'
127+
, 'string4'
128+
];
129+
130+
var val2 = [
131+
'string5'
132+
, 'string6'
133+
, 'string7'
134+
, 'string8'
135+
];
136+
err(function () {
137+
expect(val1).to.equal(val2);
138+
}, {
139+
message: 'expected [ Array(4) ] to equal [ Array(4) ]'
140+
, expected: val2
141+
, actual: val1
142+
, operator: 'deepStrictEqual'
143+
});
144+
145+
err(function () {
146+
expect(val1).to.not.equal(val1);
147+
}, {
148+
message: 'expected [ Array(4) ] to not equal [ Array(4) ]'
149+
, expected: val1
150+
, actual: val1
151+
, operator: 'notDeepStrictEqual'
152+
});
153+
});
154+
46155
it('should throw if regex val does not match error message', function () {
47156
err(function () {
48157
err(function () { throw new Err('cat') }, /dog/);

test/utilities.js

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1334,4 +1334,185 @@ describe('utilities', function () {
13341334
});
13351335
}
13361336
});
1337+
1338+
describe('getOperator', function() {
1339+
it('Must return operator if the "operator" flag is set', function() {
1340+
chai.use(function(_chai, _) {
1341+
expect(_.getOperator({}, [])).to.equal(undefined);
1342+
expect(_.getOperator({}, [null, null, null])).to.equal(undefined);
1343+
1344+
var obj = {};
1345+
_.flag(obj, 'operator', 'my-operator');
1346+
expect(_.getOperator(obj, [])).to.equal('my-operator');
1347+
});
1348+
});
1349+
1350+
it('Must return undefined if message is partial assertions', function() {
1351+
chai.use(function(_chai, _) {
1352+
expect(
1353+
_.getOperator({}, [null, 'to have the same ordered', null, 'test'])
1354+
).to.equal(undefined);
1355+
});
1356+
});
1357+
1358+
it('Must return deepStrictEqual if "expected" is a object and assertion is for equal', function() {
1359+
chai.use(function(_chai, _) {
1360+
var expected = Object.create({
1361+
dummyProperty1: 'dummyProperty1',
1362+
dummyProperty2: 'dummyProperty2',
1363+
dummyProperty3: 'dummyProperty3'
1364+
});
1365+
1366+
var obj = {};
1367+
_.flag(obj, 'negate', false);
1368+
1369+
expect(
1370+
_.getOperator(obj, [
1371+
null,
1372+
'expect #{this} deep equal to #{exp}',
1373+
'expect #{this} not deep equal to #{exp}',
1374+
expected
1375+
])
1376+
).to.equal('deepStrictEqual');
1377+
});
1378+
});
1379+
1380+
it('Must return deepStrictEqual if "expected" is a function and assertion is for equal', function() {
1381+
chai.use(function(_chai, _) {
1382+
function expected () {
1383+
this.prop = 'prop';
1384+
}
1385+
1386+
var obj = {};
1387+
_.flag(obj, 'negate', false);
1388+
1389+
expect(
1390+
_.getOperator(obj, [
1391+
null,
1392+
'expect #{this} deep equal to #{exp}',
1393+
'expect #{this} not deep equal to #{exp}',
1394+
expected
1395+
])
1396+
).to.equal('deepStrictEqual');
1397+
});
1398+
});
1399+
1400+
it('Must return deepStrictEqual if "expected" is an array and assertion is for equal', function() {
1401+
chai.use(function(_chai, _) {
1402+
var expected = [
1403+
'item 1'
1404+
];
1405+
1406+
var obj = {};
1407+
_.flag(obj, 'negate', false);
1408+
1409+
expect(
1410+
_.getOperator(obj, [
1411+
null,
1412+
'expect #{this} deep equal to #{exp}',
1413+
'expect #{this} not deep equal to #{exp}',
1414+
expected
1415+
])
1416+
).to.equal('deepStrictEqual');
1417+
});
1418+
});
1419+
1420+
it('Must return strictEqual if "expected" is a string and assertion is for equal', function() {
1421+
chai.use(function(_chai, _) {
1422+
var expected = 'someString';
1423+
1424+
var obj = {};
1425+
_.flag(obj, 'negate', false);
1426+
1427+
expect(
1428+
_.getOperator(obj, [
1429+
null,
1430+
'expect #{this} equal to #{exp}',
1431+
'expect #{this} not equal to #{exp}',
1432+
expected
1433+
])
1434+
).to.equal('strictEqual');
1435+
});
1436+
});
1437+
1438+
it('Must return notDeepStrictEqual if "expected" is a object and assertion is for inequality', function() {
1439+
chai.use(function(_chai, _) {
1440+
var expected = Object.create({
1441+
dummyProperty1: 'dummyProperty1',
1442+
dummyProperty2: 'dummyProperty2',
1443+
dummyProperty3: 'dummyProperty3'
1444+
});
1445+
1446+
var obj = {};
1447+
_.flag(obj, 'negate', true);
1448+
1449+
expect(
1450+
_.getOperator(obj, [
1451+
null,
1452+
'expect #{this} deep equal to #{exp}',
1453+
'expect #{this} not deep equal to #{exp}',
1454+
expected
1455+
])
1456+
).to.equal('notDeepStrictEqual');
1457+
});
1458+
});
1459+
1460+
it('Must return notDeepStrictEqual if "expected" is a function and assertion is for inequality', function() {
1461+
chai.use(function(_chai, _) {
1462+
function expected () {
1463+
this.prop = 'prop';
1464+
}
1465+
1466+
var obj = {};
1467+
_.flag(obj, 'negate', true);
1468+
1469+
expect(
1470+
_.getOperator(obj, [
1471+
null,
1472+
'expect #{this} deep equal to #{exp}',
1473+
'expect #{this} not deep equal to #{exp}',
1474+
expected
1475+
])
1476+
).to.equal('notDeepStrictEqual');
1477+
});
1478+
});
1479+
1480+
it('Must return notDeepStrictEqual if "expected" is an array and assertion is for inequality', function() {
1481+
chai.use(function(_chai, _) {
1482+
var expected = [
1483+
'item 1'
1484+
];
1485+
1486+
var obj = {};
1487+
_.flag(obj, 'negate', true);
1488+
1489+
expect(
1490+
_.getOperator(obj, [
1491+
null,
1492+
'expect #{this} deep equal to #{exp}',
1493+
'expect #{this} not deep equal to #{exp}',
1494+
expected
1495+
])
1496+
).to.equal('notDeepStrictEqual');
1497+
});
1498+
});
1499+
1500+
it('Must return notStrictEqual if "expected" is a string and assertion is for inequality', function() {
1501+
chai.use(function(_chai, _) {
1502+
var expected = 'someString';
1503+
1504+
var obj = {};
1505+
_.flag(obj, 'negate', true);
1506+
1507+
expect(
1508+
_.getOperator(obj, [
1509+
null,
1510+
'expect #{this} equal to #{exp}',
1511+
'expect #{this} not equal to #{exp}',
1512+
expected
1513+
])
1514+
).to.equal('notStrictEqual');
1515+
});
1516+
});
1517+
});
13371518
});

0 commit comments

Comments
 (0)