镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

Proposal: assert.matchObject #50399

Description

@arthurfiorette

What is the problem this feature will solve?

(I tried searching for related issues, but couldn't find one, sorry if this is a duplicated)

One thing I miss when using node:test and node:assert from jest related tests is the expect(A).toMatchObject(B) api. Within large production systems, a we usually have large objects with multiple deep properties, with assert.matchObject we could test the same way as assert.deepStrictEqual, but only specifying expected properties we want to test out with a much nicer DX. Obviously a assert.notMatchObject should also be present.

Current behavior:

const myObjectToTest = {
  a: 1,
  b: 2,
  c: {
    d: 3,
    e: 4,
    f: {
       g: 5
    }
  }
}

// For my specific test, I want to assert `myObjectToTest.b` and `myObjectToTest.c.f.g`.
assert.equal(myObjectToTest.b, 2);
assert.equal(myObjectToTest.c.f.g, 5);

// If I wanted to check against another object or using a object (better DX)
// I must specify ALL fields (even the one that doesn't matter for my specific test)
assert.deepStrictEqual(myObjectToTest, {
  a: 1,
  b: 2,
  c: {
    d: 3,
    e: 4,
    f: {
      g: 5
    }
  }
});

What is the feature you are proposing to solve the problem?

With assert.matchObject:

assert.matchObject(myObjectToTest, {
  b: 2,
  c: {
    f: {
      g: 5
    }
  }
});

It should ensure equality only for properties assigned to the second parameter. myObjectToTest could have 10000 other attributes or be literally the same as the second parameter, it would pass. Whenever a property declared inside the second object is not present in the first one, an AssertionError should be thrown.

Of course this is a small example that could be tested separately, but it is a perfect DX fit for large objects.

What alternatives have you considered?

I'm creating this feature request with a jest like API in mind, however any alternatives that also fixes this problem are welcome :) I'm also open to working on this, but first I need some kind of guidance :)

Activity

  1. added
    assertIssues and PRs related to the assert subsystem.
    on Oct 26, 2023
  2. targos commented on Oct 26, 2023

    @targos
    Member

    /cc @nodejs/assert. This doesn't seem like a bad idea to me.

  3. ljharb commented on Oct 26, 2023

    @ljharb
    SponsorMember

    so the difference between this and deepEqual is just that it only checks present properties on the "actual" against the "expected"? could this just be an option to deepEqual?

  4. arthurfiorette commented on Oct 26, 2023

    @arthurfiorette
    Author

    so the difference between this and deepEqual is just that it only checks present properties on the "actual" against the "expected"?

    yes.

    could this just be an option to deepEqual?

    Well, I guess so, but i'm more convinced that it should be the same as many other testing frameworks as a dedicated method.

  5. aduh95 commented on Oct 26, 2023

    @aduh95
    Contributor

    To me "assert to match object" is really not something I could understand without reading its docs, so I would prefer if we picked a different name. I think adding allowSuperset option to deepStrictEqual or something like that would make the most sense, and we can always expose an alias later if we feel the need (just my two cents, feel free to disagree). PRs welcome :)

  6. MoLow commented on Oct 26, 2023

    @MoLow
    Member

    +1 on that. assert.throws already supports something similar

  7. Pyrolistical commented on Oct 26, 2023

    @Pyrolistical

    could this just be an option to deepEqual?

    imo no. the current signature of deepEqual is assert.deepEqual(actual, expected[, message]), and if we were to maintain backwards compatibility, we would need to add the option after message. but in order for people to use this new option, they would be required to define a message which they may not want to.

    A way to make this would would require a soft breaking change with a new signature of:

    deepEqual<T>(actual: unknown, expected: T, messageOrOption?: string | {
      message?: string;
      superset?: boolean;
    })
  8. Pyrolistical commented on Oct 26, 2023

    @Pyrolistical

    @aduh95 I agree matchObject isn't a great name if it were to work with arrays (as does jest toMatchObject), but I also don't like adding an option to deepStrictEqual for the same reason as my previous comment.

    How about deepSupersetStrictEqual? We still want the primitives to be compared using ===. Maybe never add legacy deepSupersetEqual to node:assert but only add it to node:assert/strict?

  9. ljharb commented on Oct 26, 2023

    @ljharb
    SponsorMember

    I think it would be fine to make the optional third argument an options object if not a string, as you suggested - and will ensure future compatibility for additional options.

  10. bakkot commented on Oct 26, 2023

    @bakkot
    Contributor

    "superset" is a confusing name for this behavior; "allowExtraProperties", maybe?

  11. arthurfiorette commented on Oct 26, 2023

    @arthurfiorette
    Author

    Just extending the deepStrictEqual into this signature would not result in a breaking change:

    function deepStrictEqual<T>(actual: unknown, expected: T, message?: string | Error): asserts actual is T;
    function deepStrictEqual<T>(actual: unknown, expected: T, options?: { superset?: boolean }, message?: string | Error): asserts actual is T;

    I'm still not sure if an attribute would have a better DX:

    // attribute
    assert.deepStrictEqual(
      obj,
      {
        a: 1,
        b: 2
      },
      {
        superset: true
      }
    );
    
    // custom method
    assert.deepSupersetEqual(obj, {
      a: 1,
      b: 2
    });
  12. MoLow commented on Oct 27, 2023

    @MoLow
    Member

    what is the downside of a new method? @aduh95

  13. 37 remaining items

  14. added a commit that references this issue on Nov 23, 2024
  15. added a commit that references this issue on Nov 26, 2024
  16. added a commit that references this issue on Jan 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    assertIssues and PRs related to the assert subsystem.feature requestIssues requesting new Node.js features.

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions