event-driven-io / emmett

Emmett - a Node.js library taking your event-driven applications back to the future!
https://event-driven-io.github.io/emmett/
195 stars 19 forks source link

Add ability to setup integration tests through HTTP requests #26

Closed oskardudycz closed 8 months ago

oskardudycz commented 9 months ago

Currently, integration test data can be set up only by providing the initial set of events. That should be enough for most cases, but some people prefer to do it fully through the Web API, treating the application as a black box.

The entry point of that is located here: https://github.com/event-driven-io/emmett/blob/aa4413fceb90a6bcdba88823456ad8fba9842186/packages/emmett-expressjs/src/testing/apiSpecification.ts#L87.

It should be done in a similar way as with asserts but allowing to pass multiple setups. Setup should use the same structure as when passing the supertest setup https://github.com/event-driven-io/emmett/blob/aa4413fceb90a6bcdba88823456ad8fba9842186/packages/emmett-expressjs/src/testing/apiSpecification.ts#L89.

thiagomini commented 9 months ago

I'll be working on that in the next few days during my free time, do you want to assign that to me, @oskardudycz ?

oskardudycz commented 9 months ago

I'll be working on that in the next few days during my free time, do you want to assign that to me, @oskardudycz ?

Thank you a lot, you're assigned! :)

thiagomini commented 9 months ago

Hey, again! So, to wrap up our internal discussion on how to implement this, we decided to create a separate ApiSpecification for e2e tests. The reasoning behind this is that the way we test for e2e behavior differs from the integration tests.

We initially tried the following approach:

 it.only('should confirm (using request)', () => {
      return given((request) =>
        request
          .post(`/clients/${clientId}/shopping-carts/current/product-items`)
          .send(productItem),
      )
        .when((request) =>
          request.post(`/clients/${clientId}/shopping-carts/current/confirm`),
        )
        .then([
          expectResponse(204),
          expectNewEvents(shoppingCartId, [
            {
              type: 'ShoppingCartConfirmed',
              data: {
                shoppingCartId,
                confirmedAt: now,
              },
            },
          ]),
        ]);
    });

However, this test failed because we had two appended events: One for ProductItemAddedToShoppingCart and another for ShoppingCartConfirmed. We realized this is different from other tests, which could check only for the newly appended event since the initial ones, usually added by calling existingStream(streamId, events), were added to the store using setup(), which doesn't count for appended events.

Our solution will consist of a slightly different API and testing mindset: it should only call endpoints and potentially check for responses, seeing the API as a black-box: