Coder Social home page Coder Social logo

jamiemason / expect-more Goto Github PK

View Code? Open in Web Editor NEW
169.0 5.0 10.0 1.66 MB

Curried Type Testing library, and Test Matchers for Jest

License: MIT License

JavaScript 1.31% TypeScript 98.66% Shell 0.03%
assertions expect assert property-based-testing test-matchers jest jest-matchers jasmine jasmine-matchers matchers

expect-more's Introduction

expect-more's People

Contributors

dependabot[bot] avatar git-jiby-me avatar haroenv avatar jamiemason avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

expect-more's Issues

Support jest v29

Description

expect-more-jest should be migrated to jest v29 deps

Suggested Solution

upgrade deps

Help Needed

Check optional fields (may be present in object or not)

Description

I have a case when the field can be present or not in the object. I would like to check the field if it's present in the object
Case 1: { a: 10, b: 'qwerty' }
Case 2: { a: 10, b: 'qwerty' , c: 10}

(this won't work)

expect({ a: 10, b: 'qwerty' }).toMatchObject({
    a: expect.toBePositiveNumber(),
    b: expect.toBeNonEmptyString(),
    c: expect.toBeOptionalOf(expect.toBeNumber()),
  })

Returns error:

Expected: {"a": toBePositiveNumber<>, "b": toBeNonEmptyString<>, "c": toBeOptionalOf<toBeNumber>}
Received: {"a": 10, "b": "qwerty"}

Maybe there is a way to check optional field?

Suggested Solution

Help Needed

expect().toHandle* regression in 1.0.0

The issue is in these 3 lines, a second argument is needed to received the shape.

Cover with tests and fix code and typings.

Should be something like:

const createToHandleComparer = (matcherName: string, createGenerator: generatorCreator) => 
  (received: () => void), shape: any[] | object) => {
    const generator: IGenerator = createGenerator(shape);
    const result = generator.assert(received);
    // ....

Does not declare any runtime dependencies

Description

This project only declares devDependencies which is not really accurate. devDependencies are not transitory which means there is not currently any declared version compatibility limitation with respect to Jest and this project when used together in another project. However, this project breaks with jest and jest-jasmine2 ^28:

    Cannot find module 'expect/build/jasmineUtils' from 'node_modules/expect-more-jest/dist/to-be-array-of.js'

    Require stack:
      node_modules/expect-more-jest/dist/to-be-array-of.js
      node_modules/expect-more-jest/dist/index.js

      at Resolver._throwModNotFoundError (node_modules/jest-runtime/node_modules/jest-resolve/build/resolver.js:491:11)
      at Object.<anonymous> (node_modules/expect-more-jest/dist/to-be-array-of.js:5:22)

Suggested Solution

This project should be declaring regular runtime dependencies or peer dependencies for any version requirements it needs to run. Otherwise, users of this library are not alerted that this library even requires jest let alone that it only works with certain versions.

Property 'custom jest matcher' does not exist on type 'Matchers<R>'

Hi there, thanks for a great library!

I'm having some TypeScript compiler errors on my project:

  expect(result.sentAt).toBeIso8601();
Property 'toBeIso8601' does not exist on type 'Matchers<string>'.

I'm using TypeScript 2.9.2 with the following dependencies:

  • "@types/jest": "^23.3.0"
  • "expect-more-jest": "^2.0.0"
  • "jest": "^23.4.1"

I've tried to get around it for now by hacking the interface, but it makes my tests a little bit harder to read:

interface ExtendedMatchers extends jest.Matchers<R> {
  toBeIso8601(): R;
}

// usage example
(expect(result.sentAt) as ExtendedMatchers).toBeIso8601();

Unable to import expect-more jest

Description

The scaffolder newts installs expect-even-more-jest which depends on expect-more-jest. After creating a project with the latest of both (npx newts@beta), tests cannot run:

 FAIL  tests/index.spec.ts
  โ— Test suite failed to run

    Cannot find module 'expect/build/jasmineUtils' from 'node_modules/expect-more-jest/dist/to-be-array-of.js'

    Require stack:
      node_modules/expect-more-jest/dist/to-be-array-of.js
      node_modules/expect-more-jest/dist/index.js
      node_modules/expect-even-more-jest/dist/index.js
      tests/index.spec.ts

      at Resolver._throwModNotFoundError (node_modules/jest/node_modules/jest-resolve/build/resolver.js:491:11)
      at Object.<anonymous> (node_modules/expect-more-jest/dist/to-be-array-of.js:5:22)

delving a little deeper, by doing:

global.expect = require("expect");
require("expect-more-jest");

produces

Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './build/jasmineUtils' is not defined by "exports" in C:\tmp\moo-cakes-wtf\node_modules\expect\package.json
    at throwExportsNotFound (internal/modules/esm/resolve.js:299:9)
    at packageExportsResolve (internal/modules/esm/resolve.js:522:3)
    at resolveExports (internal/modules/cjs/loader.js:424:36)
    at Function.Module._findPath (internal/modules/cjs/loader.js:464:31)
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:802:27)
    at Function.Module._load (internal/modules/cjs/loader.js:667:27)
    at Module.require (internal/modules/cjs/loader.js:887:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at Object.<anonymous> (C:\tmp\moo-cakes-wtf\node_modules\expect-more-jest\dist\to-be-array-of.js:5:22)
    at Module._compile (internal/modules/cjs/loader.js:999:30) {
  code: 'ERR_PACKAGE_PATH_NOT_EXPORTED'
}

Suggested Solution

Perhaps copy-pasta the required code or use a git submodule to get to it?

If I get a moment, I'll try raise a PR

expect-more-jest: Types missing from InverseAsymmetricMatchers

I tried expect.not.toBeIso8601() as an asymmetric matcher and got this error:

error TS2339: Property 'toBeIso8601' does not exist on type 'InverseAsymmetricMatchers'.

A fix like this needs to be done for every matcher. In the meantime, this same code works as a workaround in my user code:

declare global {
  namespace jest {
    interface InverseAsymmetricMatchers {
      toBeIso8601(): any
    }
  }
}

P.S. I really appreciate this library. It gets the algebra correct and lets me reuse existing matchers (which throw errors with rich diffs) instead of making me write all-new predicates (that return boolean with no diffs) unlike jest-extended. Now I just have to get Jest to fix toHaveBeenCalledWith (and friends) to stop masking the rich diffs...

toBeArrayOfSize() throwing error on constructing message

When using:

expect(arrayOfObjects).toBeArrayOfSize(n)

I am getting errors from expect-more on creation of the jest error message when the test fails:

  TypeError: Cannot convert object to primitive value
      at Array.join (<anonymous>)
      at Array.toString (<anonymous>)
      at message (node_modules/expect-more-jest/dist/to-be-array-of-size.js:7:51)
      at message (node_modules/expect-more-jest/dist/lib/create-result.js:6:62)
      at getMessage (node_modules/expect/build/index.js:209:15)
      at processResult (node_modules/expect/build/index.js:327:25)
      at Object.toBeArrayOfSize (node_modules/expect/build/index.js:396:16)

Implement expect(foo).toBeAsyncFunction()

When expecting against an async function in TypeScript, I find that

expect(fn).toBeFunction();

fails. Delving deeper, it's because the implementation doesn't just do something along the lines of:

assert(typeof(actual) === "function");

(which is how I've implemented toBeFunction before just being lazy and relying on expect-more-jest). So the typescript test for the above fails because

Object.prototype.toString.call(fn) === "[object AsyncFunction]";

I wrote out the matcher and typings to complete this, in my repo:

import MatchersUtil = jasmine.MatchersUtil;
import CustomEqualityTester = jasmine.CustomEqualityTester;
import CustomMatcherResult = jasmine.CustomMatcherResult;

declare module jest {
    interface Matchers<R> {
        toBeAsyncFunction<R>(): void;
    }
}

function assert(expr, failMessage) {
    if (!expr) {
        throw new Error(failMessage);
    }
}

function runAssertions(func: () => void) {
    try {
        func();
        return {
            message: "",
            pass: true
        };
    } catch (e) {
        return {
            pass: false,
            message: e.message || e
        };
    }
}

jest.addMatchers({
    toBeAsyncFunction: function (util: MatchersUtil, customEqualityTester: CustomEqualityTester[]) {
        return {
            compare: function (actual: any): CustomMatcherResult {
                return runAssertions(() =>
                    assert(Object.prototype.toString.call(actual) === "[object AsyncFunction]",
                        `expected async function but got ${JSON.stringify(actual)}`)
                );
            }
        };
    }
});

Apologies for:

  • 4-space indents (it's our chosen company style)
  • "convolution" via assert and try/catch -- I expect to add more matchers and have found this to be a relatively simple way to add more matchers

I cloned this repo because I wanted to create a PR for this, but I can't successfully run tests -- npm test doesn't run for me (**). I'm probably doing something wrong, so I'd appreciate a push in the right direction, in which case, I'll just submit a PR (: In the meantime, .toBeFunction doesn't appear to recognise async functions correctly.

** What I have tried:

  1. Originally, npm test fails, throwing errors about invalid syntax around import statements. Replacing the inbuilt transpile-tests.js by installing ts-jest and using that instead, fixed that, but then came:
  2. Tests failing because they can't import expect-more. Now, I can see that each item under packages has its own package.json, but tests are run in the context of the base package; also, this is a bit of a chicken-and-egg: I can't write tests against the new code without uploading the package, if I'm to expect the import from the expect-more in each package.json to suffice. I've tried hard-linking the src folder of package.json to the node_modules folder in the base -- which gets tests to run, but many fail (for example isDivisibleBy fails on typescript errors, saying that isDivisibleBy should take two arguments -- and afaik, this is the difference between jasmine 1 and 2 tests? Not sure; anyhoo, I'm a bit lost as to the correct way to run tests and there's no point making a PR if I can't even prove that what I've added works :/ But again, given a push in the right direction, I'll gladly have a swing at it.

Similar functionality for jest expect standalone?

There's a standalone package for jest-expect, but it uses different namespace from jest itself, and also different type names for matchers, so it's impossible to simply reuse expect-more-jest package for this case.

It would really be very helpful to be able to extend that package with your matchers.

Redesign toSurvive Matcher

Had some good feedback on toSurvive that it would be easier to understand if redesigned as:

expect(unsafe).toHandleMissingBranches(shape);
expect(unsafe).toHandleMissingLeaves(shape);
expect(unsafe).toHandleMissingNodes(shape);
expect(unsafe).toHandleNullBranches(shape);
expect(unsafe).toHandleNullLeaves(shape);
expect(unsafe).toHandleNullNodes(shape);

instead of:

expect(safe).toSurvive(gen.nullNodes(shape));

and to use lodash.get in the docs example instead of getIn.

Array expectations like toBeArrayIncludingOnly do not support asymmetric matching

Description

When stating complex or partial matches on things like parameters, is is often necessary to compare the contents of objects in an array. With standard expectations like arrayContaining, you can do this using asymmetric matchers like this:

test('should contain important objects in array', () => {
    const array = [
        { 
            important: 'important',
            ignore: 'ignore'
        },
        {
            ignore: 'ignore',
        }
    ];

    expect(soy).toHaveBeenCalledWith(expect.arrayContaining(
        [expect.objectContaining({ important: 'important' })]
    ));
});

One would expect that expectations like toBeArrayIncludingOnly would follow the same semantic rules as arrayContaining and be a "drop in" replacement. However, this is not currently true because toBeArrayIncludingOnly (and others) do not appear to support asymmetric matching.

Suggested Solution

Array functions similar to arrayContaining should follow the same semantic rules and be "drop in" replacements by support asymmetric matchers.

Document asymmetric matching capabilities

Description

This library is very good. However the documentation doesn't mention that the matchers are also asymmetric. I had to test this by doing:

expect([{ dt: new Date('2021-08-29') }]).toBeArrayOf({ dt: 
   expect.toBeDateInMonth(7)
 });

It'd be nice if this was mentioned as this is one of the best things about this lib.

Also document that this works with Vitest

toBeWithinRange

Why toBeWithinRange is commented in Jest implementation and will it come back?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.