From 3422ba60f9d0ddd6d8dffb3857807152909a0843 Mon Sep 17 00:00:00 2001 From: kao Date: Thu, 15 Jun 2023 10:31:05 -0700 Subject: [PATCH] Add more documentation --- README.md | 5 +++++ documentation/layers.md | 26 ++++++++++++++++++++++++++ documentation/testing.md | 22 ++++++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 documentation/layers.md create mode 100644 documentation/testing.md diff --git a/README.md b/README.md index 61e414ac..c623bbd8 100644 --- a/README.md +++ b/README.md @@ -96,6 +96,11 @@ yarn seed-db # May take a few minutes to download a large database file yarn serve ``` +#### Navigating the codebase +These links explain the structure and key abstractions of our codebase. It's a good place to start before you go spelunking in the code. + - [Layers](documentation/layers.md). + - [Testing](documentation/testing.md). + ### Troubleshooting - Fix "permissions on /opt/keyfile/keyfile are too open" error diff --git a/documentation/layers.md b/documentation/layers.md new file mode 100644 index 00000000..e09817f6 --- /dev/null +++ b/documentation/layers.md @@ -0,0 +1,26 @@ +# Layers + +## Overview +One way to think of our backend is comprising three layers wrapping the raw data sitting in Mongo DB. +1. GraphQL +2. Datasources +3. Models + +Incoming data (API requests) pass through GraphQL > Datasource > Model and then the resulting data exit in reverse order from Model > Datasource > GraphQL. + +When you change our data model, eg adding a new field to a climb object, you should expect to update each of the three layes as well. + +## GraphQL +The outermost GraphQL layer that receives API calls. Our big integration tests (see [Testing](documentation/testing.md)) call this layer. + +Code is in `src/graphql`. + +## Datasources +The middle Mongoose datastore objects that expose commands to the GraphQL resolvers. Mongoose is our MongoDB NodeJS ORM. Our small integration tests test this layer down. + +Code is in `src/model`. + +## Models +The inner Mongoose models/schemas that represent how data is stored in the MongoDB. + +Code is in `src/db/` \ No newline at end of file diff --git a/documentation/testing.md b/documentation/testing.md new file mode 100644 index 00000000..d9405a7a --- /dev/null +++ b/documentation/testing.md @@ -0,0 +1,22 @@ +# Testing +*Updated 2023-06-15* + +## Overview +There are currently two broad classes of tests in this repo: Big integration tests and small ones. Both sets are integration tests because they validate long chains of functionality as opposed to single classes or functions (unit tests). + +The big set is called "big" because it is truly end-to-end. It posts GraphQL queries and checks their output, which is literally what the API does in production. The small set skips the GraphQL layer (you might want to read more about layers [here](documentation/layers.md)) and instead calls datasource functions directly. + +## Big Integration Tests +These tests mock up a GraphQL backend, and make HTTP calls to it. Since these tests are so realistic, they are immensely protective, illustrative and confidence-building. Open-tacos developers can cut and paste the GraphQL queries in these tests and use them to build the frontend. + +These tests are stored in `/src/__tests__/`. The setup code is in `/src/utils/testUtils.ts`. Note how most of the code is oriented around setting up and tearing down a GraphQL server and an in-memory Mongo DB. + +We rely on `mongo-memory-server` (a node package) for the in-memory Mongo DB. By running it in memory, it is lightweight and easily setup during `beforeAll`. Early on, we were hampered by the fact that the standard Mongo server that `mongo-memory-server` offers doesn't support Mongo transactions, which we use extensively. This is why we wrote small integration tests which rely on a local instance of MongoDB. However, in 2021, the package started to offer an in-memory replset which does support Mongo transactions. From then on, we've been able to write big integration tests which set up a replset which supports everything we need to do. + + +## Small Integration Tests +These essentially test datasource functions. Eg. the key line in such a test could be `await users.createOrUpdateUserProfile(updater, input)`([Source](src/model/__tests__/UserDataSource.ts)). This tests the `createOrUpdateUserProfile` function of the `user` datasource. Datasources sit one layer below the GraphQL layer (another plug to read [Layers]((documentation/layers.md))). In `src/graphql/resolvers.ts`, you can see how the GraphQL layer calls datasource functions to resolve entities in the queries. + +Other than their inability to test how the GraphQL layer resolves queries, the main shortcoming of these tests are their poor portability. To use them, you need to set up a Mongo DB locally for the tests to read and write from. This is why the the main [README](README.md) page gets developers to spin up a Docker instance and edit `/etc/hosts` mongod mappings. + +In general, we should phase these out in favor of big integration tests. In case you need to debug them or, god forbid, write new ones, they reside in `/src/model/__tests__/`.