Skip to content

Commit

Permalink
Added easier possibility to check both api response and events in API…
Browse files Browse the repository at this point in the history
… integrationt ests
  • Loading branch information
oskardudycz committed Feb 29, 2024
1 parent bcff883 commit aa4413f
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 32 deletions.
3 changes: 2 additions & 1 deletion docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,8 @@ We recommend providing different web app configurations for different endpoints'
That's what we did in our case. We've set up our Shopping Carts API and injected external dependencies:

- event store to store and retrieve events,
- The `getUnitPrice` method represents a call to an external service to get the price of a product added to the shopping cart.
- The `getUnitPrice` method represents a call to an external service to get the price of a product added to the shopping cart,
- We're also passing the current date generator. Embracing this non-deterministic dependency will be helpful for integration testing later on.

That clearly explains what dependencies this API needs, and by reading the file, you can understand what your application technology needs. That should cut the onboarding time for new people grasping our system setup.

Expand Down
30 changes: 15 additions & 15 deletions docs/snippets/gettingStarted/webApi/apiBDD.int.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-floating-promises */
import {
getInMemoryEventStore,
Expand All @@ -10,6 +8,7 @@ import {
existingStream,
expectError,
expectNewEvents,
expectResponse,
getApplication,
} from '@event-driven-io/emmett-expressjs';
import { beforeEach, describe, it } from 'node:test';
Expand All @@ -22,10 +21,13 @@ const getUnitPrice = (_productId: string) => {
};

describe('ShoppingCart', () => {
let clientId: string;
let shoppingCartId: string;
beforeEach(() => {
clientId = uuid();
shoppingCartId = `shopping_cart:${clientId}:current`;
});

describe('When empty', () => {
it('should add product item', () => {
return given()
Expand Down Expand Up @@ -67,6 +69,7 @@ describe('ShoppingCart', () => {
request.post(`/clients/${clientId}/shopping-carts/current/confirm`),
)
.then([
expectResponse(204),
expectNewEvents(shoppingCartId, [
{
type: 'ShoppingCartConfirmed',
Expand Down Expand Up @@ -114,20 +117,7 @@ describe('ShoppingCart', () => {
});
});

let clientId: string;
let shoppingCartId: string;

const getRandomProduct = (): PricedProductItem => {
return {
productId: uuid(),
unitPrice: 100,
quantity: Math.random() * 10,
};
};
const oldTime = new Date();

const productItem = getRandomProduct();

const now = new Date();

const given = ApiSpecification.for<ShoppingCartEvent>(
Expand All @@ -137,4 +127,14 @@ describe('ShoppingCart', () => {
apis: [shoppingCartApi(eventStore, getUnitPrice, () => now)],
}),
);

const getRandomProduct = (): PricedProductItem => {
return {
productId: uuid(),
unitPrice: 100,
quantity: Math.random() * 10,
};
};

const productItem = getRandomProduct();
});
3 changes: 0 additions & 3 deletions docs/snippets/gettingStarted/webApi/simpleApi.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
import {
assertNotEmptyString,
assertPositiveNumber,
Expand Down
28 changes: 15 additions & 13 deletions packages/emmett-expressjs/src/testing/apiSpecification.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,12 @@ export const existingStream = <EventType extends Event = Event>(
/////////// Asserts
////////////////////////////////

export type ResponseAssert = (response: Response) => boolean | void;

export type ApiSpecificationAssert<EventType extends Event = Event> =
| TestEventStream<EventType>[]
| ((response: Response) => boolean | void)
| {
events: TestEventStream<EventType>[];
responseMatches: (response: Response) => boolean;
};
| ResponseAssert
| [ResponseAssert, ...TestEventStream<EventType>[]];

export const expect = <EventType extends Event = Event>(
streamId: string,
Expand Down Expand Up @@ -128,17 +127,20 @@ export const ApiSpecification = {

if (succeded === false) assert.fail();
} else if (Array.isArray(verify)) {
const [first, ...rest] = verify;

if (typeof first === 'function') {
const succeded = first(response);

if (succeded === false) assert.fail();
}

const events = typeof first === 'function' ? rest : verify;

assertMatches(
Array.from(eventStore.appendedEvents.values()),
verify,
);
} else {
assert.ok(verify.responseMatches(response));
assertMatches(
Array.from(eventStore.appendedEvents.values()),
givenStreams,
events,
);
return;
}
},
};
Expand Down

0 comments on commit aa4413f

Please sign in to comment.