Skip to content

Commit

Permalink
Run specs with docker compose
Browse files Browse the repository at this point in the history
  • Loading branch information
sylvain-morin authored and sylvain-morin committed Oct 16, 2023
1 parent e8adcea commit 3f4c407
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 11 deletions.
18 changes: 17 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
FROM node:16
# Platform should be forced to amd64
# because node-mapnik is not available in arm64
FROM --platform=linux/amd64 node:16 as base

ENV NODE_ENV=development

Expand All @@ -10,6 +12,20 @@ COPY config_example.js config.js

RUN npm install

FROM base as test

ENV NODE_ENV=test

RUN apt-get update -qq && apt-get install -y postgresql-client-11

COPY . .

CMD [ "npm", "run", "coverage" ]

FROM base as development

ENV NODE_ENV=development

COPY . .

EXPOSE 4000
Expand Down
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,29 @@ Filter by pattern: `NODE_ENV=test ./node_modules/mocha/bin/_mocha --recursive --

You can also add `.only` to a `describe` or `it` call to only run that test when you run `npm test`, e.g. `it.only( "should only run this test" )`.

# Running Tests with Docker

You can run the tests with Docker Compose.
All required services will be started by the `docker-compose.test.yml` compose file:

```
docker compose -f docker-compose.test.yml up -d
```

You can follow the tests execution in the logs:

```
docker logs -f api-test
```

The first time you run the compose file, a local docker image for the API service will be automatically built, from you local GIT checkout. But if later you do some code changes, or update your GIT checkout, you need to re-build the docker image with:

```
docker compose -f docker-compose.test.yml build
```

This compose build is using the `test` target of the Dockerfile.

# ESLint

Please run ESLint to check for syntax formatting errors. To run ESLint, run: `npm run eslint`. Please address any syntax errors before submitting pull requests. ESLint will also run automatically via Github Actions on submitted pull requests along with tests.
Expand Down
8 changes: 4 additions & 4 deletions docker-compose.test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ services:
api-test:
container_name: api-test
build: .
build:
context: .
dockerfile: Dockerfile
target: test
environment:
NODE_ENV: test
INAT_DB_HOST: pg
Expand All @@ -56,11 +59,8 @@ services:
INAT_WEB_HOST: host.docker.internal
INAT_DB_NAME: inaturalist_test
INAT_ES_INDEX_PREFIX: test
DB_ALREADY_INITIALIZED: true
ports:
- 4000:4000
command:
/bin/sh -c "npm install ; npm run coverage"
extra_hosts:
- "host.docker.internal:host-gateway"

Expand Down
12 changes: 12 additions & 0 deletions lib/test_helper.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-console */
const fs = require( "fs" );
const _ = require( "lodash" );
const timersPromises = require( "timers/promises" );
Expand Down Expand Up @@ -46,6 +47,15 @@ testHelper.waitForES = async numberOfAttempts => {
return testHelper.waitForES( numberOfAttempts );
};

testHelper.closePGConnection = async ( ) => {
await pgClient.connection.end( );
delete pgClient.connection;
};

testHelper.reconnectPGConnection = async ( ) => {
await pgClient.connect( );
};

testHelper.forEachIndex = async action => {
if ( process.env.NODE_ENV !== "test" ) { return; }
const settings = JSON.parse( fs.readFileSync( "schema/settings.js" ) );
Expand Down Expand Up @@ -148,6 +158,8 @@ testHelper.testInatJSNoPreload = async ( controller, endpoint, method, done ) =>
module.exports = {
waitForPG: testHelper.waitForPG,
waitForES: testHelper.waitForES,
closePGConnection: testHelper.closePGConnection,
reconnectPGConnection: testHelper.reconnectPGConnection,
createIndices: testHelper.createIndices,
deleteIndices: testHelper.deleteIndices,
loadElasticsearchFixtures: testHelper.loadElasticsearchFixtures,
Expand Down
17 changes: 11 additions & 6 deletions test/hooks.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-console */
const { expect } = require( "chai" );
const { execSync } = require( "child_process" );
const inaturalistjs = require( "inaturalistjs" );
Expand All @@ -6,7 +7,7 @@ const testHelper = require( "../lib/test_helper" );
const Taxon = require( "../lib/models/taxon" );
const config = require( "../config" );

function initializeDb() {
async function initializeDb() {
// For tests, we want to make absolutely sure the test database is clean and
// new, and we need to make sure that happens before we try to connect to it,
// which happens every time we require pg_client, which happens inside of
Expand All @@ -18,23 +19,25 @@ function initializeDb() {
${config.database.user ? `PGUSER=${config.database.user}` : ""} \
${config.database.password ? `PGPASSWORD=${config.database.password}` : ""}`;

// Close connection before dropping DB
await testHelper.closePGConnection( );

console.log( "Dropping existing test database" );
execSync( `${testDbConnectionVar} dropdb --if-exists ${dbname}`, { stdio: [0, 1, 2] } );
console.log( "Creating test database" );
execSync( `${testDbConnectionVar} createdb -O ${config.database.user} ${dbname}`, { stdio: [0, 1, 2] } );
console.log( "Loading test database schema" );
execSync( `${testDbConnectionVar} psql -q -f schema/database.sql -d ${dbname}`, { stdio: [0, 1, 2] } );

// Reconnecto to DB
await testHelper.reconnectPGConnection( );
}

exports.mochaGlobalSetup = async function () {
expect( process.env.NODE_ENV ).to.eq( "test" );

console.log( "\n\nINITIALIZING TEST ENVIRONMENT\n\n" );

if ( !process.env.DB_ALREADY_INITIALIZED ) {
initializeDb( );
}

// Wait for Postgres
console.log( "Waiting for Postgres..." );
await testHelper.waitForPG( 100 );
Expand All @@ -43,6 +46,8 @@ exports.mochaGlobalSetup = async function () {
console.log( "Waiting for ElasticSearch..." );
await testHelper.waitForES( 100 );

initializeDb( );

console.log( "Creating ES indices" );
await testHelper.createIndices( );
console.log( "Loading ES fixtures" );
Expand All @@ -57,7 +62,7 @@ exports.mochaGlobalSetup = async function () {

exports.mochaHooks = {
async beforeAll( ) {
this.timeout( 20000 );
this.timeout( 60000 );
this.app = await app( );
},
async afterAll( ) {
Expand Down

0 comments on commit 3f4c407

Please sign in to comment.