m-radzikowski / aws-sdk-client-mock

AWS JavaScript SDK v3 mocks for easy unit testing. πŸ–‹οΈ Typed πŸ”¬ Tested πŸ“„ Documented πŸ› οΈ Maintained
https://m-radzikowski.github.io/aws-sdk-client-mock/
MIT License
799 stars 39 forks source link

Create matchers for `vitest` #139

Open ThomasAribart opened 1 year ago

ThomasAribart commented 1 year ago

Hello and thanks for this great lib πŸ™Œ

On my project we went from jest to vitest, mainly for performances. Sadly, we lost the toHaveReceivedCommand matchers in the process πŸ₯²

Would be awesome to have them for vitest as well! Maybe it was the aim of separating jest matchers in another lib in the first place ?

See https://vitest.dev/guide/extending-matchers.html

Cheers !

kldavis4 commented 1 year ago

I found this in the vitest docs: https://vitest.dev/guide/features.html#chai-and-jest-expect-compatibility

When I set test.globals: true in vite.config.js, the aws-sdk-client-mock-jest matchers seem to work.

m-radzikowski commented 1 year ago

Hey, sorry for the late reply. Thank you @kldavis4 for finding and sharing the way to make aws-sdk-client-mock-jest work with vitest. I will add that to the README.

While I see a raising popularity of vitest, I'm not using it right now myself. If anyone wants to add vitest matchers, or, even better, adjust current matchers so they can be use in vitest natively (if possible) - feel free to open a PR.

colesiegel commented 1 year ago

It still doesn't work for me, even with test.globals set to true.

expect(ddbMock).toHaveReceivedCommandWith(QueryCommand, {});

Property 'toHaveReceivedCommandWith' does not exist on type 'Assertion<AwsStub<ServiceInputTypes, ServiceOutputTypes>>'.ts(2339)

import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    reporters: ['junit', 'default'],
    outputFile: './.vitest/results.xml',
    coverage: {
      // include coverage even if no tests exist
      all: true,
      include: ['src/*'],
      reportsDirectory: './.vitest/coverage',
    },
    setupFiles: './src/setupTests.ts',
    // [https://github.com/m-radzikowski/aws-sdk-client-mock/issues/139]
    globals: true,
  },
});
mbtts commented 1 year ago

This is really excellent test utility, thank you to all who have contributed so far.

On this point from the README:

https://github.com/m-radzikowski/aws-sdk-client-mock/blob/c6896a392987cd3eefcfeea800bd9599464bb6fc/README.md?plain=1#L513-L514

One problem here is the Vitest β€œJest” matcher utils are a much smaller subset of the actual Jest matcher utils (which also rely on other Jest packages like jest-diff).

βœ… If the expectation passes there is no problem, the matchers work as expected with vitest.

❌ However if the expectations then printDiffOrStringify is called:

https://github.com/m-radzikowski/aws-sdk-client-mock/blob/c6896a392987cd3eefcfeea800bd9599464bb6fc/packages/aws-sdk-client-mock-jest/src/jestMatchers.ts#L426

At this point Vitest runner will bail:

TypeError: this.utils.printDiffOrStringify is not a function

Happy to stick my hand up to make a contribution.

My thoughts are there are a few possibilities:

  1. Avoid: Feature-sniff and use an alternative function/output when used in a non-Jest environment/Jest-like environment
  2. Import: jest-utils could become a dependency (and its implementation of printDiffOrStringify used verbatim)
  3. Delegate: Approach the Vitest maintainers about providing the same functionality/API (I could not see anything planned/open issue, but might have overlooked something)

In the very short term I think either the limitations should be documented -or- Vitest not be officially documented as supported for just the matchers.


@colesiegel On the typings question, I hope you got this resolved? Sharing my configuration in case it helps:

vitest.config.ts:

import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    globals: true,
    mockReset: true,
    setupFiles: ['./awsSdkClientMatchers.ts'],
  },
});

awsSdkClientMatchers.ts:

import 'aws-sdk-client-mock-jest';

tsconfig.json:

{
  "extends": "@tsconfig/node18/tsconfig",
  "compilerOptions": {
    "allowJs": true,
    "lib": ["ESNext"],
    "module": "NodeNext",
    "moduleResolution": "nodenext",
    "noEmit": true,
    "types": ["vitest/globals"]
  }
}
douglasg14b commented 1 month ago

@m-radzikowski Can this be re-opened? Vitest matchers don't yet exist for this project, and only kind-of work as a side effect of Vitest being very diligent about being Jest-compatable.

Dedicated Vitest matchers would go a long ways, keeping the issue open may help with fishing for a contribution πŸ€”

m-radzikowski commented 1 month ago

This will be solved when #231 is merged.

EHadoux commented 1 day ago

It still doesn't work for me, even with test.globals set to true.

expect(ddbMock).toHaveReceivedCommandWith(QueryCommand, {});

Property 'toHaveReceivedCommandWith' does not exist on type 'Assertion<AwsStub<ServiceInputTypes, ServiceOutputTypes>>'.ts(2339)

I still see this with 4.1.0. It works when running the tests but TS is not happy in vscode. Any chance someone knows how to fix it?

Using

import { DynamoDBDocumentClient, UpdateCommand } from '@aws-sdk/lib-dynamodb';
import { mockClient } from 'aws-sdk-client-mock';
import 'aws-sdk-client-mock-jest/vitest';
import { beforeEach, describe, expect, it } from 'vitest';

describe('something', () => {
  const ddbMock = mockClient(DynamoDBDocumentClient);

  beforeEach(() => {
    ddbMock.reset();
  });

  it('something', async () => {
    expect(ddbMock).toHaveReceivedCommandWith(UpdateCommand, {});
  });
});