Skip to content

Commit

Permalink
Add new matcher toHaveReceivedCommandExactlyOnceWith
Browse files Browse the repository at this point in the history
The new matcher can be used in similar way as
[toHaveBeenCalledExactlyOnceWith][1] of vitest but targeted against
AWS mocks

[1]: vitest-dev/vitest#6894
  • Loading branch information
stschulte committed Jan 17, 2025
1 parent 62b3657 commit 38bd57f
Show file tree
Hide file tree
Showing 6 changed files with 458 additions and 3 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- matcher `toHaveReceivedCommandExactlyOnceWith` can be used to verify there are
no additional calls

### Changed

- Update dependencies. This bumps `@vitest/expect` dependency to `^3.0.1`
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ You must register the new matchers explicity (think about putting this to a [set
},
});
to add the custom mat chers before each test run
to add the custom matchers before each test run
*/
import { expect } from "vitest";
import {
Expand All @@ -57,6 +57,8 @@ import {
toHaveReceivedLastCommandWith,
toReceiveAnyCommand,
toHaveReceivedAnyCommand,
toReceiveCommandExactlyOnceWith,
toHaveReceivedCommandExactlyOnceWith,
} from "aws-sdk-client-mock-vitest";

expect.extend({
Expand All @@ -74,6 +76,8 @@ expect.extend({
toHaveReceivedLastCommandWith,
toReceiveAnyCommand,
toHaveReceivedAnyCommand,
toReceiveCommandExactlyOnceWith,
toHaveReceivedCommandExactlyOnceWith,
});
```

Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ export type { CustomMatcher } from './matcher.js';
export {
toHaveReceivedAnyCommand,
toHaveReceivedCommand,
toHaveReceivedCommandExactlyOnceWith,
toHaveReceivedCommandOnce,
toHaveReceivedCommandTimes,
toHaveReceivedCommandWith,
toHaveReceivedLastCommandWith,
toHaveReceivedNthCommandWith,
toReceiveAnyCommand,
toReceiveCommand,
toReceiveCommandExactlyOnceWith,
toReceiveCommandOnce,
toReceiveCommandTimes,
toReceiveCommandWith,
Expand Down
40 changes: 38 additions & 2 deletions src/matcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { notNull, ordinalOf } from './utils.js';
interface AliasMatcher<R> {
toReceiveAnyCommand: BaseMatcher<R>['toHaveReceivedAnyCommand'];
toReceiveCommand: BaseMatcher<R>['toHaveReceivedCommand'];
toReceiveCommandExactlyOnceWith: BaseMatcher<R>['toHaveReceivedCommandExactlyOnceWith'];
toReceiveCommandOnce: BaseMatcher<R>['toHaveReceivedCommandOnce'];
toReceiveCommandTimes: BaseMatcher<R>['toHaveReceivedCommandTimes'];
toReceiveCommandWith: BaseMatcher<R>['toHaveReceivedCommandWith'];
Expand All @@ -39,6 +40,14 @@ interface BaseMatcher<R> {
command: AwsCommandConstructur<Input, Output>
): R;

toHaveReceivedCommandExactlyOnceWith<
Input extends object,
Output extends MetadataBearer,
>(
command: AwsCommandConstructur<Input, Output>,
input: Partial<Input>
): R;

toHaveReceivedCommandOnce<
Input extends object,
Output extends MetadataBearer,
Expand Down Expand Up @@ -209,9 +218,34 @@ function toHaveReceivedCommandWith(
};
};
const toReceiveCommandWith = toHaveReceivedCommandWith;
/*

*/
function toHaveReceivedCommandExactlyOnceWith(
this: MatcherState,
client: AwsStub<any, any, any>,
command: AwsCommandConstructur<any, any>,
input: Record<string, any>,
): ExpectationResult {
const { isNot, utils } = this;
const calls = client.commandCalls(command);

const hasCallWithArgs = calls.some(call =>
new ObjectContaining(input).asymmetricMatch(call.args[0].input),
);

const pass = calls.length === 1 && hasCallWithArgs;

return {
message: () => {
const message = isNot
? `expected "${command.name}" to not be called once with arguments: ${utils.printExpected(input)}`
: `expected "${command.name}" to be called once with arguments: ${utils.printExpected(input)}`;
return formatCalls(this, client, command, input, message);
},
pass,
};
};
const toReceiveCommandExactlyOnceWith = toHaveReceivedCommandExactlyOnceWith;

function toHaveReceivedNthCommandWith(
this: MatcherState,
client: AwsStub<any, any, any>,
Expand Down Expand Up @@ -289,13 +323,15 @@ export type { CustomMatcher };
export {
toHaveReceivedAnyCommand,
toHaveReceivedCommand,
toHaveReceivedCommandExactlyOnceWith,
toHaveReceivedCommandOnce,
toHaveReceivedCommandTimes,
toHaveReceivedCommandWith,
toHaveReceivedLastCommandWith,
toHaveReceivedNthCommandWith,
toReceiveAnyCommand,
toReceiveCommand,
toReceiveCommandExactlyOnceWith,
toReceiveCommandOnce,
toReceiveCommandTimes,
toReceiveCommandWith,
Expand Down
6 changes: 6 additions & 0 deletions tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ import { describe, expect, it } from 'vitest';
import {
toHaveReceivedAnyCommand,
toHaveReceivedCommand,
toHaveReceivedCommandExactlyOnceWith,
toHaveReceivedCommandOnce,
toHaveReceivedCommandTimes,
toHaveReceivedCommandWith,
toHaveReceivedLastCommandWith,
toHaveReceivedNthCommandWith,
toReceiveAnyCommand,
toReceiveCommand,
toReceiveCommandExactlyOnceWith,
toReceiveCommandOnce,
toReceiveCommandTimes,
toReceiveCommandWith,
Expand All @@ -22,13 +24,15 @@ import {
expect.extend({
toHaveReceivedAnyCommand,
toHaveReceivedCommand,
toHaveReceivedCommandExactlyOnceWith,
toHaveReceivedCommandOnce,
toHaveReceivedCommandTimes,
toHaveReceivedCommandWith,
toHaveReceivedLastCommandWith,
toHaveReceivedNthCommandWith,
toReceiveAnyCommand,
toReceiveCommand,
toReceiveCommandExactlyOnceWith,
toReceiveCommandOnce,
toReceiveCommandTimes,
toReceiveCommandWith,
Expand All @@ -52,6 +56,8 @@ describe('aws-sdk-client-mock-vitest', () => {
'toReceiveLastCommandWith',
'toReceiveNthCommandWith',
'toReceiveAnyCommand',
'toReceiveCommandExactlyOnceWith',
'toHaveReceivedCommandExactlyOnceWith',
])('extend matcher to extend with %s', (matcher) => {
expect(expect('something')).toHaveProperty(matcher);
});
Expand Down
Loading

0 comments on commit 38bd57f

Please sign in to comment.