Skip to content
Open
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
11 changes: 11 additions & 0 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,17 @@
"contributions": [
"code"
]
},
{
"login": "danielpmichalski",
"name": "Daniel Michalski",
"avatar_url": "https://avatars2.githubusercontent.com/u/5457711?v=4",
"profile": "https://twitter.com/crazyPolishDan",
"contributions": [
"code",
"doc",
"test"
]
}
],
"repoType": "github"
Expand Down
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ If you've come here to help contribute - Thanks! Take a look at the [contributin
- [Array](#array)
- [.toBeArray()](#tobearray)
- [.toBeArrayOfSize()](#tobearrayofsize)
- [.toBeArrayWithFloats([members], ?precision)](#tobearraywithfloatsmembers-precision)
- [.toIncludeAllMembers([members])](#toincludeallmembersmembers)
- [.toIncludeAnyMembers([members])](#toincludeanymembersmembers)
- [.toIncludeSameMembers([members])](#toincludesamemembersmembers)
Expand Down Expand Up @@ -272,6 +273,17 @@ test('passes when value is an array', () => {
});
```

#### .toBeArrayWithFloats([members], ?precision)

Use `.toBeArrayWithFloats` when comparing arrays of floating-point numbers with chosen precision in the same order.

```js
test('passes when arrays have same floats', () => {
expect([1.11112, 2.22221]).toBeArrayWithFloats([1.11114, 2.22223]); // default 4-digit decimal precision
expect([1.112]).not.toBeArrayWithFloats([1.111], 3); // specified 3-digit decimal precision
});
```

#### .toIncludeAllMembers([members])

Use `.toIncludeAllMembers` when checking if an `Array` contains all of the same members of a given set.
Expand Down Expand Up @@ -927,7 +939,7 @@ test('passes when value includes all substrings', () => {
| [<img src="https://avatars1.githubusercontent.com/u/10330923?v=4" width="100px;"/><br /><sub>Amish Shah</sub>](https://hydrabolt.me/)<br />[💻](https://github.com/mattphillips/jest-extended/commits?author=hydrabolt "Code") [⚠️](https://github.com/mattphillips/jest-extended/commits?author=hydrabolt "Tests") | [<img src="https://avatars3.githubusercontent.com/u/2045206?v=4" width="100px;"/><br /><sub>Dave Cooper</sub>](http://davecooper.org)<br />[💻](https://github.com/mattphillips/jest-extended/commits?author=grug "Code") [⚠️](https://github.com/mattphillips/jest-extended/commits?author=grug "Tests") | [<img src="https://avatars3.githubusercontent.com/u/3630495?v=4" width="100px;"/><br /><sub>Swann Polydor</sub>](https://github.com/soueuls)<br />[💻](https://github.com/mattphillips/jest-extended/commits?author=soueuls "Code") [⚠️](https://github.com/mattphillips/jest-extended/commits?author=soueuls "Tests") | [<img src="https://avatars1.githubusercontent.com/u/2027003?v=4" width="100px;"/><br /><sub>vikneshwar</sub>](https://github.com/vikneshwar)<br />[💻](https://github.com/mattphillips/jest-extended/commits?author=vikneshwar "Code") [⚠️](https://github.com/mattphillips/jest-extended/commits?author=vikneshwar "Tests") | [<img src="https://avatars1.githubusercontent.com/u/1243921?v=4" width="100px;"/><br /><sub>Budi Irawan</sub>](http://budiirawan.com)<br />[💻](https://github.com/mattphillips/jest-extended/commits?author=deerawan "Code") [⚠️](https://github.com/mattphillips/jest-extended/commits?author=deerawan "Tests") | [<img src="https://avatars2.githubusercontent.com/u/980783?v=4" width="100px;"/><br /><sub>Tejas Bubane</sub>](http://foss-geek.blogspot.com/)<br />[💻](https://github.com/mattphillips/jest-extended/commits?author=tejasbubane "Code") [⚠️](https://github.com/mattphillips/jest-extended/commits?author=tejasbubane "Tests") [📖](https://github.com/mattphillips/jest-extended/commits?author=tejasbubane "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/13134653?v=4" width="100px;"/><br /><sub>Subinoy Ghosh</sub>](https://github.com/subinoy7)<br />[💻](https://github.com/mattphillips/jest-extended/commits?author=subinoy7 "Code") [⚠️](https://github.com/mattphillips/jest-extended/commits?author=subinoy7 "Tests") |
| [<img src="https://avatars1.githubusercontent.com/u/1404810?v=4" width="100px;"/><br /><sub>Simen Bekkhus</sub>](https://github.com/SimenB)<br />[📖](https://github.com/mattphillips/jest-extended/commits?author=SimenB "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/49038?v=4" width="100px;"/><br /><sub>Orta</sub>](http://orta.io)<br />[📖](https://github.com/mattphillips/jest-extended/commits?author=orta "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/17221813?v=4" width="100px;"/><br /><sub>Tom</sub>](https://jsdevtom.com)<br />[💻](https://github.com/mattphillips/jest-extended/commits?author=jsdevtom "Code") [📖](https://github.com/mattphillips/jest-extended/commits?author=jsdevtom "Documentation") [💡](#example-jsdevtom "Examples") [⚠️](https://github.com/mattphillips/jest-extended/commits?author=jsdevtom "Tests") | [<img src="https://avatars0.githubusercontent.com/u/15064535?v=4" width="100px;"/><br /><sub>Lucian Buzzo</sub>](https://github.com/LucianBuzzo)<br /> | [<img src="https://avatars3.githubusercontent.com/u/2997844?v=4" width="100px;"/><br /><sub>Thiago Delgado Pinto</sub>](https://github.com/thiagodp)<br />[💻](https://github.com/mattphillips/jest-extended/commits?author=thiagodp "Code") [📖](https://github.com/mattphillips/jest-extended/commits?author=thiagodp "Documentation") [💡](#example-thiagodp "Examples") [🤔](#ideas-thiagodp "Ideas, Planning, & Feedback") [⚠️](https://github.com/mattphillips/jest-extended/commits?author=thiagodp "Tests") | [<img src="https://avatars0.githubusercontent.com/u/3042904?v=4" width="100px;"/><br /><sub>Ragnar Laud</sub>](https://github.com/xprn)<br />[💻](https://github.com/mattphillips/jest-extended/commits?author=xprn "Code") [📖](https://github.com/mattphillips/jest-extended/commits?author=xprn "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/3047126?v=4" width="100px;"/><br /><sub>Luiz Américo</sub>](https://github.com/blikblum)<br />[💻](https://github.com/mattphillips/jest-extended/commits?author=blikblum "Code") |
| [<img src="https://avatars0.githubusercontent.com/u/615334?v=4" width="100px;"/><br /><sub>Frederick Fogerty</sub>](https://github.com/frederickfogerty)<br />[💻](https://github.com/mattphillips/jest-extended/commits?author=frederickfogerty "Code") [🤔](#ideas-frederickfogerty "Ideas, Planning, & Feedback") | [<img src="https://avatars1.githubusercontent.com/u/10714808?v=4" width="100px;"/><br /><sub>Benjamin Kay</sub>](https://github.com/benjaminkay93)<br />[💻](https://github.com/mattphillips/jest-extended/commits?author=benjaminkay93 "Code") [📖](https://github.com/mattphillips/jest-extended/commits?author=benjaminkay93 "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/868844?v=4" width="100px;"/><br /><sub>Gilles De Mey</sub>](https://demey.io)<br />[💻](https://github.com/mattphillips/jest-extended/commits?author=gillesdemey "Code") [📖](https://github.com/mattphillips/jest-extended/commits?author=gillesdemey "Documentation") [⚠️](https://github.com/mattphillips/jest-extended/commits?author=gillesdemey "Tests") | [<img src="https://avatars0.githubusercontent.com/u/50928?v=4" width="100px;"/><br /><sub>Deniz Dogan</sub>](https://github.com/denizdogan)<br />[💻](https://github.com/mattphillips/jest-extended/commits?author=denizdogan "Code") | [<img src="https://avatars1.githubusercontent.com/u/13043635?v=4" width="100px;"/><br /><sub>Mikey Powers</sub>](https://github.com/mvpowers)<br />[💻](https://github.com/mattphillips/jest-extended/commits?author=mvpowers "Code") [📖](https://github.com/mattphillips/jest-extended/commits?author=mvpowers "Documentation") [⚠️](https://github.com/mattphillips/jest-extended/commits?author=mvpowers "Tests") | [<img src="https://avatars2.githubusercontent.com/u/26580?v=4" width="100px;"/><br /><sub>Tony Trinh</sub>](https://github.com/tony19)<br />[💻](https://github.com/mattphillips/jest-extended/commits?author=tony19 "Code") | [<img src="https://avatars2.githubusercontent.com/u/2844046?v=4" width="100px;"/><br /><sub>Nikita Kurpas</sub>](https://github.com/NikitaKurpas)<br />[💻](https://github.com/mattphillips/jest-extended/commits?author=NikitaKurpas "Code") |
| [<img src="https://avatars0.githubusercontent.com/u/18214059?v=4" width="100px;"/><br /><sub>Alcedo Nathaniel De Guzman Jr</sub>](https://twitter.com/natealcedo)<br />[💻](https://github.com/mattphillips/jest-extended/commits?author=natealcedo "Code") [📖](https://github.com/mattphillips/jest-extended/commits?author=natealcedo "Documentation") [💡](#example-natealcedo "Examples") [⚠️](https://github.com/mattphillips/jest-extended/commits?author=natealcedo "Tests") | [<img src="https://avatars1.githubusercontent.com/u/65444?v=4" width="100px;"/><br /><sub>Pete Hodgson</sub>](http://thepete.net)<br />[💻](https://github.com/mattphillips/jest-extended/commits?author=moredip "Code") |
| [<img src="https://avatars0.githubusercontent.com/u/18214059?v=4" width="100px;"/><br /><sub>Alcedo Nathaniel De Guzman Jr</sub>](https://twitter.com/natealcedo)<br />[💻](https://github.com/mattphillips/jest-extended/commits?author=natealcedo "Code") [📖](https://github.com/mattphillips/jest-extended/commits?author=natealcedo "Documentation") [💡](#example-natealcedo "Examples") [⚠️](https://github.com/mattphillips/jest-extended/commits?author=natealcedo "Tests") | [<img src="https://avatars1.githubusercontent.com/u/65444?v=4" width="100px;"/><br /><sub>Pete Hodgson</sub>](http://thepete.net)<br />[💻](https://github.com/mattphillips/jest-extended/commits?author=moredip "Code") | [<img src="https://avatars2.githubusercontent.com/u/5457711?v=4" width="100px;"/><br /><sub>Daniel Michalski</sub>](https://twitter.com/crazyPolishDan)<br />[💻](https://github.com/mattphillips/jest-extended/commits?author=danielpmichalski "Code") [📖](https://github.com/mattphillips/jest-extended/commits?author=danielpmichalski "Documentation") [⚠️](https://github.com/mattphillips/jest-extended/commits?author=danielpmichalski "Tests") |
<!-- ALL-CONTRIBUTORS-LIST:END -->

## LICENSE
Expand Down
18 changes: 18 additions & 0 deletions src/matchers/toBeArrayWithFloats/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import predicate from './predicate';

export default {
toBeArrayWithFloats: (received, expected, precision = 4) => {
const pass = predicate(received, expected, precision);
if (pass) {
return {
message: `expected [${received}] not to be equal to [${expected}] with ${precision}-digit precision`,
pass: true
};
} else {
return {
message: `expected [${received}] to be equal to [${expected}] with ${precision}-digit precision`,
pass: false
};
}
}
};
31 changes: 31 additions & 0 deletions src/matchers/toBeArrayWithFloats/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import matcher from './';

expect.extend(matcher);

describe('.toBeArrayWithFloats', () => {
test('passes for empty arrays', () => {
expect([]).toBeArrayWithFloats([]);
});

test('passes for arrays with same floats with default precision', () => {
expect([1.2, 2.45]).toBeArrayWithFloats([1.2, 2.45001]);
});

test('passes for arrays with floats rounded to same value with default precision', () => {
expect([0.00011]).toBeArrayWithFloats([0.0001]);
});

test('passes for arrays with same floats with specified precision', () => {
expect([1.014, 1.23456]).toBeArrayWithFloats([1.0104, 1.23112], 2);
});
});

describe('.not.toBeArrayWithFloats', () => {
test('passes for arrays with different floats', () => {
expect([1.0]).not.toBeArrayWithFloats([1.0001]);
});

test('passes for arrays with different floats due to rounding', () => {
expect([1.0]).not.toBeArrayWithFloats([1.00005]);
});
});
54 changes: 54 additions & 0 deletions src/matchers/toBeArrayWithFloats/predicate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const isUndefined = function(obj) {
return typeof obj === 'undefined';
};

const someUndefined = function(objects) {
let check = false;
objects.forEach(item => (check = check || isUndefined(item)));
return check;
};

const areArrays = function(...objects) {
if (someUndefined(objects)) {
return false;
}

let allArrays = true;
objects.forEach(item => (allArrays = allArrays && Array.isArray(item)));
return allArrays;
};

const cutDecimals = function(num, precision) {
return Number.parseFloat(Number.parseFloat(num).toFixed(precision));
};

const floatsEqual = function(float1, float2, precision) {
let a = cutDecimals(float1, precision);
let b = cutDecimals(float2, precision);

if (a === 0 && b === 0) {
return true;
} else if (a !== 0 && b === 0) {
return false;
} else {
return a / b === 1;
}
};

const arrayWithFloatsEquals = function(array1, array2, precision) {
if (array1.length !== array2.length) {
return false;
}

for (let i = 0; i < array1.length; i++) {
if (!floatsEqual(array1[i], array2[i], precision)) {
return false;
}
}

return true;
};

export default (actual, expected, precision = 4) => {
return areArrays(actual, expected) && arrayWithFloatsEquals(actual, expected, precision);
};
74 changes: 74 additions & 0 deletions src/matchers/toBeArrayWithFloats/predicate.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import predicate from './predicate';

describe('toBeArrayWithFloats predicate - positive test cases', () => {
test('returns true for empty arrays', () => {
expect(predicate([], [])).toBe(true);
});

test('returns true for arrays with zeroes', () => {
expect(predicate([0.0], [0.0])).toBe(true);
});

test('processes equal arrays with zeroes', () => {
expect(predicate([0.0, 1.0], [0.0, 1.0])).toBe(true);
});

test('returns true for arrays with same floats with default precision', () => {
expect(predicate([1.0001, 2.123], [1.00011, 2.123])).toBe(true);
});

test('returns true for arrays with same floats with specified precision', () => {
expect(predicate([1.231, 2.344], [1.23, 2.34], 2)).toBe(true);
});

test('returns true when floats do not differ after rounding', () => {
expect(predicate([1.0001], [1.00014])).toBe(true);
});
});

describe('toBeArrayWithFloats predicate - negative test cases', () => {
test('returns false for undefined objects', () => {
expect(predicate(undefined, undefined)).toBe(false);
});

test('returns false for comparing an array to undefined objects', () => {
expect(predicate([], undefined)).toBe(false);
});

test('returns false for comparing an array to undefined objects no.2', () => {
expect(predicate(undefined, [])).toBe(false);
});

test('returns false when one value is non-array', () => {
expect(predicate([1.0], 'non-array')).toBe(false);
expect(predicate('non-array', [1.0])).toBe(false);
});

test('returns false for non-array values', () => {
expect(predicate('string', 5)).toBe(false);
});

test('processes non-equal arrays with zeroes', () => {
expect(predicate([0, 1.0], [0, 0])).toBe(false);
});

test('processes non-equal arrays with zeroes in 2nd array', () => {
expect(predicate([1.0], [0])).toBe(false);
});

test('returns false when comparing arrays of different size', () => {
expect(predicate([1.0], [1.0, 2.0])).toBe(false);
});

test('returns false for arrays with different floats with default precision', () => {
expect(predicate([1.1111], [1.1112])).toBe(false);
});

test('returns false for arrays with different floats with specified precision', () => {
expect(predicate([1.1334], [1.1234], 2)).toBe(false);
});

test('returns false when floats differ by single digit due to rounding', () => {
expect(predicate([1.0001], [1.00015])).toBe(false);
});
});
7 changes: 7 additions & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@ declare namespace jest {
*/
toBeArrayOfSize(x: number): R;

/**
* Use `.toBeArrayWithFloats` when checking if a value is an `Array` with floating-point numbers. Equality is checked using default or specified precision.
* @param {Array.<Number>} expected
* @param {Number} precision, i.e. decimal places taken into account during number comparison (1.0001 is not 1.00016, but 1.0001 is 1.00015 for precision = 4)
*/
toBeArrayWithFloats(expected: number[], precision: number = 4): R;

/**
* Use `.toBeAfter` when checking if a date occurs after `date`.
* @param {Date} date
Expand Down