Jest: toContainEqual+toMatchObject

Created on 1 Jul 2018  路  8Comments  路  Source: facebook/jest

馃殌 Feature Proposal

Find an object in an array that matches like an object.

Motivation

There may be times where you need to match a partial object against something in a returned list.

Example

I am writing tests for an ORM that saves an object, but it adds extra metadata to the objects when they are later retrieved. The order of the list is not deterministic. Therefor I want to match the fetched object list from the DB and test if the origin object I saved matches any of the objects in the list returned from the query.

Most helpful comment

I'm on the fence about that. I feel like Jest core has all the matchers I've needed, except just this one. Of course being a one-off is not a reason to include it, but this does seem like a very useful and perhaps common situation to test.
Often API's yield non-deterministic lists (particularly streams) and you would like to check if one of the list items matches a test object value. It also needs to be a partial match and more and more APIs that return lists add an additional soul key to keep an internal reference of the value.. and that I don't want to try to match against that in my tests. It seems a reasonable idea to have this matcher in core imho.

All 8 comments

Can you provide an example test?

@rickhanlonii
sure:

const list = [ 
  { foo: "bar" , color: "blue"},
  { foo: "bazz" , color: "red"},
]

expect(list).toContainMatch( { color: "blue" } ); // true
expect(list).toContainMatch( { color: "red" } ); // true
expect(list).toContainMatch( { foo: "bar" , color: "blue"} ); // true
expect(list).toContainMatch( { color: "green"} ); // false

Sounds like a good fit for jest-extended?

I'm on the fence about that. I feel like Jest core has all the matchers I've needed, except just this one. Of course being a one-off is not a reason to include it, but this does seem like a very useful and perhaps common situation to test.
Often API's yield non-deterministic lists (particularly streams) and you would like to check if one of the list items matches a test object value. It also needs to be a partial match and more and more APIs that return lists add an additional soul key to keep an internal reference of the value.. and that I don't want to try to match against that in my tests. It seems a reasonable idea to have this matcher in core imho.

Ah, I understand now. You can write your example with asymmetric matchers as:

const list = [{ foo: "bar", color: "blue" }, { foo: "bazz", color: "red" }];

test("using asymmetric matchers", () => {

  expect(list).toEqual(
    expect.arrayContaining([expect.objectContaining({ color: "blue" })])
  );

  expect(list).toEqual(
    expect.arrayContaining([expect.objectContaining({ color: "red" })])
  );

  expect(list).toEqual(
    expect.arrayContaining([
      expect.objectContaining({ foo: "bar", color: "blue" })
    ])
  );

  expect(list).not.toEqual(
    expect.arrayContaining([expect.objectContaining({ color: "green" })])
  );
});

I think this would be a great addition to jest-extended which has some pretty common matchers like toBeEven and toBeEmpty which arguably are more common than this proposal for many cases

We're really strict with what makes it into core, and right now we are really only adding matchers which are applicable for all users or need to be in core for some dependency

For popular use cases like this one, we look to the community and jest-extended. This allows us to focus on building core features and not spending a lot of our time fixing/updating/maintaining a long list of matchers

Hope that makes sense!

Closing, but happy to keep the discussion open

Okay, I think this makes sense. I've added an issue to jest-extended.

I stumbled on this issue in search of this solution and found the stringMatching function quite useful/relevant. See below:

  expect(list).toEqual(
    expect.arrayContaining([
      expect.objectContaining({ foo: expect.stringMatching("bar"), color: "blue" })
    ])
  );
Was this page helpful?
0 / 5 - 0 ratings