Skip to content

Commit

Permalink
feat: request match by body (#12) (#108)
Browse files Browse the repository at this point in the history
### Features
- [#zimic] Added support to restrict request trackers by body.

```ts
const creationTracker = authInterceptor
  .post('/users')
  .with({
    body: creationPayload,
  })
  .respond((request) => {
    const user: User = {
      id: crypto.randomUUID(),
      name: request.body.name,
      email: request.body.email,
    };

    return {
      status: 201,
      body: user,
    };
  });

const response = await createUser(creationPayload);
expect(response.status).toBe(201);
```

### Refactoring
- [#zimic] Simplified request and response body schemas.
- Unified `HttpInterceptorSchema.RequestBody` and
`HttpInterceptorSchema.ResponseBody` into `HttpInterceptorSchema.Body`,
as the previous `RequestBody` and `ResponseBody` had the same semantics.
- [#zimic] Improved HTTP interceptor test scenarios, following
real-world cases more closely for each method.
Closes #12.
  • Loading branch information
diego-aquino authored Mar 17, 2024
1 parent 779fb6f commit 9e95b20
Show file tree
Hide file tree
Showing 19 changed files with 1,548 additions and 644 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,18 @@ describe('Exports', () => {
expectTypeOf<HttpInterceptorResponseSchemaStatusCode<never>>().not.toBeAny();
expectTypeOf<HttpInterceptorMethodSchema>().not.toBeAny();
expectTypeOf<HttpInterceptorPathSchema>().not.toBeAny();

expectTypeOf<HttpInterceptorSchema>().not.toBeAny();
expectTypeOf<HttpInterceptorSchema.Root<never>>().not.toBeAny();
expectTypeOf<HttpInterceptorSchema.Path<never>>().not.toBeAny();
expectTypeOf<HttpInterceptorSchema.Method<never>>().not.toBeAny();
expectTypeOf<HttpInterceptorSchema.Request<never>>().not.toBeAny();
expectTypeOf<HttpInterceptorSchema.Response<never>>().not.toBeAny();
expectTypeOf<HttpInterceptorSchema.ResponseByStatusCode<never>>().not.toBeAny();
expectTypeOf<HttpInterceptorSchema.Headers<never>>().not.toBeAny();
expectTypeOf<HttpInterceptorSchema.SearchParams<never>>().not.toBeAny();
expectTypeOf<HttpInterceptorSchema.Body<never>>().not.toBeAny();

expectTypeOf<HttpInterceptorSchemaMethod<never>>().not.toBeAny();
expectTypeOf<LiteralHttpInterceptorSchemaPath<never, never>>().not.toBeAny();
expectTypeOf<NonLiteralHttpInterceptorSchemaPath<never, never>>().not.toBeAny();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ function declareDefaultClientTests(options: ClientTestDeclarationOptions) {
.post('/users')
.with({
headers: { 'content-type': 'application/json' },
body: creationPayload,
})
.respond((request) => {
expect(request.headers.get('content-type')).toBe('application/json');
Expand Down Expand Up @@ -280,10 +281,15 @@ function declareDefaultClientTests(options: ClientTestDeclarationOptions) {
code: 'validation_error',
message: 'Invalid payload',
};
const creationTracker = authInterceptor.post('/users').respond({
status: 400,
body: validationError,
});
const creationTracker = authInterceptor
.post('/users')
.with({
body: invalidPayload,
})
.respond({
status: 400,
body: validationError,
});

const response = await createUser(invalidPayload);
expect(response.status).toBe(400);
Expand Down Expand Up @@ -318,10 +324,15 @@ function declareDefaultClientTests(options: ClientTestDeclarationOptions) {
code: 'conflict',
message: 'User already exists',
};
const creationTracker = authInterceptor.post('/users').respond({
status: 409,
body: conflictError,
});
const creationTracker = authInterceptor
.post('/users')
.with({
body: conflictingPayload,
})
.respond({
status: 409,
body: conflictError,
});

const response = await createUser(conflictingPayload);
expect(response.status).toBe(409);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function declareSharedHttpInterceptorTests(options: SharedHttpInterceptor
});

describe('Methods', () => {
const methodTestFactories: Record<HttpInterceptorMethod, () => void> = {
const methodTestFactories: Record<HttpInterceptorMethod, () => Promise<void> | void> = {
GET: declareGetHttpInterceptorTests.bind(null, options),
POST: declarePostHttpInterceptorTests.bind(null, options),
PUT: declarePutHttpInterceptorTests.bind(null, options),
Expand All @@ -38,8 +38,8 @@ export function declareSharedHttpInterceptorTests(options: SharedHttpInterceptor
};

for (const [method, methodTestFactory] of Object.entries(methodTestFactories)) {
describe(method, () => {
methodTestFactory();
describe(method, async () => {
await methodTestFactory();
});
}
});
Expand Down
Loading

0 comments on commit 9e95b20

Please sign in to comment.