├── .changeset ├── README.md └── config.json ├── .gitattributes ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md ├── renovate.json └── workflows │ └── ci.yaml ├── .gitignore ├── .husky ├── .gitignore └── pre-commit ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── all.js ├── clean.js ├── eslint.config.cjs ├── examples └── typescript │ └── all │ ├── README.md │ ├── jest.config.js │ ├── package.json │ ├── src │ └── add.ts │ ├── test │ └── add.test.ts │ ├── tsconfig.json │ └── yarn.lock ├── package.json ├── src ├── all │ └── index.ts ├── index.ts ├── matchers │ ├── fail.ts │ ├── index.ts │ ├── pass.ts │ ├── toBeAfter.ts │ ├── toBeAfterOrEqualTo.ts │ ├── toBeArray.ts │ ├── toBeArrayOfSize.ts │ ├── toBeBefore.ts │ ├── toBeBeforeOrEqualTo.ts │ ├── toBeBetween.ts │ ├── toBeBoolean.ts │ ├── toBeDate.ts │ ├── toBeDateString.ts │ ├── toBeEmpty.ts │ ├── toBeEmptyObject.ts │ ├── toBeEven.ts │ ├── toBeExtensible.ts │ ├── toBeFalse.ts │ ├── toBeFinite.ts │ ├── toBeFrozen.ts │ ├── toBeFunction.ts │ ├── toBeHexadecimal.ts │ ├── toBeInRange.ts │ ├── toBeInteger.ts │ ├── toBeNaN.ts │ ├── toBeNegative.ts │ ├── toBeNil.ts │ ├── toBeNumber.ts │ ├── toBeObject.ts │ ├── toBeOdd.ts │ ├── toBeOneOf.ts │ ├── toBePositive.ts │ ├── toBeSealed.ts │ ├── toBeString.ts │ ├── toBeSymbol.ts │ ├── toBeTrue.ts │ ├── toBeValidDate.ts │ ├── toBeWithin.ts │ ├── toChange.ts │ ├── toChangeBy.ts │ ├── toChangeTo.ts │ ├── toContainAllEntries.ts │ ├── toContainAllKeys.ts │ ├── toContainAllValues.ts │ ├── toContainAnyEntries.ts │ ├── toContainAnyKeys.ts │ ├── toContainAnyValues.ts │ ├── toContainEntries.ts │ ├── toContainEntry.ts │ ├── toContainKey.ts │ ├── toContainKeys.ts │ ├── toContainValue.ts │ ├── toContainValues.ts │ ├── toEndWith.ts │ ├── toEqualCaseInsensitive.ts │ ├── toEqualIgnoringWhitespace.ts │ ├── toHaveBeenCalledAfter.ts │ ├── toHaveBeenCalledBefore.ts │ ├── toHaveBeenCalledExactlyOnceWith.ts │ ├── toHaveBeenCalledOnce.ts │ ├── toInclude.ts │ ├── toIncludeAllMembers.ts │ ├── toIncludeAllPartialMembers.ts │ ├── toIncludeAnyMembers.ts │ ├── toIncludeMultiple.ts │ ├── toIncludeRepeated.ts │ ├── toIncludeSameMembers.ts │ ├── toIncludeSamePartialMembers.ts │ ├── toPartiallyContain.ts │ ├── toReject.ts │ ├── toResolve.ts │ ├── toSatisfy.ts │ ├── toSatisfyAll.ts │ ├── toSatisfyAny.ts │ ├── toStartWith.ts │ └── toThrowWithMessage.ts └── utils │ ├── index.ts │ └── print.ts ├── test ├── fixtures │ └── counter.ts ├── matchers │ ├── __snapshots__ │ │ ├── fail.test.ts.snap │ │ ├── pass.test.ts.snap │ │ ├── toBeAfter.test.ts.snap │ │ ├── toBeAfterOrEqualTo.test.ts.snap │ │ ├── toBeArray.test.ts.snap │ │ ├── toBeArrayOfSize.test.ts.snap │ │ ├── toBeBefore.test.ts.snap │ │ ├── toBeBeforeOrEqualTo.test.ts.snap │ │ ├── toBeBetween.test.ts.snap │ │ ├── toBeBoolean.test.ts.snap │ │ ├── toBeDate.test.ts.snap │ │ ├── toBeDateString.test.ts.snap │ │ ├── toBeEmpty.test.ts.snap │ │ ├── toBeEmptyObject.test.ts.snap │ │ ├── toBeEven.test.ts.snap │ │ ├── toBeExtensible.test.ts.snap │ │ ├── toBeFalse.test.ts.snap │ │ ├── toBeFinite.test.ts.snap │ │ ├── toBeFrozen.test.ts.snap │ │ ├── toBeFunction.test.ts.snap │ │ ├── toBeHexadecimal.test.ts.snap │ │ ├── toBeInRange.test.ts.snap │ │ ├── toBeInteger.test.ts.snap │ │ ├── toBeNaN.test.ts.snap │ │ ├── toBeNegative.test.ts.snap │ │ ├── toBeNil.test.ts.snap │ │ ├── toBeNumber.test.ts.snap │ │ ├── toBeObject.test.ts.snap │ │ ├── toBeOdd.test.ts.snap │ │ ├── toBeOneOf.test.ts.snap │ │ ├── toBePositive.test.ts.snap │ │ ├── toBeSealed.test.ts.snap │ │ ├── toBeString.test.ts.snap │ │ ├── toBeSymbol.test.ts.snap │ │ ├── toBeTrue.test.ts.snap │ │ ├── toBeValidDate.test.ts.snap │ │ ├── toBeWithin.test.ts.snap │ │ ├── toChange.test.ts.snap │ │ ├── toChangeBy.test.ts.snap │ │ ├── toChangeTo.test.ts.snap │ │ ├── toContainAllEntries.test.ts.snap │ │ ├── toContainAllKeys.test.ts.snap │ │ ├── toContainAllValues.test.ts.snap │ │ ├── toContainAnyEntries.test.ts.snap │ │ ├── toContainAnyKeys.test.ts.snap │ │ ├── toContainAnyValues.test.ts.snap │ │ ├── toContainEntries.test.ts.snap │ │ ├── toContainEntry.test.ts.snap │ │ ├── toContainKey.test.ts.snap │ │ ├── toContainKeys.test.ts.snap │ │ ├── toContainValue.test.ts.snap │ │ ├── toContainValues.test.ts.snap │ │ ├── toEndWith.test.ts.snap │ │ ├── toEqualCaseInsensitive.test.ts.snap │ │ ├── toEqualIgnoringWhitespace.test.ts.snap │ │ ├── toHaveBeenCalledAfter.test.ts.snap │ │ ├── toHaveBeenCalledBefore.test.ts.snap │ │ ├── toHaveBeenCalledExactlyOnceWith.test.ts.snap │ │ ├── toHaveBeenCalledOnce.test.ts.snap │ │ ├── toInclude.test.ts.snap │ │ ├── toIncludeAllMembers.test.ts.snap │ │ ├── toIncludeAllPartialMembers.test.ts.snap │ │ ├── toIncludeAnyMembers.test.ts.snap │ │ ├── toIncludeMultiple.test.ts.snap │ │ ├── toIncludeRepeated.test.ts.snap │ │ ├── toIncludeSameMembers.test.ts.snap │ │ ├── toIncludeSamePartialMembers.test.ts.snap │ │ ├── toPartiallyContain.test.ts.snap │ │ ├── toReject.test.ts.snap │ │ ├── toResolve.test.ts.snap │ │ ├── toSatisfy.test.ts.snap │ │ ├── toSatisfyAll.test.ts.snap │ │ ├── toSatisfyAny.test.ts.snap │ │ ├── toStartWith.test.ts.snap │ │ └── toThrowWithMessage.test.ts.snap │ ├── fail.test.ts │ ├── index.test.ts │ ├── pass.test.ts │ ├── toBeAfter.test.ts │ ├── toBeAfterOrEqualTo.test.ts │ ├── toBeArray.test.ts │ ├── toBeArrayOfSize.test.ts │ ├── toBeBefore.test.ts │ ├── toBeBeforeOrEqualTo.test.ts │ ├── toBeBetween.test.ts │ ├── toBeBoolean.test.ts │ ├── toBeDate.test.ts │ ├── toBeDateString.test.ts │ ├── toBeEmpty.test.ts │ ├── toBeEmptyObject.test.ts │ ├── toBeEven.test.ts │ ├── toBeExtensible.test.ts │ ├── toBeFalse.test.ts │ ├── toBeFinite.test.ts │ ├── toBeFrozen.test.ts │ ├── toBeFunction.test.ts │ ├── toBeHexadecimal.test.ts │ ├── toBeInRange.test.ts │ ├── toBeInteger.test.ts │ ├── toBeNaN.test.ts │ ├── toBeNegative.test.ts │ ├── toBeNil.test.ts │ ├── toBeNumber.test.ts │ ├── toBeObject.test.ts │ ├── toBeOdd.test.ts │ ├── toBeOneOf.test.ts │ ├── toBePositive.test.ts │ ├── toBeSealed.test.ts │ ├── toBeString.test.ts │ ├── toBeSymbol.test.ts │ ├── toBeTrue.test.ts │ ├── toBeValidDate.test.ts │ ├── toBeWithin.test.ts │ ├── toChange.test.ts │ ├── toChangeBy.test.ts │ ├── toChangeTo.test.ts │ ├── toContainAllEntries.test.ts │ ├── toContainAllKeys.test.ts │ ├── toContainAllValues.test.ts │ ├── toContainAnyEntries.test.ts │ ├── toContainAnyKeys.test.ts │ ├── toContainAnyValues.test.ts │ ├── toContainEntries.test.ts │ ├── toContainEntry.test.ts │ ├── toContainKey.test.ts │ ├── toContainKeys.test.ts │ ├── toContainValue.test.ts │ ├── toContainValues.test.ts │ ├── toEndWith.test.ts │ ├── toEqualCaseInsensitive.test.ts │ ├── toEqualIgnoringWhitespace.test.ts │ ├── toHaveBeenCalledAfter.test.ts │ ├── toHaveBeenCalledBefore.test.ts │ ├── toHaveBeenCalledExactlyOnceWith.test.ts │ ├── toHaveBeenCalledOnce.test.ts │ ├── toInclude.test.ts │ ├── toIncludeAllMembers.test.ts │ ├── toIncludeAllPartialMembers.test.ts │ ├── toIncludeAnyMembers.test.ts │ ├── toIncludeMultiple.test.ts │ ├── toIncludeRepeated.test.ts │ ├── toIncludeSameMembers.test.ts │ ├── toIncludeSamePartialMembers.test.ts │ ├── toPartiallyContain.test.ts │ ├── toReject.test.ts │ ├── toResolve.test.ts │ ├── toSatisfy.test.ts │ ├── toSatisfyAll.test.ts │ ├── toSatisfyAny.test.ts │ ├── toStartWith.test.ts │ └── toThrowWithMessage.test.ts └── utils │ ├── index.test.ts │ └── print.test.ts ├── tsconfig.json ├── tsconfig.test.json ├── types └── index.d.ts ├── website ├── .gitignore ├── README.md ├── babel.config.js ├── docs │ ├── getting-started │ │ ├── _category_.json │ │ ├── eslint.md │ │ ├── install.md │ │ ├── setup.md │ │ └── typescript.md │ ├── index.md │ └── matchers │ │ ├── _category_.json │ │ ├── array.mdx │ │ ├── boolean.mdx │ │ ├── date.mdx │ │ ├── fail.mdx │ │ ├── function.mdx │ │ ├── index.md │ │ ├── mock.mdx │ │ ├── number.mdx │ │ ├── object.mdx │ │ ├── pass.mdx │ │ ├── promise.mdx │ │ ├── string.mdx │ │ ├── symbol.mdx │ │ ├── toBeEmpty.mdx │ │ ├── toBeNil.mdx │ │ ├── toBeOneOf.mdx │ │ └── toSatisfy.mdx ├── docusaurus.config.js ├── package.json ├── sidebars.js ├── src │ ├── components │ │ ├── CustomSandpack.tsx │ │ └── HomepageFeatures │ │ │ ├── index.tsx │ │ │ └── styles.module.css │ ├── css │ │ └── custom.css │ └── pages │ │ ├── index.module.css │ │ └── index.tsx ├── static │ ├── .nojekyll │ └── img │ │ ├── favicon.ico │ │ ├── logo.png │ │ ├── undraw_docusaurus_mountain.svg │ │ ├── undraw_docusaurus_react.svg │ │ └── undraw_docusaurus_tree.svg ├── tsconfig.json ├── vercel.json └── yarn.lock └── yarn.lock /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "public", 8 | "baseBranch": "main", 9 | "updateInternalDependencies": "patch", 10 | "ignore": [] 11 | } 12 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js text eol=lf 2 | *.ts text eol=lf 3 | *.json text eol=lf 4 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [mattphillips] 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 8 | 9 | 29 | 30 | 38 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | ### What 11 | 12 | 13 | 14 | ### Why 15 | 16 | 17 | 18 | ### Notes 19 | 20 | ### Housekeeping 21 | 22 | - [ ] Unit tests 23 | - [ ] Documentation is up to date 24 | - [ ] No additional lint warnings 25 | - [ ] [Typescript definitions](https://github.com/jest-community/jest-extended/blob/main/types/index.d.ts) are added/updated where relevant 26 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["config:base", ":semanticCommitsDisabled"], 3 | "lockFileMaintenance": { "enabled": true, "automerge": true }, 4 | "rangeStrategy": "replace", 5 | "postUpdateOptions": ["yarnDedupeHighest"], 6 | "packageRules": [ 7 | { 8 | "matchPackageNames": ["@codesandbox/sandpack-react", "@codesandbox/sandpack-themes"], 9 | "groupName": "sandpack" 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .DS_Store 4 | *.log 5 | coverage 6 | .dccache 7 | .idea 8 | .vs 9 | .vscode 10 | package-lock.json 11 | *tsbuildinfo 12 | -------------------------------------------------------------------------------- /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | [ -n "$CI" ] && exit 0 3 | 4 | yarn lint-staged 5 | yarn test 6 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # jest-extended 2 | 3 | ## 5.0.3 4 | 5 | ### Patch Changes 6 | 7 | - 3a031b6: Fix some types bugs 8 | 9 | ## 5.0.2 10 | 11 | ### Patch Changes 12 | 13 | - 846fac2: toIncludeSameMembers should fail when passed non-arrays 14 | - 89c99c4: toBeWithin fails with bigints 15 | 16 | ## 5.0.1 17 | 18 | ### Patch Changes 19 | 20 | - 0886e55: Fix import paths 21 | 22 | ## 5.0.0 23 | 24 | ### Major Changes 25 | 26 | - b86423c: Drop support for Node 16 and 18 27 | 28 | ### Minor Changes 29 | 30 | - 94935ea: Replace jest-get-type with native type checking 31 | - 2483bcc: Add Minor: Add toIncludeSamePartialMembers 32 | - deb17c6: Add toChange, toChangeBy, and toChangeTo matchers 33 | - b2c1bd4: Switch to TypeScript 34 | - 50e6a8a: Support custom equality testers 35 | 36 | ### Patch Changes 37 | 38 | - 3f47e14: Fix toBeInRange wording 39 | - Dependency Updates 40 | 41 | ## 4.0.2 42 | 43 | ### Patch Changes 44 | 45 | - 1f88101: Mark 2nd param of toHaveBeenCalledBefore and toHaveBeenCalledAfter optional 46 | 47 | ## 4.0.1 48 | 49 | ### Patch Changes 50 | 51 | - bad7056: Fix `toHaveBeenCalledExactlyOnceWith` typings 52 | - 1609897: Remove problematic Vitest types 53 | 54 | ## 4.0.0 55 | 56 | ### Major Changes 57 | 58 | - ab20845: Rename toHaveBeenCalledOnceWith to toHaveBeenCalledExactlyOnceWith 59 | 60 | ### Minor Changes 61 | 62 | - 5b80ca8: support vitest 0.31.0 63 | 64 | ### Patch Changes 65 | 66 | - ab20845: Make CustomMatchers extend Record to fix a TypeScript error 67 | - ab20845: Fix toHaveBeenCalledOnceWith messages 68 | - ab20845: Change unknown to any in toHaveBeenCalledBefore and toHaveBeenCalledAfter 69 | 70 | ## 3.2.4 71 | 72 | ### Patch Changes 73 | 74 | - 0b07513: Support varargs in toHaveBeenCalledOnceWith (#557) 75 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thanks for being willing to contribute! 4 | 5 | **Working on your first Pull Request?** You can learn how from this _free_ series 6 | [How to Contribute to an Open Source Project on GitHub](https://egghead.io/series/how-to-contribute-to-an-open-source-project-on-github) 7 | 8 | ## Project setup 9 | 10 | 1. Fork and clone the repo 11 | 2. `$ yarn install` to install dependencies 12 | 3. `$ yarn test` to validate you've got it working 13 | 4. Create a branch for your PR 14 | 15 | ## Making changes 16 | 17 | - All changes should have unit tests 18 | - Any relevant documentation should be updated 19 | - No linting warnings/errors should be introduced 20 | 21 | ### New Matchers 22 | 23 | - Each matcher should be placed in it's own file inside of the `src/matchers/[matcher].ts`. 24 | - A matcher should: 25 | - Export the matcher in the format expected by Jest. See the docs for an [example](http://facebook.github.io/jest/docs/en/expect.html#expectextendmatchers). Note: the test outcome messages must be a function that returns a string (this caught me out 😉). 26 | - Tests for the matcher should go in `test/matchers/[matcher].test.ts` - Test suite that uses the new matcher and make sure it passes. 27 | - Docs for the new matcher should be updated in the API section of the `README.md` to no longer say `Unimplemented`. 28 | - Type definitions for the new matchers should be added to `types/index.d.ts`. 29 | 30 | ## Committing and Pushing changes 31 | 32 | Once you are ready to commit the changes, please use the below commands 33 | 34 | 1. `git add ` 35 | 2. `git commit -m 'A meaningful message` 36 | 37 | _Note: please use present tense in commit messages i.e. `Add feature X` and not ~`Added feature X`~_ 38 | 39 | ## Help needed 40 | 41 | Please check out the [issues](https://github.com/jest-community/jest-extended/issues) to discuss any of the potential 42 | work 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-present Matt Phillips (mattphillips.io) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /all.js: -------------------------------------------------------------------------------- 1 | // override rule to allow running linting before build (dist directory won't exist yet) 2 | 3 | // eslint-disable-next-line import/no-unresolved 4 | require('./dist/all'); 5 | -------------------------------------------------------------------------------- /clean.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const distPath = path.join(__dirname, 'dist'); 4 | if (fs.existsSync(distPath)) { 5 | fs.rmSync(distPath, { recursive: true, force: true }); 6 | } 7 | -------------------------------------------------------------------------------- /examples/typescript/all/README.md: -------------------------------------------------------------------------------- 1 | # Global Typescript setup of `jest-extended` 2 | 3 | This example demonstrates how to setup `jest-extended` globally with Typescript. 4 | 5 | You will need to register `jest-extended/all` with Jest using the `setupFilesAfterEnv` field in your Jest config, see here: [jest.config.js](./jest.config.js) 6 | 7 | ```sh 8 | module.exports = { 9 | setupFilesAfterEnv: ['jest-extended/all'], 10 | }; 11 | ``` 12 | 13 | To enable `jest-extended` globally in your Typescript project you will need to tell Typescript where to find the `jest-extended` type declarations. 14 | 15 | To do this add a `files` property to your tsconfig.json with an entry of `node_modules/jest-extended/types/index.d.ts`, see here [tsconfig.json](./tsconfig.json) 16 | -------------------------------------------------------------------------------- /examples/typescript/all/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | roots: [''], 3 | preset: 'ts-jest', 4 | testRegex: 'test/.*\\.test\\.tsx?$', 5 | moduleFileExtensions: ['ts', 'tsx', 'js'], 6 | setupFilesAfterEnv: ['jest-extended/all'], 7 | }; 8 | -------------------------------------------------------------------------------- /examples/typescript/all/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jest-extended-typescript-setup-all", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "devDependencies": { 7 | "@types/jest": "^27.4.0", 8 | "jest": "^27.4.7", 9 | "jest-extended": "^1.2.0", 10 | "ts-jest": "^27.1.3", 11 | "typescript": "^4.5.5" 12 | }, 13 | "scripts": { 14 | "test": "jest" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/typescript/all/src/add.ts: -------------------------------------------------------------------------------- 1 | export const add = (a: number, b: number): number => a + b; 2 | -------------------------------------------------------------------------------- /examples/typescript/all/test/add.test.ts: -------------------------------------------------------------------------------- 1 | import { add } from '../src/add'; 2 | 3 | describe('add', () => { 4 | test('Commutative Law of Addition', () => { 5 | expect(add(1, 2)).toBe(add(2, 1)); 6 | }); 7 | 8 | test('adding two integers returns an integer', () => { 9 | expect(add(1, 100)).toBeInteger(); 10 | }); 11 | 12 | test('positive numbers remain positive', () => { 13 | expect(add(1, 1)).toBePositive(); 14 | }); 15 | 16 | test('negative numbers remain negative', () => { 17 | expect(add(-1, -1)).toBeNegative(); 18 | }); 19 | 20 | test('adding two even numbers does not give an odd number', () => { 21 | expect(add(1, 3)).not.toBeOdd(); 22 | }); 23 | 24 | test('adding two odd numbers gives an even number', () => { 25 | expect(add(1, 3)).toBeEven(); 26 | }); 27 | 28 | test('array equal another array regardless of the order', () => { 29 | expect([1, 3]).toIncludeSameMembers([3, 1]); 30 | }); 31 | 32 | test('array property equal another array regardless of the order', () => { 33 | expect({ array: [1, 3] }).toEqual({ 34 | array: expect.toIncludeSameMembers([3, 1]), 35 | }); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /examples/typescript/all/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2016", 4 | "module": "commonjs", 5 | "baseUrl": "./", 6 | "esModuleInterop": true, 7 | "strict": true, 8 | "noEmit": true 9 | }, 10 | "files": ["node_modules/jest-extended/types/index.d.ts"], 11 | "include": [ "src/**/*", "test/**/*"], 12 | "exclude": ["node_modules"] 13 | } 14 | -------------------------------------------------------------------------------- /src/all/index.ts: -------------------------------------------------------------------------------- 1 | import * as matchers from '../matchers'; 2 | 3 | // @ts-expect-error expect will be hoisted into global 4 | const jestExpect = global.expect; 5 | 6 | if (jestExpect !== undefined) { 7 | jestExpect.extend(matchers); 8 | } else { 9 | throw new Error( 10 | "Unable to find Jest's global expect. " + 11 | 'Please check you have added jest-extended correctly to your jest configuration. ' + 12 | 'See https://github.com/jest-community/jest-extended#setup for help.', 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './matchers'; 2 | -------------------------------------------------------------------------------- /src/matchers/fail.ts: -------------------------------------------------------------------------------- 1 | export function fail(_: unknown, message: string) { 2 | return { 3 | pass: false, 4 | message: () => (message ? message : 'fails by .fail() assertion'), 5 | }; 6 | } 7 | -------------------------------------------------------------------------------- /src/matchers/pass.ts: -------------------------------------------------------------------------------- 1 | export function pass(_: unknown, message: string) { 2 | return { 3 | pass: true, 4 | message: () => (message ? message : 'passes by .pass() assertion'), 5 | }; 6 | } 7 | -------------------------------------------------------------------------------- /src/matchers/toBeAfter.ts: -------------------------------------------------------------------------------- 1 | export function toBeAfter(actual: unknown, after: Date) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, matcherHint } = this.utils; 4 | 5 | const pass = actual instanceof Date && actual > after; 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeAfter', 'received', '') + 12 | '\n\n' + 13 | `Expected date to be after ${printReceived(after)} but received:\n` + 14 | ` ${printReceived(actual)}` 15 | : matcherHint('.toBeAfter', 'received', '') + 16 | '\n\n' + 17 | `Expected date to be after ${printReceived(after)} but received:\n` + 18 | ` ${printReceived(actual)}`, 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/matchers/toBeAfterOrEqualTo.ts: -------------------------------------------------------------------------------- 1 | export function toBeAfterOrEqualTo(actual: unknown, expected: Date) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, matcherHint } = this.utils; 4 | 5 | const pass = actual instanceof Date && actual >= expected; 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeAfterOrEqualTo', 'received', '') + 12 | '\n\n' + 13 | `Expected date to be after or equal to ${printReceived(expected)} but received:\n` + 14 | ` ${printReceived(actual)}` 15 | : matcherHint('.toBeAfterOrEqualTo', 'received', '') + 16 | '\n\n' + 17 | `Expected date to be after or equal to ${printReceived(expected)} but received:\n` + 18 | ` ${printReceived(actual)}`, 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/matchers/toBeArray.ts: -------------------------------------------------------------------------------- 1 | export function toBeArray(expected: unknown) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { matcherHint, printReceived } = this.utils; 4 | 5 | const pass = Array.isArray(expected); 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeArray', 'received', '') + 12 | '\n\n' + 13 | 'Expected value to not be an array received:\n' + 14 | ` ${printReceived(expected)}` 15 | : matcherHint('.toBeArray', 'received', '') + 16 | '\n\n' + 17 | 'Expected value to be an array received:\n' + 18 | ` ${printReceived(expected)}`, 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/matchers/toBeArrayOfSize.ts: -------------------------------------------------------------------------------- 1 | import { determinePropertyMessage } from 'src/utils'; 2 | 3 | export function toBeArrayOfSize(actual: unknown, expected: number) { 4 | // @ts-expect-error OK to have implicit any for this.utils 5 | const { printExpected, printReceived, matcherHint } = this.utils; 6 | 7 | const pass = Array.isArray(actual) && actual.length === expected; 8 | 9 | return { 10 | pass, 11 | message: () => 12 | pass 13 | ? matcherHint('.not.toBeArrayOfSize') + 14 | '\n\n' + 15 | 'Expected value to not be an array of size:\n' + 16 | ` ${printExpected(expected)}\n` + 17 | 'Received:\n' + 18 | ` value: ${printReceived(actual)}\n` + 19 | ` length: ${printReceived(determinePropertyMessage(actual, 'length'))}` 20 | : matcherHint('.toBeArrayOfSize') + 21 | '\n\n' + 22 | 'Expected value to be an array of size:\n' + 23 | ` ${printExpected(expected)}\n` + 24 | 'Received:\n' + 25 | ` value: ${printReceived(actual)}\n` + 26 | ` length: ${printReceived(determinePropertyMessage(actual, 'length'))}`, 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /src/matchers/toBeBefore.ts: -------------------------------------------------------------------------------- 1 | export function toBeBefore(actual: unknown, expected: Date) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { matcherHint, printReceived } = this.utils; 4 | 5 | const pass = actual instanceof Date && actual < expected; 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeBefore', 'received', '') + 12 | '\n\n' + 13 | `Expected date to be before ${printReceived(expected)} but received:\n` + 14 | ` ${printReceived(actual)}` 15 | : matcherHint('.toBeBefore', 'received', '') + 16 | '\n\n' + 17 | `Expected date to be before ${printReceived(expected)} but received:\n` + 18 | ` ${printReceived(actual)}`, 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/matchers/toBeBeforeOrEqualTo.ts: -------------------------------------------------------------------------------- 1 | export function toBeBeforeOrEqualTo(actual: unknown, expected: Date) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { matcherHint, printReceived } = this.utils; 4 | 5 | const pass = actual instanceof Date && actual <= expected; 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeBeforeOrEqualTo', 'received', '') + 12 | '\n\n' + 13 | `Expected date to be before or equal to ${printReceived(expected)} but received:\n` + 14 | ` ${printReceived(actual)}` 15 | : matcherHint('.toBeBeforeOrEqualTo', 'received', '') + 16 | '\n\n' + 17 | `Expected date to be before or equal to ${printReceived(expected)} but received:\n` + 18 | ` ${printReceived(actual)}`, 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/matchers/toBeBetween.ts: -------------------------------------------------------------------------------- 1 | export function toBeBetween(actual: unknown, startDate: Date, endDate: Date) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { matcherHint, printReceived } = this.utils; 4 | 5 | const pass = actual instanceof Date && actual >= startDate && actual <= endDate; 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeBetween', 'received', '') + 12 | '\n\n' + 13 | `Expected date to be between ${printReceived(startDate)} and ${printReceived(endDate)} but received:\n` + 14 | ` ${printReceived(actual)}` 15 | : matcherHint('.toBeBetween', 'received', '') + 16 | '\n\n' + 17 | `Expected date to be between ${printReceived(startDate)} and ${printReceived(endDate)} but received:\n` + 18 | ` ${printReceived(actual)}`, 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/matchers/toBeBoolean.ts: -------------------------------------------------------------------------------- 1 | export function toBeBoolean(actual: unknown) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { matcherHint, printReceived } = this.utils; 4 | 5 | const pass = typeof actual === 'boolean' || actual instanceof Boolean; 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeBoolean', 'received', '') + 12 | '\n\n' + 13 | 'Expected value to not be of type boolean, received:\n' + 14 | ` ${printReceived(actual)}` 15 | : matcherHint('.toBeBoolean', 'received', '') + 16 | '\n\n' + 17 | 'Expected value to be of type boolean, received:\n' + 18 | ` ${printReceived(actual)}`, 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/matchers/toBeDate.ts: -------------------------------------------------------------------------------- 1 | export function toBeDate(actual: unknown) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { matcherHint, printReceived } = this.utils; 4 | 5 | const pass = actual instanceof Date && !isNaN(actual.getTime()); 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeDate', 'received', '') + 12 | '\n\n' + 13 | 'Expected value to not be a date received:\n' + 14 | ` ${printReceived(actual)}` 15 | : matcherHint('.toBeDate', 'received', '') + 16 | '\n\n' + 17 | 'Expected value to be a date received:\n' + 18 | ` ${printReceived(actual)}`, 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/matchers/toBeDateString.ts: -------------------------------------------------------------------------------- 1 | export function toBeDateString(actual: unknown) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { matcherHint, printReceived } = this.utils; 4 | 5 | const pass = typeof actual === 'string' && !isNaN(Date.parse(actual)); 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeDateString', 'received', '') + 12 | '\n\n' + 13 | 'Expected value to not be a date string received:\n' + 14 | ` ${printReceived(actual)}` 15 | : matcherHint('.toBeDateString', 'received', '') + 16 | '\n\n' + 17 | 'Expected value to be a date string received:\n' + 18 | ` ${printReceived(actual)}`, 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/matchers/toBeEmpty.ts: -------------------------------------------------------------------------------- 1 | export function toBeEmpty(actual: unknown) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, matcherHint } = this.utils; 4 | 5 | // @ts-expect-error OK to have implicit any for this.equals 6 | const pass = this.equals({}, actual, this.customTesters) || isEmptyIterable(actual); 7 | 8 | return { 9 | pass, 10 | message: () => 11 | pass 12 | ? matcherHint('.not.toBeEmpty', 'received', '') + 13 | '\n\n' + 14 | 'Expected value to not be empty received:\n' + 15 | ` ${printReceived(actual)}` 16 | : matcherHint('.toBeEmpty', 'received', '') + 17 | '\n\n' + 18 | 'Expected value to be empty received:\n' + 19 | ` ${printReceived(actual)}`, 20 | }; 21 | } 22 | 23 | const isEmptyIterable = (value: any) => { 24 | if (typeof value[Symbol.iterator] !== 'function') { 25 | return false; 26 | } 27 | const firstIteration = value[Symbol.iterator]().next(); 28 | return firstIteration.done; 29 | }; 30 | -------------------------------------------------------------------------------- /src/matchers/toBeEmptyObject.ts: -------------------------------------------------------------------------------- 1 | export function toBeEmptyObject(actual: unknown) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, matcherHint } = this.utils; 4 | 5 | const pass = 6 | typeof actual === 'object' && actual !== null && !Array.isArray(actual) && Object.keys(actual).length === 0; 7 | 8 | return { 9 | pass, 10 | message: () => 11 | pass 12 | ? matcherHint('.not.toBeEmptyObject', 'received', '') + 13 | '\n\n' + 14 | 'Expected value to not be an empty object, received:\n' + 15 | ` ${printReceived(actual)}` 16 | : matcherHint('.toBeEmptyObject', 'received', '') + 17 | '\n\n' + 18 | 'Expected value to be an empty object, received:\n' + 19 | ` ${printReceived(actual)}`, 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /src/matchers/toBeEven.ts: -------------------------------------------------------------------------------- 1 | export function toBeEven(actual: unknown) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, matcherHint } = this.utils; 4 | 5 | const pass = isNumber(actual) && isEven(actual); 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeEven', 'received', '') + 12 | '\n\n' + 13 | 'Expected value to not be an even number received:\n' + 14 | ` ${printReceived(actual)}` 15 | : matcherHint('.toBeEven', 'received', '') + 16 | '\n\n' + 17 | 'Expected value to be an even number received:\n' + 18 | ` ${printReceived(actual)}`, 19 | }; 20 | } 21 | 22 | const isNumber = (expected: any) => !isNaN(parseInt(expected)); 23 | const isEven = (expected: any) => expected % 2 === 0; 24 | -------------------------------------------------------------------------------- /src/matchers/toBeExtensible.ts: -------------------------------------------------------------------------------- 1 | export function toBeExtensible(actual: unknown) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { matcherHint, printExpected, printReceived } = this.utils; 4 | 5 | const pass = Object.isExtensible(actual); 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeExtensible', 'received', '') + 12 | '\n\n' + 13 | 'Expected value to not be extensible received:\n' + 14 | ` ${printExpected(actual)}\n` 15 | : matcherHint('.toBeExtensible', 'received', '') + 16 | '\n\n' + 17 | 'Expected value to be extensible received:\n' + 18 | ` ${printReceived(actual)}`, 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/matchers/toBeFalse.ts: -------------------------------------------------------------------------------- 1 | export function toBeFalse(actual: unknown) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, matcherHint, printExpected } = this.utils; 4 | 5 | const pass = actual === false; 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeFalse', 'received', '') + 12 | '\n\n' + 13 | 'Expected value to not be false received:\n' + 14 | ` ${printReceived(actual)}` 15 | : matcherHint('.toBeFalse', 'received', '') + 16 | '\n\n' + 17 | 'Expected value to be false:\n' + 18 | ` ${printExpected(false)}\n` + 19 | 'Received:\n' + 20 | ` ${printReceived(actual)}`, 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /src/matchers/toBeFinite.ts: -------------------------------------------------------------------------------- 1 | export function toBeFinite(actual: unknown) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, matcherHint } = this.utils; 4 | 5 | const pass = Number.isFinite(actual); 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeFinite', 'received', '') + 12 | '\n\n' + 13 | 'Expected value to not be finite received:\n' + 14 | ` ${printReceived(actual)}` 15 | : matcherHint('.toBeFinite', 'received', '') + 16 | '\n\n' + 17 | 'Expected value to be finite received:\n' + 18 | ` ${printReceived(actual)}`, 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/matchers/toBeFrozen.ts: -------------------------------------------------------------------------------- 1 | export function toBeFrozen(actual: unknown) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { matcherHint } = this.utils; 4 | 5 | const pass = Object.isFrozen(actual); 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeFrozen', 'received', '') + '\n\nExpected object to not be frozen' 12 | : matcherHint('.toBeFrozen', 'received', '') + '\n\nExpected object to be frozen', 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /src/matchers/toBeFunction.ts: -------------------------------------------------------------------------------- 1 | export function toBeFunction(actual: unknown) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, matcherHint } = this.utils; 4 | 5 | const pass = typeof actual === 'function'; 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeFunction', 'received', '') + 12 | '\n\n' + 13 | 'Expected value to not be a function, received:\n' + 14 | ` ${printReceived(actual)}` 15 | : matcherHint('.toBeFunction', 'received', '') + 16 | '\n\n' + 17 | 'Expected to receive a function, received:\n' + 18 | ` ${printReceived(actual)}`, 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/matchers/toBeHexadecimal.ts: -------------------------------------------------------------------------------- 1 | export function toBeHexadecimal(actual: unknown) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, matcherHint } = this.utils; 4 | 5 | const pass = 6 | (typeof actual === 'string' && longRegex.test(actual)) || (typeof actual === 'string' && shortRegex.test(actual)); 7 | 8 | return { 9 | pass, 10 | message: () => 11 | pass 12 | ? matcherHint('.not.toBeHexadecimal', 'received', '') + 13 | '\n\n' + 14 | 'Expected value to not be a hexadecimal, received:\n' + 15 | ` ${printReceived(actual)}` 16 | : matcherHint('.toBeHexadecimal', 'received', '') + 17 | '\n\n' + 18 | 'Expected value to be a hexadecimal, received:\n' + 19 | ` ${printReceived(actual)}`, 20 | }; 21 | } 22 | 23 | const longRegex = RegExp(/^#\b[a-f0-9]{6}\b/gi); 24 | const shortRegex = RegExp(/^#\b[a-f0-9]{3}\b/gi); 25 | -------------------------------------------------------------------------------- /src/matchers/toBeInRange.ts: -------------------------------------------------------------------------------- 1 | export function toBeInRange(actual: unknown[], min: number, max: number) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, printExpected, matcherHint } = this.utils; 4 | 5 | const element = actual.find((option: any) => option < min || option >= max); 6 | 7 | const pass = element === undefined; 8 | 9 | return { 10 | pass, 11 | message: () => 12 | pass 13 | ? matcherHint('.not.toBeInRange') + 14 | '\n\n' + 15 | `Expected Array to not be in range ${printExpected(min)}, ${printExpected(max)}\n` + 16 | 'Received:\n' + 17 | ` ${printReceived(actual)}` 18 | : matcherHint('.toBeInRange') + 19 | '\n\n' + 20 | `Expected: Array elements to be in range (${printExpected(min)}, ${printExpected(max)})\n` + 21 | `Received: Array element out of range ${printReceived(element)}`, 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /src/matchers/toBeInteger.ts: -------------------------------------------------------------------------------- 1 | export function toBeInteger(actual: unknown) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, matcherHint } = this.utils; 4 | 5 | const pass = isNumber(actual) && isInteger(actual); 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeInteger', 'received', '') + 12 | '\n\n' + 13 | 'Expected value to not be an integer received:\n' + 14 | ` ${printReceived(actual)}` 15 | : matcherHint('.toBeInteger', 'received', '') + 16 | '\n\n' + 17 | 'Expected value to be an integer received:\n' + 18 | ` ${printReceived(actual)}`, 19 | }; 20 | } 21 | 22 | const isNumber = (value: any) => !isNaN(parseInt(value)); 23 | const isInteger = (value: any) => Number.isInteger(+value); 24 | -------------------------------------------------------------------------------- /src/matchers/toBeNaN.ts: -------------------------------------------------------------------------------- 1 | export function toBeNaN(actual: any) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, matcherHint } = this.utils; 4 | 5 | const pass = isNaN(actual); 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeNaN', 'received', '') + 12 | '\n\n' + 13 | 'Expected value to be a number received:\n' + 14 | ` ${printReceived(actual)}` 15 | : matcherHint('.toBeNaN', 'received', '') + 16 | '\n\n' + 17 | 'Expected value to not be a number received:\n' + 18 | ` ${printReceived(actual)}`, 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/matchers/toBeNegative.ts: -------------------------------------------------------------------------------- 1 | export function toBeNegative(actual: unknown) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, matcherHint } = this.utils; 4 | 5 | const pass = isNumber(actual) && isNegative(actual); 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeNegative', 'received', '') + 12 | '\n\n' + 13 | 'Expected value to not be a negative number received:\n' + 14 | ` ${printReceived(actual)}` 15 | : matcherHint('.toBeNegative', 'received', '') + 16 | '\n\n' + 17 | 'Expected value to be a negative number received:\n' + 18 | ` ${printReceived(actual)}`, 19 | }; 20 | } 21 | 22 | const isNumber = (value: any) => !isNaN(parseInt(value)); 23 | const isNegative = (value: any) => value < 0; 24 | -------------------------------------------------------------------------------- /src/matchers/toBeNil.ts: -------------------------------------------------------------------------------- 1 | export function toBeNil(actual: unknown) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, matcherHint } = this.utils; 4 | 5 | const pass = actual === undefined || actual === null; 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeNil', 'received', '') + 12 | '\n\n' + 13 | 'Expected value not to be null or undefined, received:\n' + 14 | ` ${printReceived(actual)}` 15 | : matcherHint('.toBeNil', 'received', '') + 16 | '\n\n' + 17 | 'Expected value to be null or undefined, received:\n' + 18 | ` ${printReceived(actual)}`, 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/matchers/toBeNumber.ts: -------------------------------------------------------------------------------- 1 | export function toBeNumber(actual: unknown) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, matcherHint } = this.utils; 4 | 5 | const pass = typeof actual === 'number'; 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeNumber', 'received', '') + 12 | '\n\n' + 13 | 'Expected value to not be a number received:\n' + 14 | ` ${printReceived(actual)}` 15 | : matcherHint('.toBeNumber', 'received', '') + 16 | '\n\n' + 17 | 'Expected value to be a number received:\n' + 18 | ` ${printReceived(actual)}`, 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/matchers/toBeObject.ts: -------------------------------------------------------------------------------- 1 | export function toBeObject(actual: unknown) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, matcherHint } = this.utils; 4 | 5 | const pass = typeof actual === 'object' && actual !== null && !Array.isArray(actual); 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeObject', 'received', '') + 12 | '\n\n' + 13 | 'Expected value to not be an object, received:\n' + 14 | ` ${printReceived(actual)}` 15 | : matcherHint('.toBeObject', 'received', '') + 16 | '\n\n' + 17 | 'Expected value to be an object, received:\n' + 18 | ` ${printReceived(actual)}`, 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/matchers/toBeOdd.ts: -------------------------------------------------------------------------------- 1 | export function toBeOdd(actual: unknown) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, matcherHint } = this.utils; 4 | 5 | const pass = isNumber(actual) && isOdd(actual); 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeOdd', 'received', '') + 12 | '\n\n' + 13 | 'Expected value to not be odd received:\n' + 14 | ` ${printReceived(actual)}` 15 | : matcherHint('.toBeOdd', 'received', '') + 16 | '\n\n' + 17 | 'Expected value to be odd received:\n' + 18 | ` ${printReceived(actual)}`, 19 | }; 20 | } 21 | 22 | const isNumber = (expected: any) => !isNaN(parseInt(expected)); 23 | const isOdd = (expected: any) => expected % 2 === 1; 24 | -------------------------------------------------------------------------------- /src/matchers/toBeOneOf.ts: -------------------------------------------------------------------------------- 1 | import { contains } from 'src/utils'; 2 | 3 | export function toBeOneOf(actual: unknown, expected: readonly E[]) { 4 | // @ts-expect-error OK to have implicit any for this.utils 5 | const { printReceived, printExpected, matcherHint } = this.utils; 6 | 7 | // @ts-expect-error OK to have implicit any for this.equals 8 | const pass = contains((a, b) => this.equals(a, b, this.customTesters), expected, actual); 9 | 10 | return { 11 | pass, 12 | message: () => 13 | pass 14 | ? matcherHint('.not.toBeOneOf') + 15 | '\n\n' + 16 | 'Expected value to not be in list:\n' + 17 | ` ${printExpected(expected)}\n` + 18 | 'Received:\n' + 19 | ` ${printReceived(actual)}` 20 | : matcherHint('.toBeOneOf') + 21 | '\n\n' + 22 | 'Expected value to be in list:\n' + 23 | ` ${printExpected(expected)}\n` + 24 | 'Received:\n' + 25 | ` ${printReceived(actual)}`, 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /src/matchers/toBePositive.ts: -------------------------------------------------------------------------------- 1 | export function toBePositive(actual: unknown) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, matcherHint } = this.utils; 4 | 5 | const pass = isNumber(actual) && isPositive(actual); 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBePositive', 'received', '') + 12 | '\n\n' + 13 | 'Expected value to not be positive received:\n' + 14 | ` ${printReceived(actual)}` 15 | : matcherHint('.toBePositive', 'received', '') + 16 | '\n\n' + 17 | 'Expected value to be positive received:\n' + 18 | ` ${printReceived(actual)}`, 19 | }; 20 | } 21 | 22 | const isNumber = (value: any) => !isNaN(parseInt(value)); 23 | const isPositive = (value: any) => value > 0; 24 | -------------------------------------------------------------------------------- /src/matchers/toBeSealed.ts: -------------------------------------------------------------------------------- 1 | export function toBeSealed(actual: unknown) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { matcherHint } = this.utils; 4 | 5 | const pass = Object.isSealed(actual); 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeSealed', 'received', '') + '\n\nExpected object to be not sealed' 12 | : matcherHint('.toBeSealed', 'received', '') + '\n\nExpected object to not sealed', 13 | }; 14 | } 15 | -------------------------------------------------------------------------------- /src/matchers/toBeString.ts: -------------------------------------------------------------------------------- 1 | export function toBeString(expected: unknown) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, printExpected, matcherHint } = this.utils; 4 | 5 | const pass = typeof expected === 'string' || expected instanceof String; 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeString', 'received', '') + 12 | '\n\n' + 13 | 'Expected value to not be of type string received:\n' + 14 | ` ${printReceived(expected)}` 15 | : matcherHint('.toBeString', 'received', '') + 16 | '\n\n' + 17 | 'Expected value to be of type string:\n' + 18 | ` ${printExpected('type of string')}\n` + 19 | 'Received:\n' + 20 | ` ${printReceived(typeof expected)}`, 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /src/matchers/toBeSymbol.ts: -------------------------------------------------------------------------------- 1 | export function toBeSymbol(actual: unknown) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, matcherHint } = this.utils; 4 | 5 | const pass = typeof actual === 'symbol'; 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeSymbol', 'received', '') + 12 | '\n\n' + 13 | 'Expected value to not be a symbol, received:\n' + 14 | ` ${printReceived(actual)}` 15 | : matcherHint('.toBeSymbol', 'received', '') + 16 | '\n\n' + 17 | 'Expected to receive a symbol, received:\n' + 18 | ` ${printReceived(actual)}`, 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/matchers/toBeTrue.ts: -------------------------------------------------------------------------------- 1 | export function toBeTrue(actual: unknown) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, printExpected, matcherHint } = this.utils; 4 | 5 | const pass = actual === true; 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeTrue', 'received', '') + 12 | '\n\n' + 13 | 'Expected value to not be true received:\n' + 14 | ` ${printReceived(actual)}` 15 | : matcherHint('.toBeTrue', 'received', '') + 16 | '\n\n' + 17 | 'Expected value to be true:\n' + 18 | ` ${printExpected(true)}\n` + 19 | 'Received:\n' + 20 | ` ${printReceived(actual)}`, 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /src/matchers/toBeValidDate.ts: -------------------------------------------------------------------------------- 1 | export function toBeValidDate(actual: unknown) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, matcherHint } = this.utils; 4 | 5 | const pass = actual instanceof Date && !isNaN(actual.getTime()); 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeValidDate', 'received', '') + 12 | '\n\n' + 13 | 'Expected value to not be a valid date received:\n' + 14 | ` ${printReceived(actual)}` 15 | : matcherHint('.toBeValidDate', 'received', '') + 16 | '\n\n' + 17 | 'Expected value to be a valid date received:\n' + 18 | ` ${printReceived(actual)}`, 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /src/matchers/toBeWithin.ts: -------------------------------------------------------------------------------- 1 | export function toBeWithin(actual: unknown, start: number, end: number) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, printExpected, matcherHint } = this.utils; 4 | 5 | const pass = (typeof actual === 'number' || typeof actual === 'bigint') && actual >= start && actual < end; 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toBeWithin') + 12 | '\n\n' + 13 | 'Expected number to not be within start (inclusive) and end (exclusive):\n' + 14 | ` start: ${printExpected(start)} end: ${printExpected(end)}\n` + 15 | 'Received:\n' + 16 | ` ${printReceived(actual)}` 17 | : matcherHint('.toBeWithin') + 18 | '\n\n' + 19 | 'Expected number to be within start (inclusive) and end (exclusive):\n' + 20 | ` start: ${printExpected(start)} end: ${printExpected(end)}\n` + 21 | 'Received:\n' + 22 | ` ${printReceived(actual)}`, 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /src/matchers/toChange.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Use `.toChange` when checking if a value has changed. 3 | */ 4 | export function toChange(mutator: () => unknown | void, checker: () => number) { 5 | // @ts-expect-error OK to have implicit any for this.utils 6 | const { printReceived: print, matcherHint: hint } = this.utils; 7 | 8 | const before = checker(); 9 | mutator(); 10 | const received = checker(); 11 | 12 | const passMessage = ` 13 | ${hint('.not.toChange', 'received', '')}\n\nExpected value to not change, received:\n ${print(received)} 14 | `.trim(); 15 | const failMessage = ` 16 | ${hint('.toChange', 'received', '')}\n\nExpected value to change, received:\n ${print(received)} 17 | `.trim(); 18 | 19 | const pass = received !== before; 20 | return { pass, message: () => (pass ? passMessage : failMessage) }; 21 | } 22 | -------------------------------------------------------------------------------- /src/matchers/toChangeBy.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Use `.toChangeBy` when checking if a value changed by an amount. 3 | */ 4 | export function toChangeBy(mutator: () => unknown | void, checker: () => number, by: number = 1) { 5 | // @ts-expect-error OK to have implicit any for this.utils 6 | const { printReceived: print, matcherHint: hint } = this.utils; 7 | 8 | const before = checker(); 9 | mutator(); 10 | const received = checker() - before; 11 | 12 | const passMessage = ` 13 | ${hint('.not.toChangeBy', 'received', '')}\n\nExpected value to not change by ${by}, received:\n ${print(received)} 14 | `.trim(); 15 | const failMessage = ` 16 | ${hint('.toChangeBy', 'received', '')}\n\nExpected value to change by ${by}, received:\n ${print(received)} 17 | `.trim(); 18 | 19 | const pass = received === by; 20 | return { pass, message: () => (pass ? passMessage : failMessage) }; 21 | } 22 | -------------------------------------------------------------------------------- /src/matchers/toChangeTo.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Use `.toChangeTo` when checking if a value changed to a specific value. 3 | */ 4 | export function toChangeTo(mutator: () => unknown | void, checker: () => number, to: number) { 5 | // @ts-expect-error OK to have implicit any for this.utils 6 | const { printReceived: print, matcherHint: hint } = this.utils; 7 | 8 | const before = checker(); 9 | 10 | if (before === to) { 11 | const noChangeMessage = `${hint( 12 | '.toChangeTo', 13 | 'received', 14 | '', 15 | )}\n\nCannot expect a value to change to its original state, received: ${print(before)}`; 16 | return { pass: false, message: () => noChangeMessage }; 17 | } 18 | 19 | mutator(); 20 | const received = checker(); 21 | 22 | const passMessage = ` 23 | ${hint('.not.toChangeTo', 'received', '')}\n\nExpected value to not change to ${to}, received:\n ${print(received)} 24 | `.trim(); 25 | const failMessage = ` 26 | ${hint('.toChangeto', 'received', '')}\n\nExpected value to change to ${to}, received:\n ${print(received)} 27 | `.trim(); 28 | 29 | const pass = received !== before && received === to; 30 | return { pass, message: () => (pass ? passMessage : failMessage) }; 31 | } 32 | -------------------------------------------------------------------------------- /src/matchers/toContainAllEntries.ts: -------------------------------------------------------------------------------- 1 | import { containsEntry } from 'src/utils'; 2 | 3 | export function toContainAllEntries( 4 | actual: unknown, 5 | expected: readonly (readonly [keyof E, E[keyof E]])[], 6 | ): { 7 | pass: boolean; 8 | message: () => string; 9 | } { 10 | // @ts-expect-error OK to have implicit any for this.utils 11 | const { printReceived, printExpected, matcherHint } = this.utils; 12 | 13 | const pass = 14 | typeof actual === 'object' && 15 | actual !== null && 16 | !Array.isArray(actual) && 17 | expected.length == Object.keys(actual as Record).length && 18 | expected.every(entry => 19 | // @ts-expect-error containsEntry takes an any type 20 | containsEntry((a, b) => this.equals(a, b, this.customTesters), actual, entry as [any, any]), 21 | ); 22 | 23 | return { 24 | pass, 25 | message: () => 26 | pass 27 | ? matcherHint('.not.toContainAllEntries') + 28 | '\n\n' + 29 | 'Expected object to not only contain all of the given entries:\n' + 30 | ` ${printExpected(expected)}\n` + 31 | 'Received:\n' + 32 | ` ${printReceived(actual)}` 33 | : matcherHint('.toContainAllEntries') + 34 | '\n\n' + 35 | 'Expected object to only contain all of the given entries:\n' + 36 | ` ${printExpected(expected)}\n` + 37 | 'Received:\n' + 38 | ` ${printReceived(actual)}`, 39 | }; 40 | } 41 | -------------------------------------------------------------------------------- /src/matchers/toContainAllKeys.ts: -------------------------------------------------------------------------------- 1 | import { contains } from 'src/utils'; 2 | 3 | export function toContainAllKeys(actual: unknown, expected: readonly (keyof E | string)[]) { 4 | // @ts-expect-error OK to have implicit any for this.utils 5 | const { printExpected, printReceived, matcherHint } = this.utils; 6 | 7 | let pass = false; 8 | if (typeof actual === 'object' && actual !== null && !Array.isArray(actual)) { 9 | const objectKeys = Object.keys(actual as Record); 10 | pass = 11 | objectKeys.length === expected.length && 12 | // @ts-expect-error OK to have implicit any for this.equals 13 | expected.every(key => contains((a, b) => this.equals(a, b, this.customTesters), objectKeys, key)); 14 | } 15 | 16 | return { 17 | pass, 18 | message: () => 19 | pass 20 | ? matcherHint('.not.toContainAllKeys') + 21 | '\n\n' + 22 | 'Expected object to not contain all keys:\n' + 23 | ` ${printExpected(expected)}\n` + 24 | 'Received:\n' + 25 | ` ${printReceived(Object.keys(actual as Record))}` 26 | : matcherHint('.toContainAllKeys') + 27 | '\n\n' + 28 | 'Expected object to contain all keys:\n' + 29 | ` ${printExpected(expected)}\n` + 30 | 'Received:\n' + 31 | ` ${printReceived(Object.keys(actual as Record))}`, 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /src/matchers/toContainAllValues.ts: -------------------------------------------------------------------------------- 1 | import { contains } from 'src/utils'; 2 | 3 | export function toContainAllValues(actual: unknown, expected: readonly E[]) { 4 | // @ts-expect-error OK to have implicit any for this.utils 5 | const { printReceived, printExpected, matcherHint } = this.utils; 6 | 7 | let pass = false; 8 | if (typeof actual === 'object' && actual !== null && !Array.isArray(actual)) { 9 | const values = Object.keys(actual as Record).map(k => (actual as Record)[k]); 10 | pass = 11 | values.length === expected.length && 12 | // @ts-expect-error OK to have implicit any for this.equals 13 | values.every(objectValue => contains((a, b) => this.equals(a, b, this.customTesters), expected, objectValue)); 14 | } 15 | 16 | return { 17 | pass, 18 | message: () => 19 | pass 20 | ? matcherHint('.not.toContainAllValues') + 21 | '\n\n' + 22 | 'Expected object to not contain all values:\n' + 23 | ` ${printExpected(expected)}\n` + 24 | 'Received:\n' + 25 | ` ${printReceived(actual)}` 26 | : matcherHint('.toContainAllValues') + 27 | '\n\n' + 28 | 'Expected object to contain all values:\n' + 29 | ` ${printExpected(expected)}\n` + 30 | 'Received:\n' + 31 | ` ${printReceived(actual)}`, 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /src/matchers/toContainAnyEntries.ts: -------------------------------------------------------------------------------- 1 | import { contains } from 'src/utils'; 2 | 3 | export function toContainAnyEntries( 4 | actual: unknown, 5 | expected: readonly (readonly [keyof E, E[keyof E]])[], 6 | ) { 7 | // @ts-expect-error OK to have implicit any for this.utils 8 | const { printReceived, printExpected, matcherHint } = this.utils; 9 | 10 | let pass = false; 11 | if (typeof actual === 'object' && actual !== null && !Array.isArray(actual)) { 12 | const entries = Object.keys(actual as Record).map(k => [ 13 | k, 14 | (actual as Record)[k], 15 | ]); 16 | // @ts-expect-error OK to have implicit any for this.equals 17 | pass = expected.some(entry => contains((a, b) => this.equals(a, b, this.customTesters), entries, entry)); 18 | } 19 | 20 | return { 21 | pass, 22 | message: () => 23 | pass 24 | ? matcherHint('.not.toContainAnyEntries') + 25 | '\n\n' + 26 | 'Expected object to not contain any of the provided entries:\n' + 27 | ` ${printExpected(expected)}\n` + 28 | 'Received:\n' + 29 | ` ${printReceived(actual)}` 30 | : matcherHint('.toContainAnyEntries') + 31 | '\n\n' + 32 | 'Expected object to contain any of the provided entries:\n' + 33 | ` ${printExpected(expected)}\n` + 34 | 'Received:\n' + 35 | ` ${printReceived(actual)}`, 36 | }; 37 | } 38 | -------------------------------------------------------------------------------- /src/matchers/toContainAnyKeys.ts: -------------------------------------------------------------------------------- 1 | export function toContainAnyKeys(actual: unknown, expected: readonly (keyof E | string)[]) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, printExpected, matcherHint } = this.utils; 4 | 5 | const pass = expected.some(key => Object.prototype.hasOwnProperty.call(actual, key)); 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toContainAnyKeys') + 12 | '\n\n' + 13 | 'Expected object not to contain any of the following keys:\n' + 14 | ` ${printExpected(expected)}\n` + 15 | 'Received:\n' + 16 | ` ${printReceived(actual)}` 17 | : matcherHint('.toContainAnyKeys') + 18 | '\n\n' + 19 | 'Expected object to contain any of the following keys:\n' + 20 | ` ${printExpected(expected)}\n` + 21 | 'Received:\n' + 22 | ` ${printReceived(actual)}`, 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /src/matchers/toContainAnyValues.ts: -------------------------------------------------------------------------------- 1 | import { contains } from 'src/utils'; 2 | 3 | export function toContainAnyValues(actual: unknown, expected: readonly E[]) { 4 | // @ts-expect-error OK to have implicit any for this.utils 5 | const { printReceived, printExpected, matcherHint } = this.utils; 6 | 7 | let pass = false; 8 | if (typeof actual === 'object' && actual !== null && !Array.isArray(actual)) { 9 | const objectValues = Object.keys(actual as Record).map( 10 | k => (actual as Record)[k], 11 | ); 12 | // @ts-expect-error OK to have implicit any for this.equals 13 | pass = expected.some(value => contains((a, b) => this.equals(a, b, this.customTesters), objectValues, value)); 14 | } 15 | 16 | return { 17 | pass, 18 | message: () => 19 | pass 20 | ? matcherHint('.not.toContainAnyValues') + 21 | '\n\n' + 22 | 'Expected object to not contain any of the following values:\n' + 23 | ` ${printExpected(expected)}\n` + 24 | 'Received:\n' + 25 | ` ${printReceived(actual)}` 26 | : matcherHint('.toContainAnyValues') + 27 | '\n\n' + 28 | 'Expected object to contain any of the following values:\n' + 29 | ` ${printExpected(expected)}\n` + 30 | 'Received:\n' + 31 | ` ${printReceived(actual)}`, 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /src/matchers/toContainEntries.ts: -------------------------------------------------------------------------------- 1 | import { containsEntry } from 'src/utils'; 2 | 3 | export function toContainEntries(actual: unknown, expected: readonly (readonly [keyof E, E[keyof E]])[]) { 4 | // @ts-expect-error OK to have implicit any for this.utils 5 | const { printReceived, printExpected, matcherHint } = this.utils; 6 | 7 | // @ts-expect-error containsEntry takes an any type 8 | const pass = expected.every(entry => containsEntry((a, b) => this.equals(a, b, this.customTesters), actual, entry)); 9 | 10 | return { 11 | pass, 12 | message: () => 13 | pass 14 | ? matcherHint('.not.toContainEntries') + 15 | '\n\n' + 16 | 'Expected object to not contain all of the given entries:\n' + 17 | ` ${printExpected(expected)}\n` + 18 | 'Received:\n' + 19 | ` ${printReceived(actual)}` 20 | : matcherHint('.toContainEntries') + 21 | '\n\n' + 22 | 'Expected object to contain all of the given entries:\n' + 23 | ` ${printExpected(expected)}\n` + 24 | 'Received:\n' + 25 | ` ${printReceived(actual)}`, 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /src/matchers/toContainEntry.ts: -------------------------------------------------------------------------------- 1 | import { containsEntry } from 'src/utils'; 2 | 3 | export function toContainEntry(actual: unknown, expected: readonly [keyof E, E[keyof E]]) { 4 | // @ts-expect-error OK to have implicit any for this.utils 5 | const { printReceived, printExpected, matcherHint } = this.utils; 6 | 7 | // @ts-expect-error containsEntry takes an any type 8 | const pass = containsEntry((a, b) => this.equals(a, b, this.customTesters), actual, expected); 9 | 10 | return { 11 | pass, 12 | message: () => 13 | pass 14 | ? matcherHint('.not.toContainEntry') + 15 | '\n\n' + 16 | 'Expected object to not contain entry:\n' + 17 | ` ${printExpected(expected)}\n` + 18 | 'Received:\n' + 19 | ` ${printReceived(actual)}` 20 | : matcherHint('.toContainEntry') + 21 | '\n\n' + 22 | 'Expected object to contain entry:\n' + 23 | ` ${printExpected(expected)}\n` + 24 | 'Received:\n' + 25 | ` ${printReceived(actual)}`, 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /src/matchers/toContainKey.ts: -------------------------------------------------------------------------------- 1 | export function toContainKey(actual: unknown, expected: keyof E | string) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, printExpected, matcherHint } = this.utils; 4 | 5 | const pass = 6 | typeof actual === 'object' && 7 | actual !== null && 8 | !Array.isArray(actual) && 9 | actual.hasOwnProperty && 10 | Object.prototype.hasOwnProperty.call(actual, expected); 11 | 12 | return { 13 | pass, 14 | message: () => 15 | pass 16 | ? matcherHint('.not.toContainKey') + 17 | '\n\n' + 18 | 'Expected object to not contain key:\n' + 19 | ` ${printExpected(expected)}\n` + 20 | 'Received:\n' + 21 | ` ${printReceived(actual)}` 22 | : matcherHint('.toContainKey') + 23 | '\n\n' + 24 | 'Expected object to contain key:\n' + 25 | ` ${printExpected(expected)}\n` + 26 | 'Received:\n' + 27 | ` ${printReceived(actual)}`, 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /src/matchers/toContainKeys.ts: -------------------------------------------------------------------------------- 1 | export function toContainKeys(actual: unknown, expected: readonly (keyof E | string)[]) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, printExpected, matcherHint } = this.utils; 4 | 5 | const pass = expected.every( 6 | key => actual && actual.hasOwnProperty && Object.prototype.hasOwnProperty.call(actual, key), 7 | ); 8 | 9 | return { 10 | pass, 11 | message: () => 12 | pass 13 | ? matcherHint('.not.toContainKeys') + 14 | '\n\n' + 15 | 'Expected object to not contain all keys:\n' + 16 | ` ${printExpected(expected)}\n` + 17 | 'Received:\n' + 18 | ` ${printReceived(actual)}` 19 | : matcherHint('.toContainKeys') + 20 | '\n\n' + 21 | 'Expected object to contain all keys:\n' + 22 | ` ${printExpected(expected)}\n` + 23 | 'Received:\n' + 24 | ` ${printReceived(actual)}`, 25 | }; 26 | } 27 | -------------------------------------------------------------------------------- /src/matchers/toContainValue.ts: -------------------------------------------------------------------------------- 1 | import { contains } from 'src/utils'; 2 | 3 | export function toContainValue(actual: unknown, expected: E) { 4 | // @ts-expect-error OK to have implicit any for this.utils 5 | const { printReceived, printExpected, matcherHint } = this.utils; 6 | 7 | let pass = false; 8 | if (typeof actual === 'object' && actual !== null && !Array.isArray(actual)) { 9 | const values = Object.keys(actual as Record).map(k => (actual as Record)[k]); 10 | // @ts-expect-error OK to have implicit any for this.equals 11 | pass = contains((a, b) => this.equals(a, b, this.customTesters), values, expected); 12 | } 13 | 14 | return { 15 | pass, 16 | message: () => 17 | pass 18 | ? matcherHint('.not.toContainValue') + 19 | '\n\n' + 20 | 'Expected object to not contain value:\n' + 21 | ` ${printExpected(expected)}\n` + 22 | 'Received:\n' + 23 | ` ${printReceived(actual)}` 24 | : matcherHint('.toContainValue') + 25 | '\n\n' + 26 | 'Expected object to contain value:\n' + 27 | ` ${printExpected(expected)}\n` + 28 | 'Received:\n' + 29 | ` ${printReceived(actual)}`, 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /src/matchers/toContainValues.ts: -------------------------------------------------------------------------------- 1 | import { contains } from 'src/utils'; 2 | 3 | export function toContainValues(actual: unknown, expected: readonly E[]) { 4 | // @ts-expect-error OK to have implicit any for this.utils 5 | const { printReceived, printExpected, matcherHint } = this.utils; 6 | 7 | let pass = false; 8 | if (typeof actual === 'object' && actual !== null && !Array.isArray(actual)) { 9 | const values = Object.keys(actual as Record).map(k => (actual as Record)[k]); 10 | // @ts-expect-error OK to have implicit any for this.equals 11 | pass = expected.every(value => contains((a, b) => this.equals(a, b, this.customTesters), values, value)); 12 | } 13 | 14 | return { 15 | pass, 16 | message: () => 17 | pass 18 | ? matcherHint('.not.toContainValues') + 19 | '\n\n' + 20 | 'Expected object to not contain all values:\n' + 21 | ` ${printExpected(expected)}\n` + 22 | 'Received:\n' + 23 | ` ${printReceived(actual)}` 24 | : matcherHint('.toContainValues') + 25 | '\n\n' + 26 | 'Expected object to contain all values:\n' + 27 | ` ${printExpected(expected)}\n` + 28 | 'Received:\n' + 29 | ` ${printReceived(actual)}`, 30 | }; 31 | } 32 | -------------------------------------------------------------------------------- /src/matchers/toEndWith.ts: -------------------------------------------------------------------------------- 1 | export function toEndWith(actual: unknown, expected: string) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, printExpected, matcherHint } = this.utils; 4 | 5 | const pass = typeof actual === 'string' && actual.endsWith(expected); 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toEndWith') + 12 | '\n\n' + 13 | 'Expected string to not end with:\n' + 14 | ` ${printExpected(expected)}\n` + 15 | 'Received:\n' + 16 | ` ${printReceived(actual)}` 17 | : matcherHint('.toEndWith') + 18 | '\n\n' + 19 | 'Expected string to end with:\n' + 20 | ` ${printExpected(expected)}\n` + 21 | 'Received:\n' + 22 | ` ${printReceived(actual)}`, 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /src/matchers/toEqualCaseInsensitive.ts: -------------------------------------------------------------------------------- 1 | export function toEqualCaseInsensitive(actual: unknown, expected: string) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, printExpected, matcherHint } = this.utils; 4 | 5 | const pass = String(actual).toLowerCase() === String(expected).toLowerCase(); 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toEqualCaseInsensitive') + 12 | '\n\n' + 13 | 'Expected values to not be equal while ignoring case (using ===):\n' + 14 | ` ${printExpected(expected)}\n` + 15 | 'Received:\n' + 16 | ` ${printReceived(actual)}` 17 | : matcherHint('.toEqualCaseInsensitive') + 18 | '\n\n' + 19 | 'Expected values to be equal while ignoring case (using ===):\n' + 20 | ` ${printExpected(expected)}\n` + 21 | 'Received:\n' + 22 | ` ${printReceived(actual)}`, 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /src/matchers/toHaveBeenCalledOnce.ts: -------------------------------------------------------------------------------- 1 | import { isJestMockOrSpy } from 'src/utils'; 2 | 3 | export function toHaveBeenCalledOnce(actual: unknown) { 4 | // @ts-expect-error OK to have implicit any for this.utils 5 | const { printReceived, printWithType, matcherHint } = this.utils; 6 | 7 | if (!isJestMockOrSpy(actual)) { 8 | return { 9 | pass: false, 10 | message: () => 11 | matcherHint('.toHaveBeenCalledOnce') + 12 | '\n\n' + 13 | `Matcher error: ${printReceived('received')} must be a mock or spy function` + 14 | '\n\n' + 15 | printWithType('Received', actual, printReceived), 16 | }; 17 | } 18 | 19 | // @ts-expect-error isJestMockOrSpy provides the type check 20 | const pass = actual.mock.calls.length === 1; 21 | 22 | return { 23 | pass, 24 | message: () => 25 | pass 26 | ? matcherHint('.not.toHaveBeenCalledOnce') + 27 | '\n\n' + 28 | 'Expected mock function to have been called any amount of times but one, but it was called exactly once.' 29 | : matcherHint('.toHaveBeenCalledOnce') + 30 | '\n\n' + 31 | 'Expected mock function to have been called exactly once, but it was called:\n' + 32 | // @ts-expect-error isJestMockOrSpy provides the type check 33 | ` ${printReceived(actual.mock.calls.length)} times`, 34 | actual: actual, 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /src/matchers/toInclude.ts: -------------------------------------------------------------------------------- 1 | export function toInclude(actual: unknown, expected: string) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, printExpected, matcherHint } = this.utils; 4 | 5 | const pass = typeof actual === 'string' && actual.includes(expected); 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toInclude') + 12 | '\n\n' + 13 | 'Expected string to not include:\n' + 14 | ` ${printExpected(expected)}\n` + 15 | 'Received:\n' + 16 | ` ${printReceived(actual)}` 17 | : matcherHint('.toInclude') + 18 | '\n\n' + 19 | 'Expected string to include:\n' + 20 | ` ${printExpected(expected)}\n` + 21 | 'Received:\n' + 22 | ` ${printReceived(actual)}`, 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /src/matchers/toIncludeAllMembers.ts: -------------------------------------------------------------------------------- 1 | import { contains } from 'src/utils'; 2 | 3 | export function toIncludeAllMembers(actual: unknown[], expected: readonly E[] | E) { 4 | // @ts-expect-error OK to have implicit any for this.utils 5 | const { printReceived, printExpected, matcherHint } = this.utils; 6 | 7 | const pass = 8 | Array.isArray(actual) && 9 | Array.isArray(expected) && 10 | // @ts-expect-error OK to have implicit any for this.equals 11 | expected.every(val => contains((a: unknown, b: unknown) => this.equals(a, b, this.customTesters), actual, val)); 12 | 13 | return { 14 | pass, 15 | message: () => 16 | pass 17 | ? matcherHint('.not.toIncludeAllMembers') + 18 | '\n\n' + 19 | 'Expected list to not have all of the following members:\n' + 20 | ` ${printExpected(expected)}\n` + 21 | 'Received:\n' + 22 | ` ${printReceived(actual)}` 23 | : matcherHint('.toIncludeAllMembers') + 24 | '\n\n' + 25 | 'Expected list to have all of the following members:\n' + 26 | ` ${printExpected(expected)}\n` + 27 | 'Received:\n' + 28 | ` ${printReceived(actual)}`, 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /src/matchers/toIncludeAllPartialMembers.ts: -------------------------------------------------------------------------------- 1 | import { containsEntry } from 'src/utils'; 2 | 3 | export function toIncludeAllPartialMembers(actual: unknown, expected: readonly E[] | E) { 4 | // @ts-expect-error OK to have implicit any for this.utils 5 | const { printReceived, printExpected, matcherHint } = this.utils; 6 | 7 | const pass = 8 | Array.isArray(actual) && 9 | Array.isArray(expected) && 10 | expected.every(partial => 11 | actual.some(value => 12 | Object.entries(partial).every(entry => 13 | // @ts-expect-error OK to have implicit any for this.equals 14 | containsEntry((a, b) => this.equals(a, b, this.customTesters), value, entry), 15 | ), 16 | ), 17 | ); 18 | 19 | return { 20 | pass, 21 | message: () => 22 | pass 23 | ? matcherHint('.not.toIncludeAllPartialMembers') + 24 | '\n\n' + 25 | 'Expected list to not have all of the following partial members:\n' + 26 | ` ${printExpected(expected)}\n` + 27 | 'Received:\n' + 28 | ` ${printReceived(actual)}` 29 | : matcherHint('.toIncludeAllPartialMembers') + 30 | '\n\n' + 31 | 'Expected list to have all of the following partial members:\n' + 32 | ` ${printExpected(expected)}\n` + 33 | 'Received:\n' + 34 | ` ${printReceived(actual)}`, 35 | }; 36 | } 37 | -------------------------------------------------------------------------------- /src/matchers/toIncludeAnyMembers.ts: -------------------------------------------------------------------------------- 1 | import { contains } from 'src/utils'; 2 | 3 | export function toIncludeAnyMembers(actual: unknown, expected: readonly E[] | E) { 4 | // @ts-expect-error OK to have implicit any for this.utils 5 | const { printReceived, printExpected, matcherHint } = this.utils; 6 | 7 | const pass = 8 | Array.isArray(actual) && 9 | Array.isArray(expected) && 10 | // @ts-expect-error OK to have implicit any for this.equals 11 | expected.some(member => contains((a, b) => this.equals(a, b, this.customTesters), actual, member)); 12 | 13 | return { 14 | pass, 15 | message: () => 16 | pass 17 | ? matcherHint('.not.toIncludeAnyMembers') + 18 | '\n\n' + 19 | 'Expected list to not include any of the following members:\n' + 20 | ` ${printExpected(expected)}\n` + 21 | 'Received:\n' + 22 | ` ${printReceived(actual)}` 23 | : matcherHint('.toIncludeAnyMembers') + 24 | '\n\n' + 25 | 'Expected list to include any of the following members:\n' + 26 | ` ${printExpected(expected)}\n` + 27 | 'Received:\n' + 28 | ` ${printReceived(actual)}`, 29 | }; 30 | } 31 | -------------------------------------------------------------------------------- /src/matchers/toIncludeMultiple.ts: -------------------------------------------------------------------------------- 1 | export function toIncludeMultiple(actual: unknown, expected: readonly string[]) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, printExpected, matcherHint } = this.utils; 4 | 5 | const pass = typeof actual === 'string' && expected.every(value => actual.includes(value)); 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toIncludeMultiple') + 12 | '\n\n' + 13 | 'Expected string to not contain all substrings: \n' + 14 | ` ${printExpected(expected)}\n` + 15 | 'Received: \n' + 16 | ` ${printReceived(actual)}` 17 | : matcherHint('.toIncludeMultiple') + 18 | '\n\n' + 19 | 'Expected string to contain all substrings: \n' + 20 | ` ${printExpected(expected)}\n` + 21 | 'Received:\n' + 22 | ` ${printReceived(actual)}`, 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /src/matchers/toIncludeRepeated.ts: -------------------------------------------------------------------------------- 1 | export function toIncludeRepeated(actual: unknown, expected: string, occurrences: number) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, printExpected, matcherHint } = this.utils; 4 | 5 | const pass = typeof actual === 'string' && (actual.match(new RegExp(expected, 'g')) || []).length === occurrences; 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toIncludeRepeated') + 12 | '\n\n' + 13 | `Expected string to not include repeated ${occurrences} times:\n` + 14 | ` ${printExpected(expected)}\n` + 15 | 'Received:\n' + 16 | ` ${printReceived(actual)}` 17 | : matcherHint('.toIncludeRepeated') + 18 | '\n\n' + 19 | `Expected string to include repeated ${occurrences} times:\n` + 20 | ` ${printExpected(expected)}\n` + 21 | 'Received:\n' + 22 | ` ${printReceived(actual)}`, 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /src/matchers/toIncludeSameMembers.ts: -------------------------------------------------------------------------------- 1 | export function toIncludeSameMembers(actual: unknown, expected: readonly E[]) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, printExpected, matcherHint } = this.utils; 4 | 5 | const pass = 6 | Array.isArray(actual) && 7 | Array.isArray(expected) && 8 | // @ts-expect-error OK to have implicit any for this.equals 9 | predicate((a, b) => this.equals(a, b, this.customTesters), actual, expected); 10 | 11 | return { 12 | pass, 13 | message: () => 14 | pass 15 | ? matcherHint('.not.toIncludeSameMembers') + 16 | '\n\n' + 17 | 'Expected list to not exactly match the members of:\n' + 18 | ` ${printExpected(expected)}\n` + 19 | 'Received:\n' + 20 | ` ${printReceived(actual)}` 21 | : matcherHint('.toIncludeSameMembers') + 22 | '\n\n' + 23 | 'Expected list to have the following members and no more:\n' + 24 | ` ${printExpected(expected)}\n` + 25 | 'Received:\n' + 26 | ` ${printReceived(actual)}`, 27 | }; 28 | } 29 | 30 | const predicate = (equals: any, actual: any, expected: any) => { 31 | if (!Array.isArray(actual) || !Array.isArray(expected) || actual.length !== expected.length) { 32 | return false; 33 | } 34 | 35 | const remaining = expected.reduce((remaining, secondValue) => { 36 | if (remaining === null) return remaining; 37 | 38 | const index = remaining.findIndex((firstValue: any) => equals(secondValue, firstValue)); 39 | 40 | if (index === -1) { 41 | return null; 42 | } 43 | 44 | return remaining.slice(0, index).concat(remaining.slice(index + 1)); 45 | }, actual); 46 | 47 | return !!remaining && remaining.length === 0; 48 | }; 49 | -------------------------------------------------------------------------------- /src/matchers/toIncludeSamePartialMembers.ts: -------------------------------------------------------------------------------- 1 | import { containsEntry } from '../utils'; 2 | 3 | export function toIncludeSamePartialMembers(actual: unknown, expected: E) { 4 | // @ts-expect-error OK to have implicit any for this.utils 5 | const { printReceived, printExpected, matcherHint } = this.utils; 6 | 7 | // @ts-expect-error OK to have implicit any for this.equals 8 | const pass = predicate((a, b) => this.equals(a, b, this.customTesters), actual, expected); 9 | 10 | return { 11 | pass, 12 | message: () => 13 | pass 14 | ? matcherHint('.not.toIncludeSamePartialMembers') + 15 | '\n\n' + 16 | 'Expected list to not exactly match the partial members of:\n' + 17 | ` ${printExpected(expected)}\n` + 18 | 'Received:\n' + 19 | ` ${printReceived(actual)}` 20 | : matcherHint('.toIncludeSamePartialMembers') + 21 | '\n\n' + 22 | 'Expected list to have the following partial members and no more:\n' + 23 | ` ${printExpected(expected)}\n` + 24 | 'Received:\n' + 25 | ` ${printReceived(actual)}`, 26 | }; 27 | } 28 | 29 | const predicate = (equals: any, actual: unknown, expected: any) => { 30 | if (!Array.isArray(actual) || !Array.isArray(expected) || actual.length !== expected.length) { 31 | return false; 32 | } 33 | 34 | const remaining = expected.reduce((remaining, expectedPartial) => { 35 | if (remaining === null) { 36 | return remaining; 37 | } 38 | 39 | const index = remaining.findIndex((actualValue: any) => 40 | Object.entries(expectedPartial).every(entry => containsEntry(equals, actualValue, entry)), 41 | ); 42 | 43 | if (index === -1) { 44 | return null; 45 | } 46 | 47 | return remaining.slice(0, index).concat(remaining.slice(index + 1)); 48 | }, actual); 49 | 50 | return !!remaining && remaining.length === 0; 51 | }; 52 | -------------------------------------------------------------------------------- /src/matchers/toPartiallyContain.ts: -------------------------------------------------------------------------------- 1 | import { containsEntry } from 'src/utils'; 2 | 3 | export function toPartiallyContain(actual: unknown, expected: E) { 4 | // @ts-expect-error OK to have implicit any for this.utils 5 | const { printReceived, printExpected, matcherHint } = this.utils; 6 | 7 | const pass = 8 | Array.isArray(actual) && 9 | Array.isArray([expected]) && 10 | [expected].every(partial => 11 | actual.some( 12 | value => 13 | typeof partial === 'object' && 14 | partial != null && 15 | Object.entries(partial).every(entry => 16 | // @ts-expect-error OK to have implicit any for this.equals 17 | containsEntry((a, b) => this.equals(a, b, this.customTesters), value, entry), 18 | ), 19 | ), 20 | ); 21 | 22 | return { 23 | pass, 24 | message: () => 25 | pass 26 | ? matcherHint('.not.toPartiallyContain') + 27 | '\n\n' + 28 | 'Expected array not to partially contain:\n' + 29 | ` ${printExpected(expected)}\n` + 30 | 'Received:\n' + 31 | ` ${printReceived(actual)}` 32 | : matcherHint('.toPartiallyContain') + 33 | '\n\n' + 34 | 'Expected array to partially contain:\n' + 35 | ` ${printExpected(expected)}\n` + 36 | 'Received:\n' + 37 | ` ${printReceived(actual)}`, 38 | }; 39 | } 40 | -------------------------------------------------------------------------------- /src/matchers/toReject.ts: -------------------------------------------------------------------------------- 1 | export async function toReject(actual: Promise) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { matcherHint } = this.utils; 4 | 5 | const pass = await actual.then( 6 | () => false, 7 | () => true, 8 | ); 9 | 10 | return { 11 | pass, 12 | message: () => 13 | pass 14 | ? matcherHint('.not.toReject', 'received', '') + '\n\nExpected promise to resolve, however it rejected.\n' 15 | : matcherHint('.toReject', 'received', '') + '\n\nExpected promise to reject, however it resolved.\n', 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /src/matchers/toResolve.ts: -------------------------------------------------------------------------------- 1 | export async function toResolve(actual: Promise) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { matcherHint } = this.utils; 4 | 5 | const pass = await actual.then( 6 | () => true, 7 | () => false, 8 | ); 9 | 10 | return { 11 | pass, 12 | message: () => 13 | pass 14 | ? matcherHint('.not.toResolve', 'received', '') + '\n\nExpected promise to reject, however it resolved.\n' 15 | : matcherHint('.toResolve', 'received', '') + '\n\nExpected promise to resolve, however it rejected.\n', 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /src/matchers/toSatisfy.ts: -------------------------------------------------------------------------------- 1 | export function toSatisfy(actual: E, expected: (x: E) => boolean) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, printExpected, matcherHint } = this.utils; 4 | 5 | const pass = expected(actual); 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toSatisfy', 'received', '') + 12 | '\n\n' + 13 | 'Expected value to not satisfy:\n' + 14 | ` ${printExpected(expected)}\n` + 15 | 'Received:\n' + 16 | ` ${printReceived(actual)}` 17 | : matcherHint('.toSatisfy', 'received', '') + 18 | '\n\n' + 19 | 'Expected value to satisfy:\n' + 20 | ` ${printExpected(expected)}\n` + 21 | 'Received:\n' + 22 | ` ${printReceived(actual)}`, 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /src/matchers/toSatisfyAll.ts: -------------------------------------------------------------------------------- 1 | export function toSatisfyAll(actual: E[], expected: (x: E) => boolean) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, printExpected, matcherHint } = this.utils; 4 | 5 | const pass = actual.every(expected); 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toSatisfyAll') + 12 | '\n\n' + 13 | 'Expected array to not satisfy predicate for all values:\n' + 14 | ` ${printExpected(expected)}\n` + 15 | 'Received:\n' + 16 | ` ${printReceived(actual)}` 17 | : matcherHint('.toSatisfyAll') + 18 | '\n\n' + 19 | 'Expected array to satisfy predicate for all values:\n' + 20 | ` ${printExpected(expected)}\n` + 21 | 'Received:\n' + 22 | ` ${printReceived(actual)}`, 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /src/matchers/toSatisfyAny.ts: -------------------------------------------------------------------------------- 1 | export function toSatisfyAny(actual: unknown, expected: (x: unknown) => boolean) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, printExpected, matcherHint } = this.utils; 4 | 5 | let pass = false; 6 | if (Array.isArray(actual)) { 7 | pass = actual.some(expected); 8 | } 9 | 10 | return { 11 | pass, 12 | message: () => 13 | pass 14 | ? matcherHint('.not.toSatisfyAny') + 15 | '\n\n' + 16 | 'Expected array to not satisfy predicate for any value:\n' + 17 | ` ${printExpected(expected)}\n` + 18 | 'Received:\n' + 19 | ` ${printReceived(actual)}` 20 | : matcherHint('.toSatisfyAny') + 21 | '\n\n' + 22 | 'Expected array to satisfy predicate for any values:\n' + 23 | ` ${printExpected(expected)}\n` + 24 | 'Received:\n' + 25 | ` ${printReceived(actual)}`, 26 | }; 27 | } 28 | -------------------------------------------------------------------------------- /src/matchers/toStartWith.ts: -------------------------------------------------------------------------------- 1 | export function toStartWith(actual: unknown, expected: string) { 2 | // @ts-expect-error OK to have implicit any for this.utils 3 | const { printReceived, printExpected, matcherHint } = this.utils; 4 | 5 | const pass = typeof actual === 'string' && actual.startsWith(expected); 6 | 7 | return { 8 | pass, 9 | message: () => 10 | pass 11 | ? matcherHint('.not.toStartWith') + 12 | '\n\n' + 13 | 'Expected string to not start with:\n' + 14 | ` ${printExpected(expected)}\n` + 15 | 'Received:\n' + 16 | ` ${printReceived(actual)}` 17 | : matcherHint('.toStartWith') + 18 | '\n\n' + 19 | 'Expected string to start with:\n' + 20 | ` ${printExpected(expected)}\n` + 21 | 'Received:\n' + 22 | ` ${printReceived(actual)}`, 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export const contains = (equals: any, list: any, value: any) => { 2 | return list.findIndex((item: any) => equals(item, value)) > -1; 3 | }; 4 | 5 | export const determinePropertyMessage = (actual: any, property: any, message = 'Not Accessible') => { 6 | return actual && Object.hasOwnProperty.call(actual, property) ? actual[property] : message; 7 | }; 8 | 9 | export const isJestMockOrSpy: any = (value: any) => { 10 | return !!(value && value._isMockFunction === true && typeof value.mock === 'object'); 11 | }; 12 | 13 | export const containsEntry = (equals: any, obj: any, [key, value]: [any, any]) => 14 | obj.hasOwnProperty && Object.prototype.hasOwnProperty.call(obj, key) && equals(obj[key], value); 15 | -------------------------------------------------------------------------------- /test/fixtures/counter.ts: -------------------------------------------------------------------------------- 1 | export class Counter { 2 | private value: number; 3 | 4 | constructor() { 5 | this.increment = this.increment.bind(this); 6 | this.count = this.count.bind(this); 7 | this.reset = this.reset.bind(this); 8 | this.value = 0; 9 | } 10 | 11 | increment() { 12 | this.value++; 13 | } 14 | 15 | count() { 16 | return this.value; 17 | } 18 | 19 | reset() { 20 | this.value = 0; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/fail.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.fail fails with message 1`] = `"This shouldn't fail!"`; 4 | 5 | exports[`.fail fails without message 1`] = `"fails by .fail() assertion"`; 6 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/pass.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.pass does not pass, has no message 1`] = `"passes by .pass() assertion"`; 4 | 5 | exports[`.not.pass does not.pass, has no message 1`] = `"This should not pass!"`; 6 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeAfter.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeAfter fails when given a later date 1`] = ` 4 | "expect(received).not.toBeAfter() 5 | 6 | Expected date to be after 2018-06-01T22:00:00.000Z but received: 7 | 2018-06-02T22:00:00.000Z" 8 | `; 9 | 10 | exports[`.toBeAfter fails when actual is not a Date 1`] = ` 11 | "expect(received).toBeAfter() 12 | 13 | Expected date to be after 2018-06-01T22:00:00.000Z but received: 14 | "not-a-date"" 15 | `; 16 | 17 | exports[`.toBeAfter fails when given an earlier date 1`] = ` 18 | "expect(received).toBeAfter() 19 | 20 | Expected date to be after 2018-06-02T22:00:00.000Z but received: 21 | 2018-06-01T22:00:00.000Z" 22 | `; 23 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeAfterOrEqualTo.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeAfterOrEqualTo fails when given a later date 1`] = ` 4 | "expect(received).not.toBeAfterOrEqualTo() 5 | 6 | Expected date to be after or equal to 2019-09-01T22:00:00.000Z but received: 7 | 2019-09-10T22:00:00.000Z" 8 | `; 9 | 10 | exports[`.not.toBeAfterOrEqualTo fails when given an equal date 1`] = ` 11 | "expect(received).not.toBeAfterOrEqualTo() 12 | 13 | Expected date to be after or equal to 2019-09-01T22:00:00.000Z but received: 14 | 2019-09-01T22:00:00.000Z" 15 | `; 16 | 17 | exports[`.toBeAfterOrEqualTo fails when actual is not a Date 1`] = ` 18 | "expect(received).toBeAfterOrEqualTo() 19 | 20 | Expected date to be after or equal to 2019-09-01T22:00:00.000Z but received: 21 | "not-a-date"" 22 | `; 23 | 24 | exports[`.toBeAfterOrEqualTo fails when given an earlier date 1`] = ` 25 | "expect(received).toBeAfterOrEqualTo() 26 | 27 | Expected date to be after or equal to 2019-09-10T22:00:00.000Z but received: 28 | 2019-09-01T22:00:00.000Z" 29 | `; 30 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeArray.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeArray fails when given an array 1`] = ` 4 | "expect(received).not.toBeArray() 5 | 6 | Expected value to not be an array received: 7 | []" 8 | `; 9 | 10 | exports[`.toBeArray fails when not given an array 1`] = ` 11 | "expect(received).toBeArray() 12 | 13 | Expected value to be an array received: 14 | false" 15 | `; 16 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeBefore.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeBefore fails when given an earlier date 1`] = ` 4 | "expect(received).not.toBeBefore() 5 | 6 | Expected date to be before 2018-06-02T22:00:00.000Z but received: 7 | 2018-06-01T22:00:00.000Z" 8 | `; 9 | 10 | exports[`.toBeBefore fails when actual is not a Date 1`] = ` 11 | "expect(received).toBeBefore() 12 | 13 | Expected date to be before 2018-06-02T22:00:00.000Z but received: 14 | "not-a-date"" 15 | `; 16 | 17 | exports[`.toBeBefore fails when given a later date 1`] = ` 18 | "expect(received).toBeBefore() 19 | 20 | Expected date to be before 2018-06-01T22:00:00.000Z but received: 21 | 2018-06-02T22:00:00.000Z" 22 | `; 23 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeBeforeOrEqualTo.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeBeforeOrEqualTo fails when given an earlier date 1`] = ` 4 | "expect(received).not.toBeBeforeOrEqualTo() 5 | 6 | Expected date to be before or equal to 2019-09-10T22:00:00.000Z but received: 7 | 2019-09-01T22:00:00.000Z" 8 | `; 9 | 10 | exports[`.not.toBeBeforeOrEqualTo fails when given an equal date 1`] = ` 11 | "expect(received).not.toBeBeforeOrEqualTo() 12 | 13 | Expected date to be before or equal to 2019-09-01T22:00:00.000Z but received: 14 | 2019-09-01T22:00:00.000Z" 15 | `; 16 | 17 | exports[`.toBeBeforeOrEqualTo fails when actual is not a Date 1`] = ` 18 | "expect(received).toBeBeforeOrEqualTo() 19 | 20 | Expected date to be before or equal to 2019-09-10T22:00:00.000Z but received: 21 | "not-a-date"" 22 | `; 23 | 24 | exports[`.toBeBeforeOrEqualTo fails when given a later date 1`] = ` 25 | "expect(received).toBeBeforeOrEqualTo() 26 | 27 | Expected date to be before or equal to 2019-09-01T22:00:00.000Z but received: 28 | 2019-09-10T22:00:00.000Z" 29 | `; 30 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeBetween.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeBefore fails when date is in given range 1`] = ` 4 | "expect(received).not.toBeBetween() 5 | 6 | Expected date to be between 2019-09-01T22:00:00.000Z and 2019-09-10T22:00:00.000Z but received: 7 | 2019-09-03T22:00:00.000Z" 8 | `; 9 | 10 | exports[`.toBeBetween fails when actual is not a Date 1`] = ` 11 | "expect(received).toBeBetween() 12 | 13 | Expected date to be between 2019-09-01T22:00:00.000Z and 2019-09-10T22:00:00.000Z but received: 14 | "not-a-date"" 15 | `; 16 | 17 | exports[`.toBeBetween fails when date is not in given range 1`] = ` 18 | "expect(received).toBeBetween() 19 | 20 | Expected date to be between 2019-09-03T22:00:00.000Z and 2019-09-10T22:00:00.000Z but received: 21 | 2019-09-01T22:00:00.000Z" 22 | `; 23 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeBoolean.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeBoolean fails when given a boolean 1`] = ` 4 | "expect(received).not.toBeBoolean() 5 | 6 | Expected value to not be of type boolean, received: 7 | true" 8 | `; 9 | 10 | exports[`.not.toBeBoolean fails when given an object of type boolean 1`] = ` 11 | "expect(received).not.toBeBoolean() 12 | 13 | Expected value to not be of type boolean, received: 14 | {}" 15 | `; 16 | 17 | exports[`.toBeBoolean fails when not given a boolean 1`] = ` 18 | "expect(received).toBeBoolean() 19 | 20 | Expected value to be of type boolean, received: 21 | 1" 22 | `; 23 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeDate.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeDate fails when given a date 1`] = ` 4 | "expect(received).not.toBeDate() 5 | 6 | Expected value to not be a date received: 7 | 2018-01-01T13:00:00.000Z" 8 | `; 9 | 10 | exports[`.toBeDate fails when not given a date 1`] = ` 11 | "expect(received).toBeDate() 12 | 13 | Expected value to be a date received: 14 | false" 15 | `; 16 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeDateString.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeDateString fails when given a date string 1`] = ` 4 | "expect(received).not.toBeDateString() 5 | 6 | Expected value to not be a date string received: 7 | "2018-01-01T13:00:00.000Z"" 8 | `; 9 | 10 | exports[`.toBeDateString fails when not given a date string 1`] = ` 11 | "expect(received).toBeDateString() 12 | 13 | Expected value to be a date string received: 14 | "not a date"" 15 | `; 16 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeEmpty.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeEmpty fails when given empty string 1`] = ` 4 | "expect(received).not.toBeEmpty() 5 | 6 | Expected value to not be empty received: 7 | """ 8 | `; 9 | 10 | exports[`.toBeEmpty fails when given non-empty string 1`] = ` 11 | "expect(received).toBeEmpty() 12 | 13 | Expected value to be empty received: 14 | "string"" 15 | `; 16 | 17 | exports[`toBeEmpty with custom equality tester fails when custom equality does not match empty object 1`] = ` 18 | "expect(received).toBeEmpty() 19 | 20 | Expected value to be empty received: 21 | {}" 22 | `; 23 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeEmptyObject.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeEmptyObject fails when given an empty object 1`] = ` 4 | "expect(received).not.toBeEmptyObject() 5 | 6 | Expected value to not be an empty object, received: 7 | {}" 8 | `; 9 | 10 | exports[`.toBeEmptyObject fails when not given an empty object 1`] = ` 11 | "expect(received).toBeEmptyObject() 12 | 13 | Expected value to be an empty object, received: 14 | {"property1": "something"}" 15 | `; 16 | 17 | exports[`.toBeEmptyObject fails when not given an object 1`] = ` 18 | "expect(received).toBeEmptyObject() 19 | 20 | Expected value to be an empty object, received: 21 | null" 22 | `; 23 | 24 | exports[`.toBeEmptyObject fails when not given an object 2`] = ` 25 | "expect(received).toBeEmptyObject() 26 | 27 | Expected value to be an empty object, received: 28 | [42]" 29 | `; 30 | 31 | exports[`.toBeEmptyObject fails when not given an object 3`] = ` 32 | "expect(received).toBeEmptyObject() 33 | 34 | Expected value to be an empty object, received: 35 | 42" 36 | `; 37 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeFalse.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeFalse fails when given false 1`] = ` 4 | "expect(received).not.toBeFalse() 5 | 6 | Expected value to not be false received: 7 | false" 8 | `; 9 | 10 | exports[`.toBeFalse fails when not given false 1`] = ` 11 | "expect(received).toBeFalse() 12 | 13 | Expected value to be false: 14 | false 15 | Received: 16 | true" 17 | `; 18 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeFinite.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeFinite fails when given a finite number 1`] = ` 4 | "expect(received).not.toBeFinite() 5 | 6 | Expected value to not be finite received: 7 | 1" 8 | `; 9 | 10 | exports[`.toBeFinite fails when not given Infinity 1`] = ` 11 | "expect(received).toBeFinite() 12 | 13 | Expected value to be finite received: 14 | Infinity" 15 | `; 16 | 17 | exports[`.toBeFinite fails when not given NaN 1`] = ` 18 | "expect(received).toBeFinite() 19 | 20 | Expected value to be finite received: 21 | NaN" 22 | `; 23 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeFrozen.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeFrozen fails when given frozen object 1`] = ` 4 | "expect(received).not.toBeFrozen() 5 | 6 | Expected object to not be frozen" 7 | `; 8 | 9 | exports[`.toBeFrozen fails when given a non-frozen object 1`] = ` 10 | "expect(received).toBeFrozen() 11 | 12 | Expected object to be frozen" 13 | `; 14 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeFunction.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeFunction fails when given a function 1`] = ` 4 | "expect(received).not.toBeFunction() 5 | 6 | Expected value to not be a function, received: 7 | [Function anonymous]" 8 | `; 9 | 10 | exports[`.toBeFunction fails when not given a function 1`] = ` 11 | "expect(received).toBeFunction() 12 | 13 | Expected to receive a function, received: 14 | false" 15 | `; 16 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeHexadecimal.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeHexadecimal fails when given valid hexadecimal 1`] = ` 4 | "expect(received).not.toBeHexadecimal() 5 | 6 | Expected value to not be a hexadecimal, received: 7 | "#eeffee"" 8 | `; 9 | 10 | exports[`.toBeHexadecimal fails when given non-string 1`] = ` 11 | "expect(received).toBeHexadecimal() 12 | 13 | Expected value to be a hexadecimal, received: 14 | true" 15 | `; 16 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeInRange.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeInRange fails when given array is in the given range 1`] = ` 4 | "expect(received).not.toBeInRange(expected) 5 | 6 | Expected Array to not be in range 4, 10 7 | Received: 8 | [4, 5, 7, 9]" 9 | `; 10 | 11 | exports[`.toBeInRange fails when given array is not in a given range 1`] = ` 12 | "expect(received).toBeInRange(expected) 13 | 14 | Expected: Array elements to be in range (4, 8) 15 | Received: Array element out of range 9" 16 | `; 17 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeInteger.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeInteger fails when given integer 1`] = ` 4 | "expect(received).not.toBeInteger() 5 | 6 | Expected value to not be an integer received: 7 | 1" 8 | `; 9 | 10 | exports[`.toBeInteger fails when given fraction 1`] = ` 11 | "expect(received).toBeInteger() 12 | 13 | Expected value to be an integer received: 14 | 1.5" 15 | `; 16 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeNaN.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeNaN fails when given a non-number 1`] = ` 4 | "expect(received).not.toBeNaN() 5 | 6 | Expected value to be a number received: 7 | undefined" 8 | `; 9 | 10 | exports[`.toBeNaN fails when given a number 1`] = ` 11 | "expect(received).toBeNaN() 12 | 13 | Expected value to not be a number received: 14 | 3" 15 | `; 16 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeNegative.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeNegative fails when given negative number 1`] = ` 4 | "expect(received).not.toBeNegative() 5 | 6 | Expected value to not be a negative number received: 7 | -1" 8 | `; 9 | 10 | exports[`.toBeNegative fails when given Infinity 1`] = ` 11 | "expect(received).toBeNegative() 12 | 13 | Expected value to be a negative number received: 14 | Infinity" 15 | `; 16 | 17 | exports[`.toBeNegative fails when given positive number 1`] = ` 18 | "expect(received).toBeNegative() 19 | 20 | Expected value to be a negative number received: 21 | 1" 22 | `; 23 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeNil.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeNil fails when null is given 1`] = ` 4 | "expect(received).not.toBeNil() 5 | 6 | Expected value not to be null or undefined, received: 7 | null" 8 | `; 9 | 10 | exports[`.toBeNil fails when the value is not null or undefined 1`] = ` 11 | "expect(received).toBeNil() 12 | 13 | Expected value to be null or undefined, received: 14 | "value"" 15 | `; 16 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeNumber.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeNumber fails when given a number 1`] = ` 4 | "expect(received).not.toBeNumber() 5 | 6 | Expected value to not be a number received: 7 | 1" 8 | `; 9 | 10 | exports[`.toBeNumber fails when not given a number 1`] = ` 11 | "expect(received).toBeNumber() 12 | 13 | Expected value to be a number received: 14 | false" 15 | `; 16 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeOneOf.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeOneOf fails when value is in given array 1`] = ` 4 | "expect(received).not.toBeOneOf(expected) 5 | 6 | Expected value to not be in list: 7 | [1, 2, 3] 8 | Received: 9 | 1" 10 | `; 11 | 12 | exports[`.toBeOneOf fails when value is not in given array 1`] = ` 13 | "expect(received).toBeOneOf(expected) 14 | 15 | Expected value to be in list: 16 | [1, 2, 3] 17 | Received: 18 | 4" 19 | `; 20 | 21 | exports[`toBeOneOf with custom equality tester fails when custom equality does not match any array element 1`] = ` 22 | "expect(received).toBeOneOf(expected) 23 | 24 | Expected value to be in list: 25 | [1, 2, 3] 26 | Received: 27 | 1" 28 | `; 29 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBePositive.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBePositive fails when given a positive number 1`] = ` 4 | "expect(received).not.toBePositive() 5 | 6 | Expected value to not be positive received: 7 | 5" 8 | `; 9 | 10 | exports[`.toBePositive fails when not given a positive number 1`] = ` 11 | "expect(received).toBePositive() 12 | 13 | Expected value to be positive received: 14 | -1" 15 | `; 16 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeSealed.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeSealed fails when given sealed object 1`] = ` 4 | "expect(received).not.toBeSealed() 5 | 6 | Expected object to be not sealed" 7 | `; 8 | 9 | exports[`.toBeSealed fails when given a non-sealed object 1`] = ` 10 | "expect(received).toBeSealed() 11 | 12 | Expected object to not sealed" 13 | `; 14 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeString.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeString fails when given a string literal 1`] = ` 4 | "expect(received).not.toBeString() 5 | 6 | Expected value to not be of type string received: 7 | """ 8 | `; 9 | 10 | exports[`.not.toBeString fails when given an object of type string 1`] = ` 11 | "expect(received).not.toBeString() 12 | 13 | Expected value to not be of type string received: 14 | {"0": "s", "1": "t", "10": "e", "2": "r", "3": "i", "4": "n", "5": "g", "6": " ", "7": "t", "8": "y", "9": "p"}" 15 | `; 16 | 17 | exports[`.toBeString fails when not given a string 1`] = ` 18 | "expect(received).toBeString() 19 | 20 | Expected value to be of type string: 21 | "type of string" 22 | Received: 23 | "number"" 24 | `; 25 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeSymbol.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeSymbol fails when given a symbol 1`] = ` 4 | "expect(received).not.toBeSymbol() 5 | 6 | Expected value to not be a symbol, received: 7 | Symbol()" 8 | `; 9 | 10 | exports[`.toBeSymbol fails when not given a symbol 1`] = ` 11 | "expect(received).toBeSymbol() 12 | 13 | Expected to receive a symbol, received: 14 | false" 15 | `; 16 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeTrue.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeTrue fails when given true 1`] = ` 4 | "expect(received).not.toBeTrue() 5 | 6 | Expected value to not be true received: 7 | true" 8 | `; 9 | 10 | exports[`.toBeTrue fails when not given true 1`] = ` 11 | "expect(received).toBeTrue() 12 | 13 | Expected value to be true: 14 | true 15 | Received: 16 | false" 17 | `; 18 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeValidDate.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeValidDate fails when given a valid date value 1`] = ` 4 | "expect(received).not.toBeValidDate() 5 | 6 | Expected value to not be a valid date received: 7 | 2018-01-01T13:00:00.000Z" 8 | `; 9 | 10 | exports[`.toBeValidDate fails when given an invalid date 1`] = ` 11 | "expect(received).toBeValidDate() 12 | 13 | Expected value to be a valid date received: 14 | Date { NaN }" 15 | `; 16 | 17 | exports[`.toBeValidDate fails when not given non-date values 1`] = ` 18 | "expect(received).toBeValidDate() 19 | 20 | Expected value to be a valid date received: 21 | 1" 22 | `; 23 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toBeWithin.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toBeWithin fails when given number is within the given bounds of start (inclusive) and end (exclusive) 1`] = ` 4 | "expect(received).not.toBeWithin(expected) 5 | 6 | Expected number to not be within start (inclusive) and end (exclusive): 7 | start: 1 end: 3 8 | Received: 9 | 1" 10 | `; 11 | 12 | exports[`.toBeWithin fails when given number is not within the given bounds of start (inclusive) and end (exclusive) 1`] = ` 13 | "expect(received).toBeWithin(expected) 14 | 15 | Expected number to be within start (inclusive) and end (exclusive): 16 | start: 1 end: 3 17 | Received: 18 | 3" 19 | `; 20 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toChange.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toChange fails when a value expected not to change defies all expectations and changes 1`] = ` 4 | "expect(received).not.toChange() 5 | 6 | Expected value to not change, received: 7 | 1" 8 | `; 9 | 10 | exports[`.not.toChange fails when mutating a counter 1`] = ` 11 | "expect(received).not.toChange() 12 | 13 | Expected value to not change, received: 14 | 1" 15 | `; 16 | 17 | exports[`.toChange fails when a given value does not increment 1`] = ` 18 | "expect(received).toChange() 19 | 20 | Expected value to change, received: 21 | 0" 22 | `; 23 | 24 | exports[`.toChange fails when not mutating a counter 1`] = ` 25 | "expect(received).toChange() 26 | 27 | Expected value to change, received: 28 | 0" 29 | `; 30 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toChangeBy.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toChangeBy fails when a value expected not to change defies all expectations and changes 1`] = ` 4 | "expect(received).not.toChangeBy() 5 | 6 | Expected value to not change by 1, received: 7 | 1" 8 | `; 9 | 10 | exports[`.not.toChangeBy fails when mutating a counter 1`] = ` 11 | "expect(received).not.toChangeBy() 12 | 13 | Expected value to not change by 1, received: 14 | 1" 15 | `; 16 | 17 | exports[`.toChangeBy fails when a given value does not increment 1`] = ` 18 | "expect(received).toChangeBy() 19 | 20 | Expected value to change by 1, received: 21 | 0" 22 | `; 23 | 24 | exports[`.toChangeBy fails when not mutating a counter 1`] = ` 25 | "expect(received).toChangeBy() 26 | 27 | Expected value to change by 1, received: 28 | 0" 29 | `; 30 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toChangeTo.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toChange fails when a value expected not to change defies all expectations and changes 1`] = ` 4 | "expect(received).not.toChangeTo() 5 | 6 | Expected value to not change to 1, received: 7 | 1" 8 | `; 9 | 10 | exports[`.not.toChange fails when mutating a counter 1`] = ` 11 | "expect(received).not.toChangeTo() 12 | 13 | Expected value to not change to 1, received: 14 | 1" 15 | `; 16 | 17 | exports[`.toChangeTo fails when a given value does not increment 1`] = ` 18 | "expect(received).toChangeto() 19 | 20 | Expected value to change to 1, received: 21 | 0" 22 | `; 23 | 24 | exports[`.toChangeTo fails when not mutating a counter 1`] = ` 25 | "expect(received).toChangeto() 26 | 27 | Expected value to change to 1, received: 28 | 0" 29 | `; 30 | 31 | exports[`.toChangeTo fails when resetting a counter back because a change cannot be the same as the initial value 1`] = ` 32 | "expect(received).toChangeTo() 33 | 34 | Cannot expect a value to change to its original state, received: 0" 35 | `; 36 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toContainAnyKeys.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toContainAnyKeys fails when object contains one or more keys 1`] = ` 4 | "expect(received).not.toContainAnyKeys(expected) 5 | 6 | Expected object not to contain any of the following keys: 7 | ["name", "age"] 8 | Received: 9 | {"age": 37, "name": "Steve the Pirate"}" 10 | `; 11 | 12 | exports[`.toContainAnyKeys fails when object does not contain any keys 1`] = ` 13 | "expect(received).toContainAnyKeys(expected) 14 | 15 | Expected object to contain any of the following keys: 16 | ["occupation"] 17 | Received: 18 | {"age": 37, "name": "Steve the Pirate"}" 19 | `; 20 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toContainEntries.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toContainEntries fails when object contains all of the given entries 1`] = ` 4 | "expect(received).not.toContainEntries(expected) 5 | 6 | Expected object to not contain all of the given entries: 7 | [["b", "bar"], ["c", "baz"]] 8 | Received: 9 | {"a": "foo", "b": "bar", "c": "baz"}" 10 | `; 11 | 12 | exports[`.toContainEntries fails when object does not contain all of the given entries 1`] = ` 13 | "expect(received).toContainEntries(expected) 14 | 15 | Expected object to contain all of the given entries: 16 | [["b", "foo"], ["a", "foo"]] 17 | Received: 18 | {"a": "foo", "b": "bar", "c": "baz"}" 19 | `; 20 | 21 | exports[`toContainEntries with custom equality tester fails when custom equality does not match any of the values 1`] = ` 22 | "expect(received).toContainEntries(expected) 23 | 24 | Expected object to contain all of the given entries: 25 | [["a", "foo"]] 26 | Received: 27 | {"a": "foo", "b": "bar", "c": "baz"}" 28 | `; 29 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toContainEntry.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toContainEntry fails when object contains given entry 1`] = ` 4 | "expect(received).not.toContainEntry(expected) 5 | 6 | Expected object to not contain entry: 7 | ["b", "bar"] 8 | Received: 9 | {"a": "foo", "b": "bar", "c": "baz"}" 10 | `; 11 | 12 | exports[`.toContainEntry fails when object does not contain given entry 1`] = ` 13 | "expect(received).toContainEntry(expected) 14 | 15 | Expected object to contain entry: 16 | ["b", "foo"] 17 | Received: 18 | {"a": "foo", "b": "bar", "c": "baz"}" 19 | `; 20 | 21 | exports[`toContainEntry with custom equality tester fails when custom equality does not match any of the values 1`] = ` 22 | "expect(received).toContainEntry(expected) 23 | 24 | Expected object to contain entry: 25 | ["a", "foo"] 26 | Received: 27 | {"a": "foo", "b": "bar", "c": "baz"}" 28 | `; 29 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toContainKey.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toContainKey fails when given object contains key 1`] = ` 4 | "expect(received).not.toContainKey(expected) 5 | 6 | Expected object to not contain key: 7 | "hello" 8 | Received: 9 | {"hello": "world"}" 10 | `; 11 | 12 | exports[`.toContainKey fails when actual is not an object 1`] = ` 13 | "expect(received).toContainKey(expected) 14 | 15 | Expected object to contain key: 16 | "hello" 17 | Received: 18 | null" 19 | `; 20 | 21 | exports[`.toContainKey fails when actual is not an object 2`] = ` 22 | "expect(received).toContainKey(expected) 23 | 24 | Expected object to contain key: 25 | "hello" 26 | Received: 27 | 42" 28 | `; 29 | 30 | exports[`.toContainKey fails when given object does not contain key 1`] = ` 31 | "expect(received).toContainKey(expected) 32 | 33 | Expected object to contain key: 34 | "missing" 35 | Received: 36 | {"hello": "world"}" 37 | `; 38 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toContainKeys.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toContainKeys fails when object contains all keys 1`] = ` 4 | "expect(received).not.toContainKeys(expected) 5 | 6 | Expected object to not contain all keys: 7 | ["a", "b", "c"] 8 | Received: 9 | {"a": "foo", "b": "bar", "c": "baz"}" 10 | `; 11 | 12 | exports[`.toContainKeys fails when object does not contain all keys 1`] = ` 13 | "expect(received).toContainKeys(expected) 14 | 15 | Expected object to contain all keys: 16 | ["a", "d"] 17 | Received: 18 | {"a": "foo", "b": "bar", "c": "baz"}" 19 | `; 20 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toEndWith.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toEndWith fails when string ends with given suffix 1`] = ` 4 | "expect(received).not.toEndWith(expected) 5 | 6 | Expected string to not end with: 7 | "world" 8 | Received: 9 | "hello world"" 10 | `; 11 | 12 | exports[`.toEndWith fails when string does not end with the given suffix 1`] = ` 13 | "expect(received).toEndWith(expected) 14 | 15 | Expected string to end with: 16 | "hello" 17 | Received: 18 | "hello world"" 19 | `; 20 | 21 | exports[`.toEndWith fails when the string is shorter than the given suffix 1`] = ` 22 | "expect(received).toEndWith(expected) 23 | 24 | Expected string to end with: 25 | "hello world" 26 | Received: 27 | "hello"" 28 | `; 29 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toEqualCaseInsensitive.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toEqualCaseInsensitive fails if strings do not match 1`] = ` 4 | "expect(received).not.toEqualCaseInsensitive(expected) 5 | 6 | Expected values to not be equal while ignoring case (using ===): 7 | "aaaa" 8 | Received: 9 | "aaaa"" 10 | `; 11 | 12 | exports[`.toEqualCaseInsensitive passes if strings are equal despite case 1`] = ` 13 | "expect(received).toEqualCaseInsensitive(expected) 14 | 15 | Expected values to be equal while ignoring case (using ===): 16 | "bbbb" 17 | Received: 18 | "aaaa"" 19 | `; 20 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toHaveBeenCalledOnce.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toHaveBeenCalledOnce fails if mock was invoked exactly once 1`] = ` 4 | "expect(received).not.toHaveBeenCalledOnce(expected) 5 | 6 | Expected mock function to have been called any amount of times but one, but it was called exactly once." 7 | `; 8 | 9 | exports[`.toHaveBeenCalledOnce fails if mock was invoked more than once, indicating how many times it was invoked 1`] = ` 10 | "expect(received).toHaveBeenCalledOnce(expected) 11 | 12 | Expected mock function to have been called exactly once, but it was called: 13 | 17 times" 14 | `; 15 | 16 | exports[`.toHaveBeenCalledOnce fails if mock was never invoked indicating that it was invoked 0 times 1`] = ` 17 | "expect(received).toHaveBeenCalledOnce(expected) 18 | 19 | Expected mock function to have been called exactly once, but it was called: 20 | 0 times" 21 | `; 22 | 23 | exports[`.toHaveBeenCalledOnce fails when given value is not a jest spy or mock 1`] = ` 24 | "expect(received).toHaveBeenCalledOnce(expected) 25 | 26 | Matcher error: "received" must be a mock or spy function 27 | 28 | Received has type: function 29 | Received has value: [Function mock1]" 30 | `; 31 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toInclude.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.toInclude .not.toInclude fails when a string does have a given substring 1`] = ` 4 | "expect(received).not.toInclude(expected) 5 | 6 | Expected string to not include: 7 | "ell" 8 | Received: 9 | "hello world"" 10 | `; 11 | 12 | exports[`.toInclude fails when a string does not have a given substring 1`] = ` 13 | "expect(received).toInclude(expected) 14 | 15 | Expected string to include: 16 | "bob" 17 | Received: 18 | "hello world"" 19 | `; 20 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toIncludeMultiple.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toIncludeMultiple fails when string includes all substrings 1`] = ` 4 | "expect(received).not.toIncludeMultiple(expected) 5 | 6 | Expected string to not contain all substrings: 7 | ["hello", "world"] 8 | Received: 9 | "hello world"" 10 | `; 11 | 12 | exports[`.toIncludeMultiple fails when string does not include all substrings 1`] = ` 13 | "expect(received).toIncludeMultiple(expected) 14 | 15 | Expected string to contain all substrings: 16 | ["hello", "world", "bob"] 17 | Received: 18 | "hello world"" 19 | `; 20 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toIncludeRepeated.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toIncludeRepeated fails when given string includes given substring 1 time 1`] = ` 4 | "expect(received).not.toIncludeRepeated(expected) 5 | 6 | Expected string to not include repeated 1 times: 7 | "ell" 8 | Received: 9 | "hello world"" 10 | `; 11 | 12 | exports[`.not.toIncludeRepeated fails when given string includes given substring to the given occurrences 1`] = ` 13 | "expect(received).not.toIncludeRepeated(expected) 14 | 15 | Expected string to not include repeated 3 times: 16 | "l" 17 | Received: 18 | "hello world"" 19 | `; 20 | 21 | exports[`.toIncludeRepeated fails when given string does not have a given substring the correct number of times 1`] = ` 22 | "expect(received).toIncludeRepeated(expected) 23 | 24 | Expected string to include repeated 2 times: 25 | "world" 26 | Received: 27 | "hello world"" 28 | `; 29 | 30 | exports[`.toIncludeRepeated fails when given string does not include given substring 1`] = ` 31 | "expect(received).toIncludeRepeated(expected) 32 | 33 | Expected string to include repeated 1 times: 34 | "bob" 35 | Received: 36 | "hello world"" 37 | `; 38 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toPartiallyContain.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.toPartiallyContain .not.toPartiallyContain fails when an array contains all of the properties of a given object 1`] = ` 4 | "expect(received).not.toPartiallyContain(expected) 5 | 6 | Expected array not to partially contain: 7 | {"baz": "qux", "foo": "bar"} 8 | Received: 9 | [{"bax": "zax", "baz": "qux", "foo": "bar"}]" 10 | `; 11 | 12 | exports[`.toPartiallyContain fails when an array does not contain any of the properties of a given object 1`] = ` 13 | "expect(received).toPartiallyContain(expected) 14 | 15 | Expected array to partially contain: 16 | {"baz": "qux", "foo": "bar"} 17 | Received: 18 | [{"a": 1, "b": 2}]" 19 | `; 20 | 21 | exports[`.toPartiallyContain with custom equality tester fails when custom equality does not match any of the values 1`] = ` 22 | "expect(received).toPartiallyContain(expected) 23 | 24 | Expected array to partially contain: 25 | {"baz": "qux", "foo": "bar"} 26 | Received: 27 | [{"baz": "qux", "foo": "bar"}]" 28 | `; 29 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toReject.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toReject fails when passed a promise that rejects 1`] = ` 4 | "expect(received).not.toReject() 5 | 6 | Expected promise to resolve, however it rejected. 7 | " 8 | `; 9 | 10 | exports[`.toReject fails when passed a promise that resolved 1`] = ` 11 | "expect(received).toReject() 12 | 13 | Expected promise to reject, however it resolved. 14 | " 15 | `; 16 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toResolve.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toResolve fails when passed a promise that resolved 1`] = ` 4 | "expect(received).not.toResolve() 5 | 6 | Expected promise to reject, however it resolved. 7 | " 8 | `; 9 | 10 | exports[`.toResolve fails when passed a promise that rejects 1`] = ` 11 | "expect(received).toResolve() 12 | 13 | Expected promise to resolve, however it rejected. 14 | " 15 | `; 16 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toSatisfy.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toSatisfy fails when given a function that returns true 1`] = ` 4 | "expect(received).not.toSatisfy() 5 | 6 | Expected value to not satisfy: 7 | [Function isTrue] 8 | Received: 9 | true" 10 | `; 11 | 12 | exports[`.toSatisfy fails when given function that returns false 1`] = ` 13 | "expect(received).toSatisfy() 14 | 15 | Expected value to satisfy: 16 | [Function is2] 17 | Received: 18 | 3" 19 | `; 20 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toSatisfyAll.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toSatisfyAll fails when all values satisfy predicate 1`] = ` 4 | "expect(received).not.toSatisfyAll(expected) 5 | 6 | Expected array to not satisfy predicate for all values: 7 | [Function isOdd] 8 | Received: 9 | [1, 3, 5, 7]" 10 | `; 11 | 12 | exports[`.toSatisfyAll fails when any value does not satisfy the predicate 1`] = ` 13 | "expect(received).toSatisfyAll(expected) 14 | 15 | Expected array to satisfy predicate for all values: 16 | [Function isOdd] 17 | Received: 18 | [1, 3, 4, 5]" 19 | `; 20 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toSatisfyAny.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toSatisfyAll fails when any value satisfies predicate 1`] = ` 4 | "expect(received).not.toSatisfyAny(expected) 5 | 6 | Expected array to not satisfy predicate for any value: 7 | [Function isOdd] 8 | Received: 9 | [2, 3, 6, 8]" 10 | `; 11 | 12 | exports[`.toSatisfyAny fails when no value satisfies the predicate 1`] = ` 13 | "expect(received).toSatisfyAny(expected) 14 | 15 | Expected array to satisfy predicate for any values: 16 | [Function isOdd] 17 | Received: 18 | [2, 4, 6, 8]" 19 | `; 20 | -------------------------------------------------------------------------------- /test/matchers/__snapshots__/toStartWith.test.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`.not.toStartWith fails when string starts with given prefix 1`] = ` 4 | "expect(received).not.toStartWith(expected) 5 | 6 | Expected string to not start with: 7 | "hello" 8 | Received: 9 | "hello world"" 10 | `; 11 | 12 | exports[`.toStartWith fails when string does not start with the given prefix 1`] = ` 13 | "expect(received).toStartWith(expected) 14 | 15 | Expected string to start with: 16 | "world" 17 | Received: 18 | "hello world"" 19 | `; 20 | 21 | exports[`.toStartWith fails when the string is shorter than the given prefix 1`] = ` 22 | "expect(received).toStartWith(expected) 23 | 24 | Expected string to start with: 25 | "hello world" 26 | Received: 27 | "hello"" 28 | `; 29 | -------------------------------------------------------------------------------- /test/matchers/fail.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/fail'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.fail', () => { 6 | test('fails without message', () => { 7 | // @ts-expect-error TODO: fix 8 | expect(() => expect().fail()).toThrowErrorMatchingSnapshot(); 9 | }); 10 | test('fails with message', () => { 11 | // @ts-expect-error TODO: fix 12 | expect(() => expect().fail("This shouldn't fail!")).toThrowErrorMatchingSnapshot(); 13 | }); 14 | }); 15 | 16 | describe('.not.fail', () => { 17 | test('does not fail without message', () => { 18 | // @ts-expect-error TODO: fix 19 | expect().not.fail(); 20 | }); 21 | test('does not fail with message', () => { 22 | // @ts-expect-error TODO: fix 23 | expect().not.fail('this should fail!'); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /test/matchers/pass.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/pass'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.pass', () => { 6 | test('passes without message', () => { 7 | // @ts-expect-error TODO: fix 8 | expect().pass(); 9 | }); 10 | test('passes with message', () => { 11 | // @ts-expect-error TODO: fix 12 | expect().pass('this should pass!'); 13 | }); 14 | }); 15 | 16 | describe('.not.pass', () => { 17 | test('does not pass, has no message', () => { 18 | // @ts-expect-error TODO: fix 19 | expect(() => expect().not.pass()).toThrowErrorMatchingSnapshot(); 20 | }); 21 | test('does not.pass, has no message', () => { 22 | // @ts-expect-error TODO: fix 23 | expect(() => expect().not.pass('This should not pass!')).toThrowErrorMatchingSnapshot(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /test/matchers/toBeAfter.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeAfter'; 2 | 3 | expect.extend(matcher); 4 | 5 | const EARLIER = new Date('2018-06-01T22:00:00.000Z'); 6 | const LATER = new Date('2018-06-02T22:00:00.000Z'); 7 | 8 | describe('.toBeAfter', () => { 9 | test('passes when given a later date', () => { 10 | expect(LATER).toBeAfter(EARLIER); 11 | }); 12 | 13 | test('fails when given an earlier date', () => { 14 | expect(() => { 15 | expect(EARLIER).toBeAfter(LATER); 16 | }).toThrowErrorMatchingSnapshot(); 17 | }); 18 | 19 | test('fails when actual is not a Date', () => { 20 | expect(() => { 21 | expect('not-a-date').toBeAfter(EARLIER); 22 | }).toThrowErrorMatchingSnapshot(); 23 | }); 24 | }); 25 | 26 | describe('.not.toBeAfter', () => { 27 | test('passes when not given an earlier date', () => { 28 | expect(EARLIER).not.toBeAfter(LATER); 29 | }); 30 | 31 | test('fails when given a later date', () => { 32 | expect(() => { 33 | expect(LATER).not.toBeAfter(EARLIER); 34 | }).toThrowErrorMatchingSnapshot(); 35 | }); 36 | 37 | test('passes when actual is not a Date', () => { 38 | expect(() => { 39 | expect('not-a-date').not.toBeAfter(LATER); 40 | }); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /test/matchers/toBeAfterOrEqualTo.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeAfterOrEqualTo'; 2 | 3 | expect.extend(matcher); 4 | 5 | const EARLIER = new Date('2019-09-01T22:00:00.000Z'); 6 | const LATER = new Date('2019-09-10T22:00:00.000Z'); 7 | 8 | describe('.toBeAfterOrEqualTo', () => { 9 | test('passes when given a later date', () => { 10 | expect(LATER).toBeAfterOrEqualTo(EARLIER); 11 | }); 12 | 13 | test('passes when given an equal date', () => { 14 | expect(EARLIER).toBeAfterOrEqualTo(EARLIER); 15 | }); 16 | 17 | test('fails when given an earlier date', () => { 18 | expect(() => { 19 | expect(EARLIER).toBeAfterOrEqualTo(LATER); 20 | }).toThrowErrorMatchingSnapshot(); 21 | }); 22 | 23 | test('fails when actual is not a Date', () => { 24 | expect(() => { 25 | expect('not-a-date').toBeAfterOrEqualTo(EARLIER); 26 | }).toThrowErrorMatchingSnapshot(); 27 | }); 28 | }); 29 | 30 | describe('.not.toBeAfterOrEqualTo', () => { 31 | test('passes when given an earlier date', () => { 32 | expect(EARLIER).not.toBeAfterOrEqualTo(LATER); 33 | }); 34 | 35 | test('fails when given a later date', () => { 36 | expect(() => { 37 | expect(LATER).not.toBeAfterOrEqualTo(EARLIER); 38 | }).toThrowErrorMatchingSnapshot(); 39 | }); 40 | 41 | test('fails when given an equal date', () => { 42 | expect(() => { 43 | expect(EARLIER).not.toBeAfterOrEqualTo(EARLIER); 44 | }).toThrowErrorMatchingSnapshot(); 45 | }); 46 | 47 | test('passes when actual is not a Date', () => { 48 | expect(() => { 49 | expect('not-a-date').not.toBeAfterOrEqualTo(LATER); 50 | }); 51 | }); 52 | }); 53 | -------------------------------------------------------------------------------- /test/matchers/toBeArray.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeArray'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeArray', () => { 6 | test('passes when given an array', () => { 7 | expect([]).toBeArray(); 8 | }); 9 | 10 | test('fails when not given an array', () => { 11 | expect(() => expect(false).toBeArray()).toThrowErrorMatchingSnapshot(); 12 | }); 13 | }); 14 | 15 | describe('.not.toBeArray', () => { 16 | test.each([[false], [true], [0], [{}], [() => {}], [undefined], [null], [NaN]])( 17 | 'passes when not given an array: %s', 18 | given => { 19 | expect(given).not.toBeArray(); 20 | }, 21 | ); 22 | 23 | test('fails when given an array', () => { 24 | expect(() => expect([]).not.toBeArray()).toThrowErrorMatchingSnapshot(); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /test/matchers/toBeBefore.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeBefore'; 2 | 3 | expect.extend(matcher); 4 | 5 | const EARLIER = new Date('2018-06-01T22:00:00.000Z'); 6 | const LATER = new Date('2018-06-02T22:00:00.000Z'); 7 | 8 | describe('.toBeBefore', () => { 9 | test('passes when given an earlier date', () => { 10 | expect(EARLIER).toBeBefore(LATER); 11 | }); 12 | 13 | test('fails when given a later date', () => { 14 | expect(() => { 15 | expect(LATER).toBeBefore(EARLIER); 16 | }).toThrowErrorMatchingSnapshot(); 17 | }); 18 | 19 | test('fails when actual is not a Date', () => { 20 | expect(() => { 21 | expect('not-a-date').toBeBefore(LATER); 22 | }).toThrowErrorMatchingSnapshot(); 23 | }); 24 | }); 25 | 26 | describe('.not.toBeBefore', () => { 27 | test('passes when given an earlier date', () => { 28 | expect(LATER).not.toBeBefore(EARLIER); 29 | }); 30 | 31 | test('fails when given an earlier date', () => { 32 | expect(() => { 33 | expect(EARLIER).not.toBeBefore(LATER); 34 | }).toThrowErrorMatchingSnapshot(); 35 | }); 36 | 37 | test('passes when actual is not a Date', () => { 38 | expect(() => { 39 | expect('not-a-date').not.toBeBefore(EARLIER); 40 | }); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /test/matchers/toBeBeforeOrEqualTo.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeBeforeOrEqualTo'; 2 | 3 | expect.extend(matcher); 4 | 5 | const EARLIER = new Date('2019-09-01T22:00:00.000Z'); 6 | const LATER = new Date('2019-09-10T22:00:00.000Z'); 7 | 8 | describe('.toBeBeforeOrEqualTo', () => { 9 | test('passes when given an earlier date', () => { 10 | expect(EARLIER).toBeBeforeOrEqualTo(LATER); 11 | }); 12 | 13 | test('passes when given an equal date', () => { 14 | expect(EARLIER).toBeBeforeOrEqualTo(EARLIER); 15 | }); 16 | 17 | test('fails when given a later date', () => { 18 | expect(() => { 19 | expect(LATER).toBeBeforeOrEqualTo(EARLIER); 20 | }).toThrowErrorMatchingSnapshot(); 21 | }); 22 | 23 | test('fails when actual is not a Date', () => { 24 | expect(() => { 25 | expect('not-a-date').toBeBeforeOrEqualTo(LATER); 26 | }).toThrowErrorMatchingSnapshot(); 27 | }); 28 | }); 29 | 30 | describe('.not.toBeBeforeOrEqualTo', () => { 31 | test('passes when given an earlier date', () => { 32 | expect(LATER).not.toBeBeforeOrEqualTo(EARLIER); 33 | }); 34 | 35 | test('fails when given an earlier date', () => { 36 | expect(() => { 37 | expect(EARLIER).not.toBeBeforeOrEqualTo(LATER); 38 | }).toThrowErrorMatchingSnapshot(); 39 | }); 40 | 41 | test('fails when given an equal date', () => { 42 | expect(() => { 43 | expect(EARLIER).not.toBeBeforeOrEqualTo(EARLIER); 44 | }).toThrowErrorMatchingSnapshot(); 45 | }); 46 | 47 | test('passes when actual is not a Date', () => { 48 | expect(() => { 49 | expect('not-a-date').not.toBeBeforeOrEqualTo(EARLIER); 50 | }); 51 | }); 52 | }); 53 | -------------------------------------------------------------------------------- /test/matchers/toBeBetween.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeBetween'; 2 | 3 | expect.extend(matcher); 4 | 5 | const TESTDATE1 = new Date('2019-09-01T22:00:00.000Z'); 6 | const TESTDATE2 = new Date('2019-09-10T22:00:00.000Z'); 7 | const TESTDATE3 = new Date('2019-09-03T22:00:00.000Z'); 8 | 9 | describe('.toBeBetween', () => { 10 | test('passes when date is in given range', () => { 11 | expect(TESTDATE3).toBeBetween(TESTDATE1, TESTDATE2); 12 | }); 13 | 14 | test('fails when date is not in given range', () => { 15 | expect(() => { 16 | expect(TESTDATE1).toBeBetween(TESTDATE3, TESTDATE2); 17 | }).toThrowErrorMatchingSnapshot(); 18 | }); 19 | 20 | test('fails when actual is not a Date', () => { 21 | expect(() => { 22 | expect('not-a-date').toBeBetween(TESTDATE1, TESTDATE2); 23 | }).toThrowErrorMatchingSnapshot(); 24 | }); 25 | }); 26 | 27 | describe('.not.toBeBefore', () => { 28 | test('passes when date is not in given range', () => { 29 | expect(TESTDATE1).not.toBeBetween(TESTDATE3, TESTDATE2); 30 | }); 31 | 32 | test('fails when date is in given range', () => { 33 | expect(() => { 34 | expect(TESTDATE3).not.toBeBetween(TESTDATE1, TESTDATE2); 35 | }).toThrowErrorMatchingSnapshot(); 36 | }); 37 | 38 | test('passes when actual is not a Date', () => { 39 | expect(() => { 40 | expect('not-a-date').not.toBeBetween(TESTDATE3, TESTDATE2); 41 | }); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /test/matchers/toBeBoolean.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeBoolean'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeBoolean', () => { 6 | test('passes when given false', () => { 7 | expect(false).toBeBoolean(); 8 | }); 9 | 10 | test('passes when given true', () => { 11 | expect(true).toBeBoolean(); 12 | }); 13 | 14 | test('passes when given something that evaluates to a boolean', () => { 15 | expect(1 === 1).toBeBoolean(); 16 | }); 17 | 18 | test('passes when given an object of type Boolean', () => { 19 | expect(new Boolean()).toBeBoolean(); 20 | }); 21 | 22 | test('fails when not given a boolean', () => { 23 | expect(() => expect(1).toBeBoolean()).toThrowErrorMatchingSnapshot(); 24 | }); 25 | }); 26 | 27 | describe('.not.toBeBoolean', () => { 28 | test.each([['true'], [0], [{}], [[]], [() => {}], [undefined], [null], [NaN]])( 29 | 'passes when item is not of type boolean: %s', 30 | given => { 31 | expect(given).not.toBeBoolean(); 32 | }, 33 | ); 34 | 35 | test('fails when given a boolean', () => { 36 | expect(() => expect(true).not.toBeBoolean()).toThrowErrorMatchingSnapshot(); 37 | }); 38 | 39 | test('fails when given an object of type boolean', () => { 40 | expect(() => expect(new Boolean()).not.toBeBoolean()).toThrowErrorMatchingSnapshot(); 41 | }); 42 | }); 43 | -------------------------------------------------------------------------------- /test/matchers/toBeDate.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeDate'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeDate', () => { 6 | test('passes when given a date', () => { 7 | expect(new Date()).toBeDate(); 8 | }); 9 | 10 | test('fails when not given a date', () => { 11 | expect(() => expect(false).toBeDate()).toThrowErrorMatchingSnapshot(); 12 | }); 13 | }); 14 | 15 | describe('.not.toBeDate', () => { 16 | test.each([[false], [true], [0], [''], [{}], [() => {}], [undefined], [null], [NaN]])( 17 | 'passes when not given a date: %s', 18 | given => { 19 | expect(given).not.toBeDate(); 20 | }, 21 | ); 22 | 23 | test('fails when given a date', () => { 24 | expect(() => expect(new Date('2018-01-01T13:00:00.000Z')).not.toBeDate()).toThrowErrorMatchingSnapshot(); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /test/matchers/toBeDateString.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeDateString'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeDateString', () => { 6 | test('passes when given a date string', () => { 7 | expect(new Date().toISOString()).toBeDateString(); 8 | }); 9 | 10 | test('fails when not given a date string', () => { 11 | expect(() => expect('not a date').toBeDateString()).toThrowErrorMatchingSnapshot(); 12 | }); 13 | }); 14 | 15 | describe('.not.toBeDateString', () => { 16 | test('passes when not given a date string', () => { 17 | expect('not a date').not.toBeDateString(); 18 | }); 19 | 20 | test('fails when given a date string', () => { 21 | expect(() => expect('2018-01-01T13:00:00.000Z').not.toBeDateString()).toThrowErrorMatchingSnapshot(); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/matchers/toBeEmptyObject.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeEmptyObject'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeEmptyObject', () => { 6 | test('passes when given an empty object', () => { 7 | expect({}).toBeEmptyObject(); 8 | }); 9 | 10 | test('fails when not given an empty object', () => { 11 | expect(() => expect({ property1: 'something' }).toBeEmptyObject()).toThrowErrorMatchingSnapshot(); 12 | }); 13 | 14 | test('fails when not given an object', () => { 15 | expect(() => expect(null).toBeEmptyObject()).toThrowErrorMatchingSnapshot(); 16 | expect(() => expect([42]).toBeEmptyObject()).toThrowErrorMatchingSnapshot(); 17 | expect(() => expect(42).toBeEmptyObject()).toThrowErrorMatchingSnapshot(); 18 | }); 19 | }); 20 | 21 | describe('.not.toBeEmptyObject', () => { 22 | test('passes when not given an empty object', () => { 23 | expect({ property1: 'something' }).not.toBeEmptyObject(); 24 | }); 25 | 26 | test('fails when given an empty object', () => { 27 | expect(() => expect({}).not.toBeEmptyObject()).toThrowErrorMatchingSnapshot(); 28 | }); 29 | 30 | test('passes when not given an object', () => { 31 | expect(() => expect(null).not.toBeEmptyObject()); 32 | expect(() => expect([42]).not.toBeEmptyObject()); 33 | expect(() => expect(42).not.toBeEmptyObject()); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /test/matchers/toBeEven.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeEven'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeEven', () => { 6 | test('passes when given even number', () => { 7 | expect(2).toBeEven(); 8 | }); 9 | 10 | test.each([[false], [true], [''], [1], [{}], [() => {}], [undefined], [null], [NaN]])( 11 | 'fails when not given an even number', 12 | given => { 13 | expect(() => expect(given).toBeEven()).toThrowErrorMatchingSnapshot(); 14 | }, 15 | ); 16 | }); 17 | 18 | describe('.not.toBeEven', () => { 19 | test('fails when given an even number', () => { 20 | expect(() => expect(2).not.toBeEven()).toThrowErrorMatchingSnapshot(); 21 | }); 22 | 23 | test.each([[false], [true], [''], [1], [[]], [{}], [() => {}], [undefined], [null], [NaN]])( 24 | 'passes when not given an even number: %s', 25 | given => { 26 | expect(given).not.toBeEven(); 27 | }, 28 | ); 29 | }); 30 | -------------------------------------------------------------------------------- /test/matchers/toBeExtensible.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeExtensible'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeExtensible', () => { 6 | test.each([{}, [], () => {}])('passes when given an extensible object: %s', given => { 7 | expect(given).toBeExtensible(); 8 | }); 9 | 10 | test.each([[false], [''], [0], [undefined], [null], [NaN], [Object.seal({})], [Object.freeze({})]])( 11 | 'fails when not given an extensible object: %s', 12 | given => { 13 | expect(() => expect(given).toBeExtensible()).toThrowErrorMatchingSnapshot(); 14 | }, 15 | ); 16 | }); 17 | 18 | describe('.not.toBeExtensible', () => { 19 | test.each([[false], [''], [0], [undefined], [null], [NaN], [Object.seal({})], [Object.freeze({})]])( 20 | 'passes when not given extensible object: %s', 21 | given => { 22 | expect(given).not.toBeExtensible(); 23 | }, 24 | ); 25 | 26 | test.each([[{}], [[]], [() => {}]])('fails when given an extensible object: %s', given => { 27 | expect(() => expect(given).not.toBeExtensible()).toThrowErrorMatchingSnapshot(); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /test/matchers/toBeFalse.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeFalse'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeFalse', () => { 6 | test('passes when given false', () => { 7 | expect(false).toBeFalse(); 8 | }); 9 | 10 | test('fails when not given false', () => { 11 | expect(() => expect(true).toBeFalse()).toThrowErrorMatchingSnapshot(); 12 | }); 13 | }); 14 | 15 | describe('.not.toBeFalse', () => { 16 | test.each([[true], [''], [0], [{}], [[]], [() => {}], [undefined], [null], [NaN]])( 17 | 'passes when not given false: %s', 18 | given => { 19 | expect(given).not.toBeFalse(); 20 | }, 21 | ); 22 | 23 | test('fails when given false', () => { 24 | expect(() => expect(false).not.toBeFalse()).toThrowErrorMatchingSnapshot(); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /test/matchers/toBeFinite.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeFinite'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeFinite', () => { 6 | test('passes when given a positive finite number', () => { 7 | expect(1).toBeFinite(); 8 | }); 9 | 10 | test('passes when given a negative finite number', () => { 11 | expect(-1).toBeFinite(); 12 | }); 13 | 14 | test('passes when given the largest finite number', () => { 15 | expect(Number.MAX_SAFE_INTEGER).toBeFinite(); 16 | }); 17 | 18 | test('passes when given the largetst negative finite number', () => { 19 | expect(Number.MIN_SAFE_INTEGER).toBeFinite(); 20 | }); 21 | 22 | test('passes when given 0', () => { 23 | expect(0).toBeFinite(); 24 | }); 25 | 26 | test('fails when not given NaN', () => { 27 | expect(() => expect(NaN).toBeFinite()).toThrowErrorMatchingSnapshot(); 28 | }); 29 | 30 | test('fails when not given Infinity', () => { 31 | expect(() => expect(Infinity).toBeFinite()).toThrowErrorMatchingSnapshot(); 32 | }); 33 | }); 34 | 35 | describe('.not.toBeFinite', () => { 36 | test('fails when given a finite number', () => { 37 | expect(() => expect(1).not.toBeFinite()).toThrowErrorMatchingSnapshot(); 38 | }); 39 | 40 | test('passes when given NaN', () => { 41 | expect(NaN).not.toBeFinite(); 42 | }); 43 | 44 | test('passes when given Infinity', () => { 45 | expect(Infinity).not.toBeFinite(); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /test/matchers/toBeFrozen.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeFrozen'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeFrozen', () => { 6 | test('passes when given frozen object', () => { 7 | expect(Object.freeze({})).toBeFrozen(); 8 | }); 9 | 10 | test('fails when given a non-frozen object', () => { 11 | expect(() => expect({}).toBeFrozen()).toThrowErrorMatchingSnapshot(); 12 | }); 13 | }); 14 | 15 | describe('.not.toBeFrozen', () => { 16 | test('fails when given frozen object', () => { 17 | expect(() => expect(Object.freeze({})).not.toBeFrozen()).toThrowErrorMatchingSnapshot(); 18 | }); 19 | 20 | test('passes when given a non-frozen object', () => { 21 | expect({}).not.toBeFrozen(); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/matchers/toBeFunction.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeFunction'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeFunction', () => { 6 | test('passes when given a function', () => { 7 | expect(() => {}).toBeFunction(); 8 | }); 9 | 10 | test('fails when not given a function', () => { 11 | expect(() => expect(false).toBeFunction()).toThrowErrorMatchingSnapshot(); 12 | }); 13 | }); 14 | 15 | describe('.not.toBeFunction', () => { 16 | test.each([[false], [''], [0], [{}], [[]], [undefined], [null], [NaN]])( 17 | 'passes when not given a function: %s', 18 | given => { 19 | expect(given).not.toBeFunction(); 20 | }, 21 | ); 22 | 23 | test('fails when given a function', () => { 24 | expect(() => expect(() => {}).not.toBeFunction()).toThrowErrorMatchingSnapshot(); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /test/matchers/toBeHexadecimal.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeHexadecimal'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeHexadecimal', () => { 6 | test('passes when given valid 6 digit hexadecimal', () => { 7 | expect('#ECECEC').toBeHexadecimal(); 8 | }); 9 | 10 | test('passes when given valid 3 digit hexadecimal', () => { 11 | expect('#000').toBeHexadecimal(); 12 | }); 13 | 14 | test('fails when given non-string', () => { 15 | expect(() => expect(true).toBeHexadecimal()).toThrowErrorMatchingSnapshot(); 16 | }); 17 | }); 18 | 19 | describe('.not.toBeHexadecimal', () => { 20 | test('passes when given positive number', () => { 21 | expect(1).not.toBeHexadecimal(); 22 | }); 23 | 24 | test('fails when given valid hexadecimal', () => { 25 | expect(() => expect('#eeffee').not.toBeHexadecimal()).toThrowErrorMatchingSnapshot(); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/matchers/toBeInRange.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeInRange'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeInRange', () => { 6 | test('passes when given array is in range', () => { 7 | expect([4, 5, 7, 9]).toBeInRange(4, 10); 8 | }); 9 | 10 | test('fails when given array is not in a given range', () => { 11 | expect(() => expect([4, 5, 7, 9]).toBeInRange(4, 8)).toThrowErrorMatchingSnapshot(); 12 | }); 13 | }); 14 | 15 | describe('.not.toBeInRange', () => { 16 | test('passes when given array is not in the given range', () => { 17 | expect([12, 13, 15, 17]).not.toBeInRange(4, 9); 18 | }); 19 | 20 | test('fails when given array is in the given range', () => { 21 | expect(() => expect([4, 5, 7, 9]).not.toBeInRange(4, 10)).toThrowErrorMatchingSnapshot(); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/matchers/toBeInteger.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeInteger'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeInteger', () => { 6 | test('passes when given integer', () => { 7 | expect(1).toBeInteger(); 8 | }); 9 | 10 | test('fails when given fraction', () => { 11 | expect(() => expect(1.5).toBeInteger()).toThrowErrorMatchingSnapshot(); 12 | }); 13 | }); 14 | 15 | describe('.not.toBeInteger', () => { 16 | test('passes when given fraction', () => { 17 | expect(1.5).not.toBeInteger(); 18 | }); 19 | 20 | test('fails when given integer', () => { 21 | expect(() => expect(1).not.toBeInteger()).toThrowErrorMatchingSnapshot(); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/matchers/toBeNaN.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeNaN'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeNaN', () => { 6 | test('passes when given a non-number', () => { 7 | expect({}).toBeNaN(); 8 | }); 9 | 10 | test('fails when given a number', () => { 11 | expect(() => expect(3).toBeNaN()).toThrowErrorMatchingSnapshot(); 12 | }); 13 | }); 14 | 15 | describe('.not.toBeNaN', () => { 16 | test.each([[0], [1], [300], [10.5], [-50]])('passes when given a number: %s', given => { 17 | expect(given).not.toBeNaN(); 18 | }); 19 | 20 | test('fails when given a non-number', () => { 21 | expect(() => expect(undefined).not.toBeNaN()).toThrowErrorMatchingSnapshot(); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/matchers/toBeNegative.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeNegative'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeNegative', () => { 6 | test('passes when given negative number', () => { 7 | expect(-1).toBeNegative(); 8 | }); 9 | 10 | test('fails when given positive number', () => { 11 | expect(() => expect(1).toBeNegative()).toThrowErrorMatchingSnapshot(); 12 | }); 13 | 14 | test('fails when given Infinity', () => { 15 | expect(() => expect(Infinity).toBeNegative()).toThrowErrorMatchingSnapshot(); 16 | }); 17 | }); 18 | 19 | describe('.not.toBeNegative', () => { 20 | test('passes when given positive number', () => { 21 | expect(1).not.toBeNegative(); 22 | }); 23 | 24 | test('passes when given Infinity', () => { 25 | expect(Infinity).not.toBeNegative(); 26 | }); 27 | 28 | test('passes when given NaN', () => { 29 | expect(NaN).not.toBeNegative(); 30 | }); 31 | 32 | test('fails when given negative number', () => { 33 | expect(() => expect(-1).not.toBeNegative()).toThrowErrorMatchingSnapshot(); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /test/matchers/toBeNil.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeNil'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeNil', () => { 6 | test('passes when null is given', () => { 7 | expect(null).toBeNil(); 8 | }); 9 | 10 | test('passes when undefined is given', () => { 11 | expect(undefined).toBeNil(); 12 | }); 13 | test('fails when the value is not null or undefined', () => { 14 | expect(() => expect('value').toBeNil()).toThrowErrorMatchingSnapshot(); 15 | }); 16 | }); 17 | 18 | describe('.not.toBeNil', () => { 19 | test.each([['true'], [{}], [true]])('passes when value is not null or undefined : %s', given => { 20 | expect(given).not.toBeNil(); 21 | }); 22 | 23 | test('fails when null is given', () => { 24 | expect(() => expect(null).not.toBeNil()).toThrowErrorMatchingSnapshot(); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /test/matchers/toBeNumber.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeNumber'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeNumber', () => { 6 | test.each` 7 | number 8 | ${10} 9 | ${NaN} 10 | ${Infinity} 11 | ${-Infinity} 12 | `('passes when given: $number', ({ number }) => { 13 | expect(number).toBeNumber(); 14 | }); 15 | 16 | test('fails when not given a number', () => { 17 | expect(() => expect(false).toBeNumber()).toThrowErrorMatchingSnapshot(); 18 | }); 19 | }); 20 | 21 | describe('.not.toBeNumber', () => { 22 | test.each([[false], [true], [[]], [{}], [() => {}], [undefined], [null], ['10']])( 23 | 'passes when not given a number: %s', 24 | given => { 25 | expect(given).not.toBeNumber(); 26 | }, 27 | ); 28 | 29 | test('fails when given a number', () => { 30 | expect(() => expect(1).not.toBeNumber()).toThrowErrorMatchingSnapshot(); 31 | }); 32 | }); 33 | -------------------------------------------------------------------------------- /test/matchers/toBeObject.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeObject'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeObject', () => { 6 | test('passes when given an object', () => { 7 | expect({}).toBeObject(); 8 | }); 9 | 10 | test.each([[false], [''], [0], [() => {}], [undefined], [NaN], [[1, 2, 3]]])( 11 | 'fails when not given an object: %s', 12 | given => { 13 | expect(() => expect(given).toBeObject()).toThrowErrorMatchingSnapshot(); 14 | }, 15 | ); 16 | }); 17 | 18 | describe('.not.toBeObject', () => { 19 | test.each([[false], [''], [0], [() => {}], [undefined], [NaN], [[1, 2, 3]]])( 20 | 'passes when not given an object: %s', 21 | given => { 22 | expect(given).not.toBeObject(); 23 | }, 24 | ); 25 | 26 | test('fails when given an object', () => { 27 | expect(() => expect({}).not.toBeObject()).toThrowErrorMatchingSnapshot(); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /test/matchers/toBeOdd.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeOdd'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeOdd', () => { 6 | test('passes when given an odd number', () => { 7 | expect(1).toBeOdd(); 8 | }); 9 | 10 | test.each([[false], [true], [''], [2], [{}], [() => {}], [undefined], [null], [NaN]])( 11 | 'fails when given not given an odd number', 12 | given => { 13 | expect(() => expect(given).toBeOdd()).toThrowErrorMatchingSnapshot(); 14 | }, 15 | ); 16 | }); 17 | 18 | describe('.not.toBeOdd', () => { 19 | test.each([[false], [true], [''], [2], [[]], [{}], [() => {}], [undefined], [null], [NaN]])( 20 | 'passes when not given an odd number: %s', 21 | given => { 22 | expect(given).not.toBeOdd(); 23 | }, 24 | ); 25 | 26 | test('fails when given an odd number', () => { 27 | expect(() => expect(1).not.toBeOdd()).toThrowErrorMatchingSnapshot(); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /test/matchers/toBeOneOf.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeOneOf'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeOneOf', () => { 6 | test('passes when value is in given array', () => { 7 | expect(1).toBeOneOf([1, 2, 3]); 8 | }); 9 | 10 | test('fails when value is not in given array', () => { 11 | expect(() => expect(4).toBeOneOf([1, 2, 3])).toThrowErrorMatchingSnapshot(); 12 | }); 13 | }); 14 | 15 | describe('.not.toBeOneOf', () => { 16 | test('passes when value is not in given array', () => { 17 | expect(4).not.toBeOneOf([1, 2, 3]); 18 | }); 19 | 20 | test('fails when value is in given array', () => { 21 | expect(() => expect(1).not.toBeOneOf([1, 2, 3])).toThrowErrorMatchingSnapshot(); 22 | }); 23 | }); 24 | 25 | // Note - custom equality tester must be at the end of the file because once we add it, it cannot be removed 26 | (expect.addEqualityTesters ? describe : describe.skip)('toBeOneOf with custom equality tester', () => { 27 | let mockEqualityTester: jest.Mock; 28 | beforeAll(() => { 29 | mockEqualityTester = jest.fn(); 30 | expect.addEqualityTesters([mockEqualityTester]); 31 | }); 32 | afterEach(() => { 33 | mockEqualityTester.mockReset(); 34 | }); 35 | test('passes when custom equality matches one of array elements', () => { 36 | mockEqualityTester.mockImplementation(a => a === 3); 37 | expect('a').toBeOneOf([1, 2, 3]); 38 | }); 39 | test('fails when custom equality does not match any array element', () => { 40 | mockEqualityTester.mockReturnValue(false); 41 | expect(() => expect(1).toBeOneOf([1, 2, 3])).toThrowErrorMatchingSnapshot(); 42 | }); 43 | }); 44 | -------------------------------------------------------------------------------- /test/matchers/toBePositive.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBePositive'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBePositive', () => { 6 | test('passes when given a positive number', () => { 7 | expect(1).toBePositive(); 8 | }); 9 | 10 | test('fails when not given a positive number', () => { 11 | expect(() => expect(-1).toBePositive()).toThrowErrorMatchingSnapshot(); 12 | }); 13 | }); 14 | 15 | describe('.not.toBePositive', () => { 16 | test.each([[false], [''], [-1], [0], [{}], [[]], [() => {}], [undefined], [null], [NaN], [Infinity]])( 17 | 'passes when not given a positive number: %s', 18 | given => { 19 | expect(given).not.toBePositive(); 20 | }, 21 | ); 22 | 23 | test('fails when given a positive number', () => { 24 | expect(() => expect(5).not.toBePositive()).toThrowErrorMatchingSnapshot(); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /test/matchers/toBeSealed.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeSealed'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeSealed', () => { 6 | test('passes when given sealed object', () => { 7 | expect(Object.seal({})).toBeSealed(); 8 | }); 9 | 10 | test('fails when given a non-sealed object', () => { 11 | expect(() => expect({}).toBeSealed()).toThrowErrorMatchingSnapshot(); 12 | }); 13 | }); 14 | 15 | describe('.not.toBeSealed', () => { 16 | test('fails when given sealed object', () => { 17 | expect(() => expect(Object.seal({})).not.toBeSealed()).toThrowErrorMatchingSnapshot(); 18 | }); 19 | 20 | test('passes when given a non-sealed object', () => { 21 | expect({}).not.toBeSealed(); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/matchers/toBeString.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeString'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeString', () => { 6 | test('passes when given a string literal', () => { 7 | expect('string type').toBeString(); 8 | }); 9 | 10 | test('passes when given an object of type string', () => { 11 | expect(new String('string type')).toBeString(); 12 | }); 13 | 14 | test('fails when not given a string', () => { 15 | expect(() => expect(5).toBeString()).toThrowErrorMatchingSnapshot(); 16 | }); 17 | }); 18 | 19 | describe('.not.toBeString', () => { 20 | test.each([[false], [0], [{}], [[]], [() => {}], [undefined], [null], [NaN]])( 21 | 'passes when not item is not of type string: %s', 22 | given => { 23 | expect(given).not.toBeString(); 24 | }, 25 | ); 26 | 27 | test('fails when given a string literal', () => { 28 | expect(() => expect('').not.toBeString()).toThrowErrorMatchingSnapshot(); 29 | }); 30 | 31 | test('fails when given an object of type string', () => { 32 | expect(() => expect(new String('string type')).not.toBeString()).toThrowErrorMatchingSnapshot(); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /test/matchers/toBeSymbol.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeSymbol'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeSymbol', () => { 6 | test('passes when given a symbol', () => { 7 | expect(Symbol()).toBeSymbol(); 8 | }); 9 | 10 | test('fails when not given a symbol', () => { 11 | expect(() => expect(false).toBeSymbol()).toThrowErrorMatchingSnapshot(); 12 | }); 13 | }); 14 | 15 | describe('.not.toBeSymbol', () => { 16 | test.each([[false], [''], [0], [{}], [[]], [undefined], [null], [NaN], [() => {}]])( 17 | 'passes when not given a symbol: %s', 18 | given => { 19 | expect(given).not.toBeSymbol(); 20 | }, 21 | ); 22 | 23 | test('fails when given a symbol', () => { 24 | expect(() => expect(Symbol()).not.toBeSymbol()).toThrowErrorMatchingSnapshot(); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /test/matchers/toBeTrue.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeTrue'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeTrue', () => { 6 | test('passes when given true', () => { 7 | expect(true).toBeTrue(); 8 | }); 9 | 10 | test('fails when not given true', () => { 11 | expect(() => expect(false).toBeTrue()).toThrowErrorMatchingSnapshot(); 12 | }); 13 | }); 14 | 15 | describe('.not.toBeTrue', () => { 16 | test.each([[false], [''], [0], [{}], [[]], [() => {}], [undefined], [null], [NaN]])( 17 | 'passes when not given true: %s', 18 | given => { 19 | expect(given).not.toBeTrue(); 20 | }, 21 | ); 22 | 23 | test('fails when given true', () => { 24 | expect(() => expect(true).not.toBeTrue()).toThrowErrorMatchingSnapshot(); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /test/matchers/toBeValidDate.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeValidDate'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeValidDate', () => { 6 | test('passes when given a valid date', () => { 7 | expect(new Date()).toBeValidDate(); 8 | }); 9 | 10 | test('fails when given an invalid date', () => { 11 | expect(() => expect(new Date('2018-90-90T13:00:00.000Z')).toBeValidDate()).toThrowErrorMatchingSnapshot(); 12 | }); 13 | 14 | test('fails when not given non-date values', () => { 15 | expect(() => expect(1).toBeValidDate()).toThrowErrorMatchingSnapshot(); 16 | }); 17 | }); 18 | 19 | describe('.not.toBeValidDate', () => { 20 | test.each([ 21 | [new Date('01/90/2018')], 22 | [new Date('32/01/2018')], 23 | [false], 24 | [true], 25 | [0], 26 | [''], 27 | [{}], 28 | [() => {}], 29 | [undefined], 30 | [null], 31 | [NaN], 32 | ])('passes when not given a date: %s', given => { 33 | expect(given).not.toBeValidDate(); 34 | }); 35 | 36 | test('fails when given a valid date value', () => { 37 | expect(() => expect(new Date('2018-01-01T13:00:00.000Z')).not.toBeValidDate()).toThrowErrorMatchingSnapshot(); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /test/matchers/toBeWithin.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toBeWithin'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toBeWithin', () => { 6 | test('passes when given number is within the given bounds of start (inclusive) and end (exclusive)', () => { 7 | expect(1).toBeWithin(1, 3); 8 | }); 9 | 10 | test('passes when given bigint number is within the given bounds of start (inclusive) and end (exclusive)', () => { 11 | expect(BigInt(1)).toBeWithin(1, 3); 12 | }); 13 | 14 | test('fails when given number is not within the given bounds of start (inclusive) and end (exclusive)', () => { 15 | expect(() => expect(3).toBeWithin(1, 3)).toThrowErrorMatchingSnapshot(); 16 | }); 17 | }); 18 | 19 | describe('.not.toBeWithin', () => { 20 | test('passes when given number is not within the given bounds of start (inclusive) and end (exclusive)', () => { 21 | expect(3).not.toBeWithin(1, 3); 22 | }); 23 | 24 | test('fails when given number is within the given bounds of start (inclusive) and end (exclusive)', () => { 25 | expect(() => expect(1).not.toBeWithin(1, 3)).toThrowErrorMatchingSnapshot(); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/matchers/toChange.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toChange'; 2 | import { Counter } from '../fixtures/counter'; 3 | 4 | expect.extend(matcher); 5 | 6 | describe('.toChange', () => { 7 | test('passes when given a value that the mutator increments', () => { 8 | let value = 0; 9 | expect(() => value++).toChange(() => value); 10 | }); 11 | 12 | test('passes when mutating a counter', () => { 13 | const counter = new Counter(); 14 | expect(counter.increment).toChange(counter.count); 15 | }); 16 | 17 | test('fails when a given value does not increment', () => { 18 | const value = 0; 19 | expect(() => expect(() => value).toChange(() => value)).toThrowErrorMatchingSnapshot(); 20 | }); 21 | 22 | test('fails when not mutating a counter', () => { 23 | const counter = new Counter(); 24 | expect(() => expect(counter.count).toChange(counter.count)).toThrowErrorMatchingSnapshot(); 25 | }); 26 | }); 27 | 28 | describe('.not.toChange', () => { 29 | test('passes when given a mutator that does not increment the value', () => { 30 | const value = 0; 31 | expect(() => value).not.toChange(() => value); 32 | }); 33 | 34 | test('passes when not mutating a counter', () => { 35 | const counter = new Counter(); 36 | expect(counter.count).not.toChange(counter.count); 37 | }); 38 | 39 | test('fails when mutating a counter', () => { 40 | const counter = new Counter(); 41 | expect(() => expect(counter.increment).not.toChange(counter.count)).toThrowErrorMatchingSnapshot(); 42 | }); 43 | 44 | test('fails when a value expected not to change defies all expectations and changes', () => { 45 | let value = 0; 46 | expect(() => expect(() => value++).not.toChange(() => value)).toThrowErrorMatchingSnapshot(); 47 | }); 48 | }); 49 | -------------------------------------------------------------------------------- /test/matchers/toContainAnyKeys.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toContainAnyKeys'; 2 | 3 | expect.extend(matcher); 4 | 5 | const testObject = { 6 | name: 'Steve the Pirate', 7 | age: 37, 8 | }; 9 | 10 | describe('.toContainAnyKeys', () => { 11 | test('passes when object contains one or more keys', () => { 12 | expect(testObject).toContainAnyKeys(['name']); 13 | }); 14 | 15 | test('fails when object does not contain any keys', () => { 16 | expect(() => expect(testObject).toContainAnyKeys(['occupation'])).toThrowErrorMatchingSnapshot(); 17 | }); 18 | }); 19 | 20 | describe('.not.toContainAnyKeys', () => { 21 | test('passes when object does not contain any keys', () => { 22 | expect(testObject).not.toContainAnyKeys(['occupation']); 23 | }); 24 | 25 | test('fails when object contains one or more keys', () => { 26 | expect(() => expect(testObject).not.toContainAnyKeys(['name', 'age'])).toThrowErrorMatchingSnapshot(); 27 | }); 28 | }); 29 | -------------------------------------------------------------------------------- /test/matchers/toContainKey.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toContainKey'; 2 | 3 | expect.extend(matcher); 4 | 5 | const data = { hello: 'world' }; 6 | 7 | describe('.toContainKey', () => { 8 | test('passes when given object contains key', () => { 9 | expect(data).toContainKey('hello'); 10 | }); 11 | 12 | test('fails when given object does not contain key', () => { 13 | expect(() => expect(data).toContainKey('missing')).toThrowErrorMatchingSnapshot(); 14 | }); 15 | 16 | test('fails when actual is not an object', () => { 17 | expect(() => expect(null).toContainKey('hello')).toThrowErrorMatchingSnapshot(); 18 | expect(() => expect(42).toContainKey('hello')).toThrowErrorMatchingSnapshot(); 19 | }); 20 | }); 21 | 22 | describe('.not.toContainKey', () => { 23 | test('passes when given object does not contain key', () => { 24 | expect(data).not.toContainKey('missing'); 25 | }); 26 | 27 | test('fails when given object contains key', () => { 28 | expect(() => expect(data).not.toContainKey('hello')).toThrowErrorMatchingSnapshot(); 29 | }); 30 | 31 | test('passes when actual is not an object', () => { 32 | expect(() => expect(null).not.toContainKey('hello')); 33 | expect(() => expect(42).not.toContainKey('hello')); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /test/matchers/toContainKeys.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toContainKeys'; 2 | 3 | expect.extend(matcher); 4 | 5 | const data = { a: 'foo', b: 'bar', c: 'baz' }; 6 | 7 | describe('.toContainKeys', () => { 8 | test('passes when object contains all keys', () => { 9 | expect(data).toContainKeys(['b', 'c']); 10 | }); 11 | 12 | test('fails when object does not contain all keys', () => { 13 | expect(() => expect(data).toContainKeys(['a', 'd'])).toThrowErrorMatchingSnapshot(); 14 | }); 15 | }); 16 | 17 | describe('.not.toContainKeys', () => { 18 | test('passes when object does not contain all keys', () => { 19 | expect(data).not.toContainKeys(['d']); 20 | }); 21 | 22 | test('fails when object contains all keys', () => { 23 | expect(() => expect(data).not.toContainKeys(['a', 'b', 'c'])).toThrowErrorMatchingSnapshot(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /test/matchers/toEndWith.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toEndWith'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toEndWith', () => { 6 | test('passes when string ends with given suffix', () => { 7 | expect('hello world').toEndWith('world'); 8 | }); 9 | 10 | test('fails when the string is shorter than the given suffix', () => { 11 | expect(() => expect('hello').toEndWith('hello world')).toThrowErrorMatchingSnapshot(); 12 | }); 13 | 14 | test('fails when string does not end with the given suffix', () => { 15 | expect(() => expect('hello world').toEndWith('hello')).toThrowErrorMatchingSnapshot(); 16 | }); 17 | }); 18 | 19 | describe('.not.toEndWith', () => { 20 | test('passes when string does not end with the given suffix', () => { 21 | expect('hello world').not.toEndWith('hello'); 22 | }); 23 | 24 | test('passes when string is shorter than the given suffix', () => { 25 | expect('hello').not.toEndWith('hello world'); 26 | }); 27 | 28 | test('fails when string ends with given suffix', () => { 29 | expect(() => expect('hello world').not.toEndWith('world')).toThrowErrorMatchingSnapshot(); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /test/matchers/toEqualCaseInsensitive.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toEqualCaseInsensitive'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toEqualCaseInsensitive', () => { 6 | test('passes if strings are equal despite case', () => { 7 | expect('a').toEqualCaseInsensitive('A'); 8 | expect('aaAA').toEqualCaseInsensitive('aaaa'); 9 | expect('HELLO WORLD').toEqualCaseInsensitive('hello world'); 10 | expect('hello world').toEqualCaseInsensitive('HELLO WORLD'); 11 | expect(() => expect('aaaa').toEqualCaseInsensitive('bbbb')).toThrowErrorMatchingSnapshot(); 12 | }); 13 | }); 14 | 15 | describe('.not.toEqualCaseInsensitive', () => { 16 | test('fails if strings do not match', () => { 17 | expect('hello world').not.toEqualCaseInsensitive('hello'); 18 | expect(() => expect('aaaa').not.toEqualCaseInsensitive('aaaa')).toThrowErrorMatchingSnapshot(); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /test/matchers/toHaveBeenCalledOnce.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toHaveBeenCalledOnce'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toHaveBeenCalledOnce', () => { 6 | let mock: jest.Mock | (() => void); 7 | beforeEach(() => { 8 | mock = jest.fn(); 9 | }); 10 | 11 | test('passes if mock was invoked exactly once', () => { 12 | mock(); 13 | expect(mock).toHaveBeenCalledOnce(); 14 | }); 15 | 16 | test('fails if mock was never invoked indicating that it was invoked 0 times', () => { 17 | expect(() => expect(mock).toHaveBeenCalledOnce()).toThrowErrorMatchingSnapshot(); 18 | }); 19 | 20 | test('fails if mock was invoked more than once, indicating how many times it was invoked', () => { 21 | // Invoke mock 17 times 22 | new Array(17).fill(mock).forEach(e => e(Math.random())); 23 | expect(() => expect(mock).toHaveBeenCalledOnce()).toThrowErrorMatchingSnapshot(); 24 | }); 25 | 26 | test('fails when given value is not a jest spy or mock', () => { 27 | const mock1 = () => {}; 28 | expect(() => expect(mock1).toHaveBeenCalledOnce()).toThrowErrorMatchingSnapshot(); 29 | }); 30 | }); 31 | 32 | describe('.not.toHaveBeenCalledOnce', () => { 33 | let mock: jest.Mock | (() => void); 34 | beforeEach(() => { 35 | mock = jest.fn(); 36 | }); 37 | 38 | test('passes if mock was never invoked', () => { 39 | expect(mock).not.toHaveBeenCalledOnce(); 40 | }); 41 | 42 | test('passes if mock was invoked more than once', () => { 43 | mock(); 44 | mock(); 45 | expect(mock).not.toHaveBeenCalledOnce(); 46 | }); 47 | 48 | test('fails if mock was invoked exactly once', () => { 49 | mock(); 50 | expect(() => expect(mock).not.toHaveBeenCalledOnce()).toThrowErrorMatchingSnapshot(); 51 | }); 52 | }); 53 | -------------------------------------------------------------------------------- /test/matchers/toInclude.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toInclude'; 2 | 3 | expect.extend(matcher); 4 | 5 | const data = 'hello world'; 6 | 7 | describe('.toInclude', () => { 8 | test('passes when a string has a given substring', () => { 9 | expect(data).toInclude('ell'); 10 | }); 11 | 12 | test('fails when a string does not have a given substring', () => { 13 | expect(() => expect(data).toInclude('bob')).toThrowErrorMatchingSnapshot(); 14 | }); 15 | 16 | describe('.not.toInclude', () => { 17 | test('passes when a string does not have a given substring', () => { 18 | expect(data).not.toInclude('bob'); 19 | }); 20 | 21 | test('fails when a string does have a given substring', () => { 22 | expect(() => expect(data).not.toInclude('ell')).toThrowErrorMatchingSnapshot(); 23 | }); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /test/matchers/toIncludeMultiple.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toIncludeMultiple'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toIncludeMultiple', () => { 6 | test('passes when string includes all substrings', () => { 7 | expect('hello world').toIncludeMultiple(['world', 'hello']); 8 | }); 9 | 10 | test('fails when string does not include all substrings', () => { 11 | expect(() => expect('hello world').toIncludeMultiple(['hello', 'world', 'bob'])).toThrowErrorMatchingSnapshot(); 12 | }); 13 | }); 14 | 15 | describe('.not.toIncludeMultiple', () => { 16 | test('passes when string does not include all substrings', () => { 17 | expect('hello world').not.toIncludeMultiple(['world', 'hello', 'bob']); 18 | }); 19 | 20 | test('fails when string includes all substrings', () => { 21 | expect(() => expect('hello world').not.toIncludeMultiple(['hello', 'world'])).toThrowErrorMatchingSnapshot(); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /test/matchers/toIncludeRepeated.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toIncludeRepeated'; 2 | 3 | expect.extend(matcher); 4 | 5 | const string = 'hello world'; 6 | 7 | describe('.toIncludeRepeated', () => { 8 | test('passes when a string includes a given substring 1 time', () => { 9 | expect(string).toIncludeRepeated('ell', 1); 10 | }); 11 | 12 | test('passes when a string includes a given substring 3 times', () => { 13 | expect(string).toIncludeRepeated('l', 3); 14 | }); 15 | 16 | test('fails when given string does not include given substring', () => { 17 | expect(() => expect(string).toIncludeRepeated('bob', 1)).toThrowErrorMatchingSnapshot(); 18 | }); 19 | 20 | test('fails when given string does not have a given substring the correct number of times', () => { 21 | expect(() => expect(string).toIncludeRepeated('world', 2)).toThrowErrorMatchingSnapshot(); 22 | }); 23 | }); 24 | 25 | describe('.not.toIncludeRepeated', () => { 26 | test('fails when given string includes given substring 1 time', () => { 27 | expect(() => expect(string).not.toIncludeRepeated('ell', 1)).toThrowErrorMatchingSnapshot(); 28 | }); 29 | 30 | test('fails when given string includes given substring to the given occurrences', () => { 31 | expect(() => expect(string).not.toIncludeRepeated('l', 3)).toThrowErrorMatchingSnapshot(); 32 | }); 33 | 34 | test('passes when given string does not include given substring', () => { 35 | expect(string).not.toIncludeRepeated('bob', 1); 36 | }); 37 | 38 | test('passes when given string does not have a given substring the correct number of times', () => { 39 | expect(string).not.toIncludeRepeated('world', 2); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /test/matchers/toReject.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toReject'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toReject', () => { 6 | test('passes when passed a promise that rejects', async () => { 7 | const promise = Promise.reject(); 8 | await expect(promise).toReject(); 9 | }); 10 | 11 | test('fails when passed a promise that resolved', async () => { 12 | const promise = Promise.resolve(); 13 | await expect(expect(promise).toReject()).rejects.toThrowErrorMatchingSnapshot(); 14 | }); 15 | }); 16 | 17 | describe('.not.toReject', () => { 18 | test('fails when passed a promise that rejects', async () => { 19 | const promise = Promise.reject(); 20 | await expect(expect(promise).not.toReject()).rejects.toThrowErrorMatchingSnapshot(); 21 | }); 22 | 23 | test('passes when passed a promise that resolved', async () => { 24 | const promise = Promise.resolve(); 25 | await expect(promise).not.toReject(); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/matchers/toResolve.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toResolve'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toResolve', () => { 6 | test('passes when passed a promise that resolved', async () => { 7 | const promise = Promise.resolve(); 8 | await expect(promise).toResolve(); 9 | }); 10 | 11 | test('fails when passed a promise that rejects', async () => { 12 | const promise = Promise.reject(); 13 | await expect(expect(promise).toResolve()).rejects.toThrowErrorMatchingSnapshot(); 14 | }); 15 | }); 16 | 17 | describe('.not.toResolve', () => { 18 | test('fails when passed a promise that resolved', async () => { 19 | const promise = Promise.resolve(); 20 | await expect(expect(promise).not.toResolve()).rejects.toThrowErrorMatchingSnapshot(); 21 | }); 22 | 23 | test('passes when passed a promise that rejects', async () => { 24 | const promise = Promise.reject(); 25 | await expect(promise).not.toResolve(); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/matchers/toSatisfy.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toSatisfy'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toSatisfy', () => { 6 | const is2 = (n: number) => n === 2; 7 | 8 | test('passes when given a function that returns true', () => { 9 | expect(2).toSatisfy(is2); 10 | }); 11 | 12 | test('fails when given function that returns false', () => { 13 | expect(() => expect(3).toSatisfy(is2)).toThrowErrorMatchingSnapshot(); 14 | }); 15 | }); 16 | 17 | describe('.not.toSatisfy', () => { 18 | const isTrue = (a: boolean) => a; 19 | 20 | test('passes when given a function that returns false', () => { 21 | expect(false).not.toSatisfy(isTrue); 22 | }); 23 | 24 | test('fails when given a function that returns true', () => { 25 | expect(() => expect(true).not.toSatisfy(isTrue)).toThrowErrorMatchingSnapshot(); 26 | }); 27 | }); 28 | -------------------------------------------------------------------------------- /test/matchers/toSatisfyAll.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toSatisfyAll'; 2 | 3 | expect.extend(matcher); 4 | 5 | const isEven = (el: number) => el % 2 === 0; 6 | const isOdd = (el: number) => el % 2 === 1; 7 | 8 | describe('.toSatisfyAll', () => { 9 | test('passes when all values satisfy predicate', () => { 10 | expect([1, 3, 5, 7]).toSatisfyAll(isOdd); 11 | expect([2, 4, 6, 8]).toSatisfyAll(isEven); 12 | expect([11]).toSatisfyAll(isOdd); 13 | expect([10]).toSatisfyAll(isEven); 14 | }); 15 | 16 | test('fails when any value does not satisfy the predicate', () => { 17 | expect(() => expect([1, 3, 4, 5]).toSatisfyAll(isOdd)).toThrowErrorMatchingSnapshot(); 18 | }); 19 | }); 20 | 21 | describe('.not.toSatisfyAll', () => { 22 | test('passes when any value does not satisfy the predicate', () => { 23 | expect([1, 3, 4, 5]).not.toSatisfyAll(isOdd); 24 | expect([8, 6, 3, 1, 2]).not.toSatisfyAll(isEven); 25 | }); 26 | 27 | test('fails when all values satisfy predicate', () => { 28 | expect(() => expect([1, 3, 5, 7]).not.toSatisfyAll(isOdd)).toThrowErrorMatchingSnapshot(); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /test/matchers/toSatisfyAny.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toSatisfyAny'; 2 | 3 | expect.extend(matcher); 4 | 5 | const isEven = (el: number) => el % 2 === 0; 6 | const isOdd = (el: number) => el % 2 === 1; 7 | 8 | describe('.toSatisfyAny', () => { 9 | test('passes when any values satisfy predicate', () => { 10 | expect([2, 3, 6, 8]).toSatisfyAny(isOdd); 11 | expect([1, 4, 7, 9]).toSatisfyAny(isEven); 12 | expect([11]).toSatisfyAny(isOdd); 13 | expect([10]).toSatisfyAny(isEven); 14 | }); 15 | 16 | test('fails when no value satisfies the predicate', () => { 17 | expect(() => expect([2, 4, 6, 8]).toSatisfyAny(isOdd)).toThrowErrorMatchingSnapshot(); 18 | }); 19 | }); 20 | 21 | describe('.not.toSatisfyAll', () => { 22 | test('passes when all values does not satisfy the predicate', () => { 23 | expect([2, 4, 6, 8]).not.toSatisfyAny(isOdd); 24 | expect([1, 3, 5, 7]).not.toSatisfyAny(isEven); 25 | }); 26 | 27 | test('fails when any value satisfies predicate', () => { 28 | expect(() => expect([2, 3, 6, 8]).not.toSatisfyAny(isOdd)).toThrowErrorMatchingSnapshot(); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /test/matchers/toStartWith.test.ts: -------------------------------------------------------------------------------- 1 | import * as matcher from 'src/matchers/toStartWith'; 2 | 3 | expect.extend(matcher); 4 | 5 | describe('.toStartWith', () => { 6 | test('passes when string starts with given prefix', () => { 7 | expect('hello world').toStartWith('hello'); 8 | }); 9 | 10 | test('fails when the string is shorter than the given prefix', () => { 11 | expect(() => expect('hello').toStartWith('hello world')).toThrowErrorMatchingSnapshot(); 12 | }); 13 | 14 | test('fails when string does not start with the given prefix', () => { 15 | expect(() => expect('hello world').toStartWith('world')).toThrowErrorMatchingSnapshot(); 16 | }); 17 | }); 18 | 19 | describe('.not.toStartWith', () => { 20 | test('passes when string does not start with the given prefix', () => { 21 | expect('hello world').not.toStartWith('world'); 22 | }); 23 | 24 | test('passes when string is shorter than the given prefix', () => { 25 | expect('hello').not.toStartWith('hello world'); 26 | }); 27 | 28 | test('fails when string starts with given prefix', () => { 29 | expect(() => expect('hello world').not.toStartWith('hello')).toThrowErrorMatchingSnapshot(); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /test/utils/print.test.ts: -------------------------------------------------------------------------------- 1 | import { tokenize } from 'src/utils/print'; 2 | 3 | describe('print-util module', () => { 4 | it('should tokenize given string', () => { 5 | const tokens = tokenize('This function \n creates tokens \t keeping white-space intact.'); 6 | 7 | expect(tokens).toEqual([ 8 | { 9 | isWhitespace: false, 10 | value: 'This', 11 | }, 12 | { 13 | isWhitespace: true, 14 | value: ' ', 15 | }, 16 | { 17 | isWhitespace: false, 18 | value: 'function', 19 | }, 20 | { 21 | isWhitespace: true, 22 | value: ' \n ', 23 | }, 24 | { 25 | isWhitespace: false, 26 | value: 'creates', 27 | }, 28 | { 29 | isWhitespace: true, 30 | value: ' ', 31 | }, 32 | { 33 | isWhitespace: false, 34 | value: 'tokens', 35 | }, 36 | { 37 | isWhitespace: true, 38 | value: ' \t ', 39 | }, 40 | { 41 | isWhitespace: false, 42 | value: 'keeping', 43 | }, 44 | { 45 | isWhitespace: true, 46 | value: ' ', 47 | }, 48 | { 49 | isWhitespace: false, 50 | value: 'white-space', 51 | }, 52 | { 53 | isWhitespace: true, 54 | value: ' ', 55 | }, 56 | { 57 | isWhitespace: false, 58 | value: 'intact.', 59 | }, 60 | ]); 61 | }); 62 | }); 63 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "incremental": true, 4 | "tsBuildInfoFile": "./.tsbuildinfo", 5 | "target": "es2022", 6 | "module": "CommonJS", 7 | "rootDir": "src", 8 | "outDir": "dist", 9 | "esModuleInterop": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "strict": true, 12 | "allowUnreachableCode": false, 13 | "allowUnusedLabels": false, 14 | "noUncheckedIndexedAccess": true, 15 | "noImplicitOverride": true, 16 | "noUnusedLocals": true, 17 | "noUnusedParameters": true, 18 | "baseUrl": ".", 19 | "paths": { 20 | "src/*": [ 21 | "src/*" 22 | ] 23 | }, 24 | }, 25 | "include": [ 26 | "src/**/*", 27 | "types/*", 28 | ], 29 | "exclude": [ 30 | "node_modules", 31 | "dist", 32 | "examples", 33 | "website" 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /tsconfig.test.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "incremental": true, 4 | "tsBuildInfoFile": "./.tsbuildinfo", 5 | "target": "es2022", 6 | "module": "CommonJS", 7 | "rootDirs": ["src", "test"], 8 | "outDir": "dist", 9 | "esModuleInterop": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "strict": true, 12 | "allowUnreachableCode": false, 13 | "allowUnusedLabels": false, 14 | "noUncheckedIndexedAccess": true, 15 | "noImplicitOverride": true, 16 | "noUnusedLocals": true, 17 | "noUnusedParameters": true, 18 | "baseUrl": ".", 19 | "paths": { 20 | "src/*": [ 21 | "src/*" 22 | ], 23 | "test/*": [ 24 | "test/*" 25 | ] 26 | }, 27 | }, 28 | "include": [ 29 | "src/**/*", 30 | "test/**/*", 31 | "types/*", 32 | ], 33 | "exclude": [ 34 | "node_modules", 35 | "dist", 36 | "examples", 37 | "website" 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /website/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /website/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator. 4 | 5 | ### Installation 6 | 7 | ``` 8 | $ yarn 9 | ``` 10 | 11 | ### Local Development 12 | 13 | ``` 14 | $ yarn start 15 | ``` 16 | 17 | This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ### Build 20 | 21 | ``` 22 | $ yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ### Deployment 28 | 29 | Using SSH: 30 | 31 | ``` 32 | $ USE_SSH=true yarn deploy 33 | ``` 34 | 35 | Not using SSH: 36 | 37 | ``` 38 | $ GIT_USER= yarn deploy 39 | ``` 40 | 41 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 42 | -------------------------------------------------------------------------------- /website/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /website/docs/getting-started/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Getting Started", 3 | "position": 2 4 | } 5 | -------------------------------------------------------------------------------- /website/docs/getting-started/eslint.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 4 3 | --- 4 | 5 | # ESLint 6 | 7 | ## Installation 8 | 9 | npm: 10 | 11 | ``` 12 | npm install --save-dev eslint eslint-plugin-jest-extended 13 | ``` 14 | 15 | Yarn: 16 | 17 | ``` 18 | yarn add --dev eslint eslint-plugin-jest-extended 19 | ``` 20 | 21 | **Note:** If you installed ESLint globally then you must also install `eslint-plugin-jest-extended` globally. 22 | 23 | ## Usage 24 | 25 | Add `jest-extended` to the plugins section of your `.eslintrc` configuration file. You can omit the `eslint-plugin-` prefix: 26 | 27 | ```json 28 | { 29 | "plugins": ["jest-extended"] 30 | } 31 | ``` 32 | 33 | Then configure the rules you want to use under the rules section. 34 | 35 | ```json 36 | { 37 | "rules": { 38 | "jest-extended/prefer-to-be-true": "warn", 39 | "jest-extended/prefer-to-be-false": "error" 40 | } 41 | } 42 | ``` 43 | 44 | :::info 45 | Full docs can be found: [`eslint-plugin-jest-extended`](https://github.com/jest-community/eslint-plugin-jest-extended). 46 | ::: 47 | -------------------------------------------------------------------------------- /website/docs/getting-started/install.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | # Installation 6 | 7 | With npm: 8 | 9 | ```sh 10 | npm install --save-dev jest-extended 11 | ``` 12 | 13 | With yarn: 14 | 15 | ```sh 16 | yarn add -D jest-extended 17 | ``` 18 | -------------------------------------------------------------------------------- /website/docs/getting-started/typescript.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | --- 4 | 5 | # Typescript 6 | 7 | If your editor does not recognise the custom `jest-extended` matchers, add a `global.d.ts` file to your project with: 8 | 9 | ```ts 10 | import 'jest-extended'; 11 | ``` 12 | 13 | :::caution 14 | When using `ts-jest >= 25.5.0` 15 | ::: 16 | 17 | Since the breaking changes in `25.5.0` you may also need to update your `tsconfig.json` to include the new `global.d.ts` file in the `files` property like so: 18 | 19 | ```json 20 | { 21 | "compilerOptions": { 22 | ... 23 | }, 24 | ... 25 | "files": ["global.d.ts"] 26 | } 27 | ``` 28 | 29 | Also note that when adding this for the first time this affects which files are compiled by the TypeScript compiler and you might need to add the `include` property as well. See the [TypeScript docs](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) for more details. 30 | 31 | If the above import syntax does not work, replace it with the following: 32 | 33 | ```ts 34 | /// 35 | ``` 36 | 37 | :::info 38 | An example of project with Typescript globally setup can be found [here](https://github.com/jest-community/jest-extended/tree/main/examples/typescript/all). 39 | ::: 40 | -------------------------------------------------------------------------------- /website/docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | slug: / 4 | --- 5 | 6 | # Introduction 7 | 8 | ## jest-extended 🃏💪 9 | 10 | Additional Jest matchers 11 | 12 | ## Problem 13 | 14 | Jest is an amazing test runner and has some awesome assertion APIs built in by default. However, there are times when having more specific matchers (assertions) would be far more convenient. 15 | 16 | ## Solution 17 | 18 | jest-extended aims to add additional matchers to Jest's default ones making it easy to test everything 🙌 19 | -------------------------------------------------------------------------------- /website/docs/matchers/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Matchers", 3 | "position": 3 4 | } 5 | -------------------------------------------------------------------------------- /website/docs/matchers/boolean.mdx: -------------------------------------------------------------------------------- 1 | import { TestFile } from '../../src/components/CustomSandpack'; 2 | 3 | # Boolean 4 | 5 | ### .toBeBoolean() 6 | 7 | Use `.toBeBoolean` when checking if a value is a `Boolean`. 8 | 9 | 10 | {`test('passes when value is a boolean', () => { 11 | expect(false).toBeBoolean(); 12 | expect(true).toBeBoolean(); 13 | expect(1 === 1).toBeBoolean(); 14 | expect(1).not.toBeBoolean(); 15 | });`} 16 | 17 | 18 | ### .toBeTrue() 19 | 20 | Use `.toBeTrue` when checking a value is equal (`===`) to `true`. 21 | 22 | 23 | {`const isJestCool = () => true;\n 24 | test('is jest cool', () => { 25 | expect(isJestCool()).toBeTrue(); 26 | expect(false).not.toBeTrue(); 27 | });`} 28 | 29 | 30 | 31 | ### .toBeFalse() 32 | 33 | Use `.toBeFalse` when checking a value is equal (`===`) to `false`. 34 | 35 | 36 | {`const areWeThereYet = () => false;\n 37 | test('returns false', () => { 38 | expect(areWeThereYet()).toBeFalse(); 39 | expect(true).not.toBeFalse(); 40 | });`} 41 | 42 | -------------------------------------------------------------------------------- /website/docs/matchers/fail.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 2 3 | --- 4 | 5 | import { TestFile } from '../../src/components/CustomSandpack'; 6 | 7 | # .fail(message) 8 | 9 | Failing assertion. 10 | 11 | 12 | {`test('fail', () => { 13 | expect().fail('test should fail'); 14 | });`} 15 | 16 | -------------------------------------------------------------------------------- /website/docs/matchers/mock.mdx: -------------------------------------------------------------------------------- 1 | import { TestFile } from '../../src/components/CustomSandpack'; 2 | 3 | # Mock 4 | 5 | ### .toHaveBeenCalledBefore() 6 | 7 | Use `.toHaveBeenCalledBefore` when checking if a `Mock` was called before another `Mock`. 8 | 9 | 10 | {`test('calls mock1 before mock2', () => { 11 | const mock1 = jest.fn(); 12 | const mock2 = jest.fn();\n 13 | mock1(); 14 | mock2(); 15 | mock1();\n 16 | expect(mock1).toHaveBeenCalledBefore(mock2); 17 | });`} 18 | 19 | 20 | 21 | ### .toHaveBeenCalledAfter() 22 | 23 | Use `.toHaveBeenCalledAfter` when checking if a `Mock` was called after another `Mock`. 24 | 25 | 26 | {`test('calls mock1 after mock2', () => { 27 | const mock1 = jest.fn(); 28 | const mock2 = jest.fn();\n 29 | mock2(); 30 | mock1(); 31 | mock2();\n 32 | expect(mock1).toHaveBeenCalledAfter(mock2); 33 | });`} 34 | 35 | 36 | 37 | ### .toHaveBeenCalledOnce() 38 | 39 | Use `.toHaveBeenCalledOnce` to check if a `Mock` was called exactly one time. 40 | 41 | 42 | {`test('passes only if mock was called exactly once', () => { 43 | const mock = jest.fn();\n 44 | expect(mock).not.toHaveBeenCalled(); 45 | mock(); 46 | expect(mock).toHaveBeenCalledOnce(); 47 | });`} 48 | 49 | 50 | 51 | ### .toHaveBeenCalledExactlyOnceWith() 52 | 53 | Use `.toHaveBeenCalledExactlyOnceWith` to check if a `Mock` was called exactly one time and with the expected values. 54 | 55 | 56 | {`test('passes only if mock was called exactly once with the expected value', () => { 57 | const mock = jest.fn();\n 58 | expect(mock).not.toHaveBeenCalled(); 59 | mock('hello'); 60 | expect(mock).toHaveBeenCalledExactlyOnceWith('hello'); 61 | });`} 62 | 63 | 64 | -------------------------------------------------------------------------------- /website/docs/matchers/pass.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 1 3 | --- 4 | 5 | import { TestFile } from '../../src/components/CustomSandpack'; 6 | 7 | # .pass(message) 8 | 9 | Passing assertion. 10 | 11 | 12 | {`test('.pass', async () => { 13 | expect().pass("should pass"); 14 | });`} 15 | 16 | -------------------------------------------------------------------------------- /website/docs/matchers/promise.mdx: -------------------------------------------------------------------------------- 1 | import { TestFile } from '../../src/components/CustomSandpack'; 2 | 3 | # Promise 4 | 5 | ### .toResolve() 6 | 7 | Use `.toResolve` when checking if a promise is resolved. 8 | 9 | 10 | {`test('passes when a promise resolves', async () => { 11 | await expect(Promise.resolve()).toResolve(); 12 | });`} 13 | 14 | 15 | ### .toReject() 16 | 17 | Use `.toReject` when checking if a promise is rejected. 18 | 19 | 20 | {`test('passes when a promise rejects', async () => { 21 | await expect(Promise.reject()).toReject(); 22 | });`} 23 | 24 | -------------------------------------------------------------------------------- /website/docs/matchers/symbol.mdx: -------------------------------------------------------------------------------- 1 | import { TestFile } from '../../src/components/CustomSandpack'; 2 | 3 | # Symbol 4 | 5 | ### .toBeSymbol() 6 | 7 | Use `.toBeSymbol` when checking if a value is a `Symbol`. 8 | 9 | 10 | {`test('passes when value is a symbol', () => { 11 | expect(Symbol()).toBeSymbol(); 12 | expect(true).not.toBeSymbol(); 13 | });;`} 14 | 15 | -------------------------------------------------------------------------------- /website/docs/matchers/toBeEmpty.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 3 3 | --- 4 | 5 | import { TestFile } from '../../src/components/CustomSandpack'; 6 | 7 | # .toBeEmpty() 8 | 9 | Use `.toBeEmpty` when checking if a `String` `''`, `Array` `[]`, `Object` `{}`, or [`Iterable`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#Built-in_iterables) is empty. Because `toBeEmpty` supports checking for emptiness of Iterables, you can use it to check whether a `Map`, or `Set` is empty, as well as checking that a generator yields no values. 10 | 11 | 12 | {`test('passes when given an empty string', () => { 13 | expect('').toBeEmpty(); 14 | expect('hello').not.toBeEmpty(); 15 | });\n 16 | test('passes when given an empty array', () => { 17 | expect([]).toBeEmpty(); 18 | expect(['hello']).not.toBeEmpty(); 19 | });\n 20 | test('passes when given an empty object', () => { 21 | expect({}).toBeEmpty(); 22 | expect({ hello: 'world' }).not.toBeEmpty(); 23 | });`} 24 | 25 | -------------------------------------------------------------------------------- /website/docs/matchers/toBeNil.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | --- 4 | 5 | import { TestFile } from '../../src/components/CustomSandpack'; 6 | 7 | # .toBeNil() 8 | 9 | Use `.toBeNil` when checking a value is `null` or `undefined`. 10 | 11 | 12 | {`test('passes when value is null or undefined', () => { 13 | expect(null).toBeNil(); 14 | expect(undefined).toBeNil(); 15 | expect(true).not.toBeNil(); 16 | });`} 17 | 18 | -------------------------------------------------------------------------------- /website/docs/matchers/toBeOneOf.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 4 3 | --- 4 | 5 | import { TestFile } from '../../src/components/CustomSandpack'; 6 | 7 | # .toBeOneOf([members]) 8 | 9 | Use `.toBeOneOf` when checking if a value is a member of a given `Array`. 10 | 11 | 12 | {`test('passes when value is in given array', () => { 13 | expect(1).toBeOneOf([1, 2, 3]); 14 | expect(4).not.toBeOneOf([1, 2, 3]); 15 | });`} 16 | 17 | -------------------------------------------------------------------------------- /website/docs/matchers/toSatisfy.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 6 3 | --- 4 | 5 | import { TestFile } from '../../src/components/CustomSandpack'; 6 | 7 | # .toSatisfy(predicate) 8 | 9 | Use `.toSatisfy` when you want to use a custom matcher by supplying a predicate function that returns a `Boolean`. 10 | 11 | 12 | {`test('passes when value passes given predicate', () => { 13 | const greaterThanOneButNotThree = n => n > 1 && n !== 3; 14 | expect(100).toSatisfy(greaterThanOneButNotThree); 15 | expect(0).not.toSatisfy(greaterThanOneButNotThree); 16 | expect(3).not.toSatisfy(greaterThanOneButNotThree); 17 | });`} 18 | 19 | -------------------------------------------------------------------------------- /website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "website", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "docusaurus start", 8 | "build": "docusaurus build", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "clear": "docusaurus clear", 12 | "serve": "docusaurus serve", 13 | "write-translations": "docusaurus write-translations", 14 | "write-heading-ids": "docusaurus write-heading-ids", 15 | "typecheck": "tsc" 16 | }, 17 | "dependencies": { 18 | "@codesandbox/sandpack-react": "^2.0.0", 19 | "@codesandbox/sandpack-themes": "^2.0.0", 20 | "@docusaurus/core": "3.8.0", 21 | "@docusaurus/preset-classic": "3.8.0", 22 | "@mdx-js/react": "^3.0.0", 23 | "clsx": "^2.0.0", 24 | "prism-react-renderer": "^2.0.0", 25 | "react": "^19.0.0", 26 | "react-dom": "^19.0.0" 27 | }, 28 | "devDependencies": { 29 | "@docusaurus/module-type-aliases": "3.8.0", 30 | "@tsconfig/docusaurus": "^2.0.0", 31 | "typescript": "^5.0.0" 32 | }, 33 | "browserslist": { 34 | "production": [ 35 | ">0.5%", 36 | "not dead", 37 | "not op_mini all" 38 | ], 39 | "development": [ 40 | "last 1 chrome version", 41 | "last 1 firefox version", 42 | "last 1 safari version" 43 | ] 44 | }, 45 | "engines": { 46 | "node": ">=16.14" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /website/sidebars.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Creating a sidebar enables you to: 3 | - create an ordered group of docs 4 | - render a sidebar for each doc of that group 5 | - provide next/previous navigation 6 | 7 | The sidebars can be generated from the filesystem, or explicitly defined here. 8 | 9 | Create as many sidebars as you want. 10 | */ 11 | 12 | // @ts-check 13 | 14 | /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ 15 | const sidebars = { 16 | // By default, Docusaurus generates a sidebar from the docs folder structure 17 | tutorialSidebar: [{ type: 'autogenerated', dirName: '.' }], 18 | 19 | // But you can create a sidebar manually 20 | /* 21 | tutorialSidebar: [ 22 | { 23 | type: 'category', 24 | label: 'Tutorial', 25 | items: ['hello'], 26 | }, 27 | ], 28 | */ 29 | }; 30 | 31 | module.exports = sidebars; 32 | -------------------------------------------------------------------------------- /website/src/components/HomepageFeatures/styles.module.css: -------------------------------------------------------------------------------- 1 | .features { 2 | display: flex; 3 | align-items: center; 4 | padding: 2rem 0; 5 | width: 100%; 6 | } 7 | 8 | .featureSvg { 9 | height: 200px; 10 | width: 200px; 11 | } 12 | -------------------------------------------------------------------------------- /website/src/css/custom.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Any CSS included here will be global. The classic template 3 | * bundles Infima by default. Infima is a CSS framework designed to 4 | * work well for content-centric websites. 5 | */ 6 | 7 | /* You can override the default Infima variables here. */ 8 | :root { 9 | --ifm-color-primary: #2e8555; 10 | --ifm-color-primary-dark: #29784c; 11 | --ifm-color-primary-darker: #277148; 12 | --ifm-color-primary-darkest: #205d3b; 13 | --ifm-color-primary-light: #33925d; 14 | --ifm-color-primary-lighter: #359962; 15 | --ifm-color-primary-lightest: #3cad6e; 16 | --ifm-code-font-size: 95%; 17 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); 18 | } 19 | 20 | /* For readability concerns, you should choose a lighter palette in dark mode. */ 21 | [data-theme='dark'] { 22 | --ifm-color-primary: #25c2a0; 23 | --ifm-color-primary-dark: #21af90; 24 | --ifm-color-primary-darker: #1fa588; 25 | --ifm-color-primary-darkest: #1a8870; 26 | --ifm-color-primary-light: #29d5b0; 27 | --ifm-color-primary-lighter: #32d8b4; 28 | --ifm-color-primary-lightest: #4fddbf; 29 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); 30 | } 31 | -------------------------------------------------------------------------------- /website/src/pages/index.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * CSS files with the .module.css suffix will be treated as CSS modules 3 | * and scoped locally. 4 | */ 5 | 6 | .heroBanner { 7 | padding: 4rem 0; 8 | text-align: center; 9 | position: relative; 10 | overflow: hidden; 11 | } 12 | 13 | @media screen and (max-width: 996px) { 14 | .heroBanner { 15 | padding: 2rem; 16 | } 17 | .playground { 18 | padding: 2rem; 19 | } 20 | } 21 | 22 | .buttons { 23 | display: flex; 24 | align-items: center; 25 | justify-content: center; 26 | } 27 | 28 | .playground { 29 | padding: 4rem 2rem; 30 | } 31 | -------------------------------------------------------------------------------- /website/static/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jest-community/jest-extended/35545697c11ee0a1c9a7a18455b5053c71ca3b66/website/static/.nojekyll -------------------------------------------------------------------------------- /website/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jest-community/jest-extended/35545697c11ee0a1c9a7a18455b5053c71ca3b66/website/static/img/favicon.ico -------------------------------------------------------------------------------- /website/static/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jest-community/jest-extended/35545697c11ee0a1c9a7a18455b5053c71ca3b66/website/static/img/logo.png -------------------------------------------------------------------------------- /website/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | // This file is not used in compilation. It is here just for a nice editor experience. 3 | "extends": "@tsconfig/docusaurus/tsconfig.json", 4 | "compilerOptions": { 5 | "baseUrl": "." 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /website/vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "github": { 3 | "silent": true 4 | } 5 | } 6 | --------------------------------------------------------------------------------