- HapiJS Server with KnexJS DB Connection
- Jest Unit Tests
- Integration Tests via Docker
- E2E smoke test to check your deployment's health
- Swagger API Docs for existing routes
To initialize this repository in your Github org enabled with CI and CD:
Clone the repo git clone git@github.com:<YOUR_GITHUB_ORG>/<YOUR_GITHUB_REPO>.git
- node version >= 14.17 (run
node -v
to check)- If needed, nvm recommended for update (e.g.
nvm install 14.17.5
)
- If needed, nvm recommended for update (e.g.
- npm version >= 6.14 (run
npm -v
to check)- If you've updated node via nvm, npm will be updated as well
- postgres/psql (homebrew recommended)
- Docker for Mac (Only for running integration tests)
Create a .env
file at the root directory and copy the contents from .env.example
npm install
- Ensure postgres is running and you have a
postgres
user
- (If homebrew was used)
brew services start postgresql && /usr/local/opt/postgres/bin/createuser -s postgres
npm run db:setup
npm run dev
- API documentation at localhost:3000/documentation
Check your app's health including the local database connection at localhost:3000/health.
To create a timestamped migration file:
npm run migrate:make <name_of_migration>
To run migrations: npm run db:migrate
To roll back migrations: npm run db:rollback
To run all seeds: npm run db:seed
To run 1 seed: npm run db:seed -- --specific=000_your_seed_file.js
To reset database: npm run db:setup
- Make sure your .env file has values for
DATABASE_URL
.
To run all unit tests: npm test
To watch all unit tests: npm run test:watch
Start Docker Desktop
To setup test database: docker-compose up -d
To run integration tests: npm run test:integration
- Run
npm run test:integration -- -- <string match>
to run a single test
If you follow these steps and hit an error like error: password authentication failed for user "postgres"
, you might have an existing Docker container with the same name as the one used in this project. To get around this, try the following:
- Run
docker-compose down
to stop the test container - Run
docker system prune -a
to clean up your stopped containers. Note that this is a destructive operation; please heed the CLI's warning.
Integration tests are those that have been annotated with integration
via jest-runner-groups:
/**
* NameOfTest
* @group integration/<sub-group>
*/
Integration tests will clean the database after each test and have the following globals available:
container
-- set up exactly like the container used in developmentserver
-- set up exactly like the server used in development
Review src/_framework/configure[Server/Container].js
for details
This is our preferred strategy, but we recognize that there may be cases where we need to diverge.
- E2E test for Routes
- Happy path only
- 1 E2E test per route
- Unit test for Services
- Mock repositories using the Container
- Test for Boom errors when throwing error code statuses
- No unit test for Routes
- Testing the Service integration is already covered by the E2E test
- No integration test for Services
- Testing the Repository integration is already covered by the E2E test
- No tests for Repositories
- Testing the DB integration is already covered by the E2E test
All deployments are automated via CircleCI and DB migrations are automated via Heroku in a release
phase as specified in the Procfile
at the root of this repo.
Install Heroku CLI
Log into the Heroku CLI: heroku login
The heroku/deploy-via-git
job in CircleCI should provide the active logs when deploying but if you need to monitor them in more detail in Heroku:
View the status of the apps: heroku ps -a <HEROKU_APP_NAME>
View the current log: heroku logs --tail -a <HEROKU_APP_NAME>
View a list of releases: heroku releases -a <HEROKU_APP_NAME>
View the log of a specific release: heroku releases:output <v#> -a <HEROKU_APP_NAME>
- API documentation available when your server is running at localhost:3000/documentation
- We use hapi-swagger
- Out-of-the-box Swagger configurations live in
src/_framework/configureServer.js
- When setting up a new route, you must add the
tags: ['api']
entry to the route options in order for it to show up in the docs
- When setting up a new route, you must add the
- Organized by domain (e.g.
auth
,health
,users
). - Every test should be a sibling of the file that it's testing.
- Each domain folder will contain but is not limited to:
<domainName>Routes.js
<domainName>Routes.test.js
<DomainName>Service.js
<DomainName>Service.test.js
<DomainName>Repository.js
<DomainName>Repository.test.js
/models/<\*>.js
- Is instantiated in
index.js
- All Services and Repositories need to be registered in the Container
- Is used as an Inversion of Control Container, as well as a Dependency Locator
- Should be passed as a dependency to each Service
- Should be passed as an option to each Route
For example we register the db
on the container in src/_framework/configureContainer.js
. Using this form of dependency injection allows us to register a connection to our Knex Postgres library, while not coupling us to Knex in the rest of the code, and it also allows us to run our integration tests against a different Knex connection (and database) than our dev server, while elegantly reusing the same code.
- Should have access to the Container in order to locate Services
- Should orchestrate Services
- Should typically not have to call Repositories but may be required for simple use cases
- Contains methods that represents a Unit of Work
- Is responsible for committing or rolling back DB transactions
- Contains the business logic
- Is responsible for using and creating Domain Models
- Should have access to the Container in order to locate repositories
- Throws Boom errors to be bubbled up to the Route Layer
- Should orchestrate Repositories
- Should not call other services
- All errors will by default throw 500, apply specific Boom errors when necessary
- Contains methods that performs DB queries
- Should not transform the result from the database
- Should have access to the DB connection via the Container
- Should represent our domain
- Should be object-oriented
- Should be required directly by Services