m-radzikowski/aws-sdk-client-mock

Improve diffing of Jest Matchers

Opened this issue · 1 comments

Love the library. It is much more ergonomic compared to the mocking I was doing by hand!

Jest can show a diff between the received and actual calls when I use .toHaveBeenCalledWith(...) including when there are multiple non-matches.

Diff Examples in a Details so this ticket doesn't look super long
describe('diff demo', () => {
    it('diffs the real call and expected', () => {
        const mockFn = jest.fn();
        mockFn({ RoleArn: 'abc', RoleSessionName: 'def' });
        expect(mockFn).toHaveBeenCalledWith({
            SomeField: 'xyz',
            RoleArn: 'ABC',
            RoleSessionName: 'def',
        });
    });
});
expect(jest.fn()).toHaveBeenCalledWith(...expected)

- Expected
+ Received

  Object {
-   "RoleArn": "ABC",
+   "RoleArn": "abc",
    "RoleSessionName": "def",
-   "SomeField": "xyz",
  },

Number of calls: 1
it('diffs the real call and expected with multiple calls', () => {
    const mockFn = jest.fn();
    mockFn({ RoleArn: 'abc', RoleSessionName: 'def' });
    mockFn({ SomeField: 'xyz', RoleSessionName: 'def' });
    expect(mockFn).toHaveBeenCalledWith({
        SomeField: 'xyz',
        RoleArn: 'ABC',
        RoleSessionName: 'def',
    });
});
expect(jest.fn()).toHaveBeenCalledWith(...expected)

Expected: {"RoleArn": "ABC", "RoleSessionName": "def", "SomeField": "xyz"}
Received
       1
          Object {
        -   "RoleArn": "ABC",
        +   "RoleArn": "abc",
            "RoleSessionName": "def",
        -   "SomeField": "xyz",
          },
       2
          Object {
        -   "RoleArn": "ABC",
            "RoleSessionName": "def",
            "SomeField": "xyz",
          },

Number of calls: 2

Whereas when I use aws-sdk-client-mock-jest matcher .toHaveReceivedCommandWith

it("Doesn't diff the real call and expected", async () => {
    const mockedClient = new STSClient();
    await mockedClient.send(
        new AssumeRoleCommand({
            RoleArn: 'abc',
            RoleSessionName: 'def',
        }),
    );

    expect(stsMock).toHaveReceivedCommandWith(AssumeRoleCommand, {
        RoleArn: 'ABC',
        RoleSessionName: 'def',
        SourceIdentity: 'xyz',
    });
});
Expected STSClient to receive "AssumeRoleCommand" with {"RoleArn": "ABC", "RoleSessionName": "def", "SourceIdentity": "xyz"}
STSClient received matching "AssumeRoleCommand" 0 times

Calls:
  1. AssumeRoleCommand: {"RoleArn": "abc", "RoleSessionName": "def"}

particularly when the difference between expected and actual is subtle (the example that prompted this feature request was an arn with a : v.s. :: it would be nice to see the diff output (which I naively assume Jest can do for us? 🤞)

If this is a feature you'd support I'd happily contribute some time to making it happen.

The main problem here is that toHaveReceivedCommandWith() does not simply compare 2 objects but compares the expected object with all received values, of which there can be 0, 1, or multiple. So if we received 2 calls and none of them match, we don't know to which we should compare in a "nice" output.

However:

  1. In most cases, like your example, we receive only a single call, so we could show the nice diff then (because 99% it is the call we expected and want to compare to), otherwise defaulting to the current behavior (listing all received calls).
  2. There is toHaveReceivedNthCommandWith() which compares expected value and single received value, so we can show the nice diff here as well.

This sounds like a nice improvement. If you are willing to do so, please create a PR.