Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
357456a
chore: pg_dump db sql
QuaidBartolomei Feb 25, 2022
9777575
ci(pr): add e2e tests to workflow
QuaidBartolomei Feb 25, 2022
49e2fc3
ci(pr): set docker postgis image version
QuaidBartolomei Feb 25, 2022
8b2dc2e
ci(pr): ignore npm install scripts
QuaidBartolomei Feb 25, 2022
1e6a685
chore: add user to db dump
QuaidBartolomei Feb 25, 2022
c0acfd7
build(test): create @mocks path alias
QuaidBartolomei Feb 25, 2022
c5f19f9
refactor: create TableNames enum
QuaidBartolomei Feb 25, 2022
9d39e72
test(wip): trees.spec uses mock data
QuaidBartolomei Feb 25, 2022
cef1499
ci(wip): only test trees.spec
QuaidBartolomei Feb 26, 2022
0ab6273
test(wip): skip failing tests
QuaidBartolomei Feb 26, 2022
7bf9ace
ci(pr): seed db before tests
QuaidBartolomei Feb 26, 2022
8d95a5d
test(setup): conditionally seed db before testing
QuaidBartolomei Feb 26, 2022
c229ad0
test(wallet): use seed data
QuaidBartolomei Feb 26, 2022
86e9283
chore: dump wallet schema
QuaidBartolomei Mar 1, 2022
e6e295a
ci(pr): load wallet schema sql
QuaidBartolomei Mar 1, 2022
44166ec
ci(pr): sql assigns tables to user 'postgres'
QuaidBartolomei Mar 1, 2022
b74454c
chore: add uuid extension to db.sql
QuaidBartolomei Mar 1, 2022
92bc1e8
refactor: add table names to enum
QuaidBartolomei Mar 1, 2022
9cdeb4b
chore: create example data
QuaidBartolomei Mar 1, 2022
c91b394
test(setup): seed table data
QuaidBartolomei Mar 1, 2022
3e1b302
chore(fixup): create example data
QuaidBartolomei Mar 1, 2022
43d318d
fix: add grower_account_uuid to public.planter table
QuaidBartolomei Mar 1, 2022
649587a
chore(fixup): create example data
QuaidBartolomei Mar 1, 2022
2d8c526
test(seed): seed org before planter to fulfill fk restraint
QuaidBartolomei Mar 1, 2022
71c7d0e
chore(fixup): create example data
QuaidBartolomei Mar 1, 2022
e73b3f2
ci: run e2e tests
QuaidBartolomei Mar 1, 2022
e0d3a24
test(species): use seed data
QuaidBartolomei Mar 1, 2022
19836e0
ci: always run tests
QuaidBartolomei Mar 1, 2022
aecd360
test(seed): update seed data
QuaidBartolomei Mar 1, 2022
5119e05
test: use seed data
QuaidBartolomei Mar 1, 2022
ac001df
test(organization): assert seed data
QuaidBartolomei Mar 3, 2022
1e2169b
test(planter): use seed data
QuaidBartolomei Mar 3, 2022
596d25a
test(tree): get tree by org id uses seed data
QuaidBartolomei Mar 3, 2022
ace6f41
test(token): use seed data
QuaidBartolomei Mar 5, 2022
e63d6e6
ci(pr): run token e2e tests
QuaidBartolomei Mar 5, 2022
8d2ae1c
refactor(organizations.spec): rename var
QuaidBartolomei Mar 5, 2022
aafcd83
test(seed): add country to region_type
QuaidBartolomei Mar 5, 2022
7b72b92
chore: move schema sql to database/schemas
QuaidBartolomei Mar 5, 2022
2bd7c9e
refactor: seed wallet data with .insert
QuaidBartolomei Mar 5, 2022
e2cfde3
build(package): add tsconfig-paths dev dep
QuaidBartolomei Mar 6, 2022
1689a12
refactor: move seed data to database/seeds/data
QuaidBartolomei Mar 6, 2022
ed97810
ci(pr): consolidate integration tests
QuaidBartolomei Mar 6, 2022
e98cada
refactor: test setup uses region_type.json
QuaidBartolomei Mar 6, 2022
479a15d
refactor: table name and schema name enums
QuaidBartolomei Mar 6, 2022
1e0244a
Merge remote-tracking branch 'upstream/main' into ci/pr-workflow-inte…
QuaidBartolomei Mar 20, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 36 additions & 3 deletions .github/workflows/pull-request-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,30 @@ on:
- main
env:
project-directory: ./
DATABASE_URL: ${{ secrets.DATABASE_URL }}
DATABASE_URL: postgresql://postgres:postgres@postgres/postgres

jobs:
test:
name: Run all tests
runs-on: ubuntu-latest
container: node:16.12.0

# Service containers to run with `container-job`
services:
# Label used to access the service container
postgres:
# Docker Hub image
image: postgis/postgis:11-2.5-alpine
# Provide the password for postgres
env:
POSTGRES_PASSWORD: postgres
# Set health checks to wait until postgres has started
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5

steps:
- uses: actions/checkout@v2
- name: Use Node.js 16.x
Expand All @@ -23,13 +41,28 @@ jobs:
node-version: '16.x'

- name: npm clean install
run: npm ci
run: npm ci --ignore-scripts

- name: Typescript compiles
run: npm run build

- name: Eslint
run: npm run lint

- name: run tests
- name: install psql
run: |
apt-get update
apt-get install --yes --no-install-recommends postgresql-client

- name: Prepare DB
run: |
psql postgresql://postgres:postgres@postgres/postgres < database/schemas/public.sql
psql postgresql://postgres:postgres@postgres/postgres < database/schemas/wallet.sql

- name: Unit Tests
run: npm test

- name: Integration Tests
run: npm run test-e2e
env:
SEED: true
31 changes: 30 additions & 1 deletion .jest/globalSetup.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,32 @@
import * as dotenv from 'dotenv';
dotenv.config();
export default function globalSetup() {}
import 'tsconfig-paths/register';
import tree from '@seeds/data/tree.json';
import wallet from '@seeds/data/wallet.json';
import species from '@seeds/data/species.json';
import planter from '@seeds/data/planter.json';
import country from '@seeds/data/country.json';
import organization from '@seeds/data/organization.json';
import token from '@seeds/data/token.json';
import regionType from '@seeds/data/region_type.json';
import knex, {
PublicTables,
SchemaNames,
WalletTables,
} from 'infra/database/knex';

export default async function globalSetup() {
if (process.env.SEED === 'true') {
await knex(PublicTables.Trees).insert(tree);
await knex(WalletTables.Wallet)
.withSchema(SchemaNames.Wallet)
.insert(wallet);
await knex(WalletTables.Token).withSchema(SchemaNames.Wallet).insert(token);
await knex(PublicTables.Species).insert(species);
await knex(PublicTables.Organizations).insert(organization);
await knex(PublicTables.Planters).insert(planter);
await knex(PublicTables.RegionType).insert(regionType);
await knex(PublicTables.Countries).insert(country);
}
knex.destroy();
}
108 changes: 61 additions & 47 deletions __tests__/e2e/countries.spec.ts
Original file line number Diff line number Diff line change
@@ -1,61 +1,75 @@
import exampleCountry from '@seeds/data/country.json';
import supertest from 'supertest';
import app from '../../server/app';
import app from 'app';

describe('', () => {
it('countries/6632544', async () => {
const response = await supertest(app).get('/countries/6632544');
expect(response.status).toBe(200);
expect(response.body).toMatchObject({
id: 6632544,
name: 'China',
});
it('countries/6632544', async () => {
const response = await supertest(app).get(`/countries/${exampleCountry.id}`);
expect(response.status).toBe(200);
expect(response.body).toMatchObject({
id: 6632544,
name: 'China',
});
});

// 103.819073145824,36.5617653792527
it('countries?lat=36.5617653792527&lon=103.819073145824', async () => {
const response = await supertest(app).get(
'/countries?lat=36.5617653792527&lon=103.819073145824',
);
// 103.819073145824,36.5617653792527
it('countries?lat=36.5617653792527&lon=103.819073145824', async () => {
const response = await supertest(app).get(
'/countries?lat=36.5617653792527&lon=103.819073145824',
);
expect(response.status).toBe(200);
expect(response.body.countries[0]).toMatchObject({
id: 6632544,
name: 'China',
});
});

it.skip(
'countries/leaderboard',
async () => {
const response = await supertest(app).get('/countries/leaderboard');
expect(response.status).toBe(200);
expect(response.body.countries[0]).toMatchObject({
id: 6632544,
name: 'China',
id: expect.any(Number),
name: expect.any(String),
planted: expect.any(String),
centroid: expect.stringMatching(/coordinates/),
});
},
1000 * 60,
);

it('countries/v2/6632544', async () => {
const response = await supertest(app).get('/countries/v2/6632544');
expect(response.status).toBe(200);
expect(response.body).toMatchObject({
id: 6632544,
name: 'China',
});
});

it('countries/v2/6632544', async () => {
const response = await supertest(app).get('/countries/v2/6632544');
expect(response.status).toBe(200);
expect(response.body).toMatchObject({
id: 6632544,
name: 'China',
});
// 103.819073145824,36.5617653792527
it('countries/v2/?lat=36.5617653792527&lon=103.819073145824', async () => {
const response = await supertest(app).get(
'/countries/v2/?lat=36.5617653792527&lon=103.819073145824',
);
expect(response.status).toBe(200);
expect(response.body.countries[0]).toMatchObject({
id: 6632544,
name: 'China',
});
});

// 103.819073145824,36.5617653792527
it('countries/v2/?lat=36.5617653792527&lon=103.819073145824', async () => {
const response = await supertest(app).get(
'/countries/v2/?lat=36.5617653792527&lon=103.819073145824',
);
it(
'countries/leaderboard',
async () => {
const response = await supertest(app).get('/countries/leaderboard');
expect(response.status).toBe(200);
expect(response.body.countries[0]).toMatchObject({
id: 6632544,
name: 'China',
id: expect.any(Number),
name: expect.any(String),
planted: expect.any(String),
centroid: expect.stringMatching(/coordinates/),
});
});

it(
'countries/leaderboard',
async () => {
const response = await supertest(app).get('/countries/leaderboard');
expect(response.status).toBe(200);
expect(response.body.countries[0]).toMatchObject({
id: expect.any(Number),
name: expect.any(String),
planted: expect.any(String),
centroid: expect.stringMatching(/coordinates/),
});
},
1000 * 60,
);
});
},
1000 * 60,
);
58 changes: 30 additions & 28 deletions __tests__/e2e/organizations.spec.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,39 @@
import exampleOrganization from '@seeds/data/organization.json';
import examplePlanter from '@seeds/data/planter.json';
import supertest from 'supertest';
import app from '../../server/app';
import app from 'app';

describe('organizations', () => {
it('organizations/{id}', async () => {
const response = await supertest(app).get('/organizations/1');
it('organizations/{id}', async () => {
const response = await supertest(app).get(
`/organizations/${exampleOrganization.id}`,
);
expect(response.status).toBe(200);
expect(response.body).toMatchObject({
id: exampleOrganization.id,
links: {
featured_trees: expect.stringMatching(/trees/),
associated_planters: expect.stringMatching(/planters/),
species: expect.stringMatching(/species/),
},
});
});

it(
'organizations?planter_id=1&limit=1',
async () => {
const response = await supertest(app).get(
`/organizations?planter_id=${examplePlanter.id}&limit=1`,
);
expect(response.status).toBe(200);
expect(response.body).toMatchObject({
id: 1,
expect(response.body.organizations).toBeInstanceOf(Array);
expect(response.body.organizations[0]).toMatchObject({
id: expect.any(Number),
links: {
featured_trees: expect.stringMatching(/trees/),
associated_planters: expect.stringMatching(/planters/),
species: expect.stringMatching(/species/),
},
});
});

it(
'organizations?planter_id=1&limit=1',
async () => {
const response = await supertest(app).get(
'/organizations?planter_id=1&limit=1',
);
expect(response.status).toBe(200);
expect(response.body.organizations).toBeInstanceOf(Array);
expect(response.body.organizations[0]).toMatchObject({
id: expect.any(Number),
links: {
featured_trees: expect.stringMatching(/trees/),
associated_planters: expect.stringMatching(/planters/),
species: expect.stringMatching(/species/),
},
});
},
1000 * 30,
);
});
},
1000 * 30,
);
80 changes: 43 additions & 37 deletions __tests__/e2e/planters.spec.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,55 @@
import exampleOrganization from '@seeds/data/organization.json';
import examplePlanter from '@seeds/data/planter.json';
import supertest from 'supertest';
import app from '../../server/app';
import app from 'app';

describe('planters', () => {
it('planters/{id}', async () => {
const response = await supertest(app).get('/planters/1');
it('planters/{id}', async () => {
const response = await supertest(app).get(`/planters/${examplePlanter.id}`);
expect(response.status).toBe(200);
expect(response.body).toMatchObject({
id: examplePlanter.id,
links: {
featured_trees: expect.stringMatching(/trees/),
associated_organizations: expect.stringMatching(/organizations/),
species: expect.stringMatching(/species/),
},
});
});

// route is bugged: https://github.com/Greenstand/treetracker-query-api/issues/93
it.skip(
'planters?organization_id=1&limit=1',
async () => {
const response = await supertest(app).get(
`/planters?organization_id=${exampleOrganization.id}&limit=1`,
);
expect(response.status).toBe(200);
expect(response.body).toMatchObject({
id: 1,
expect(response.body.planters).toBeInstanceOf(Array);
console.log(response.body.planters[0]);
expect(response.body.planters[0]).toMatchObject({
id: examplePlanter.id,
organization_id: exampleOrganization.id,
links: {
featured_trees: expect.stringMatching(/trees/),
associated_organizations: expect.stringMatching(/organizations/),
species: expect.stringMatching(/species/),
},
});
});
},
1000 * 30,
);

it(
'planters?organization_id=1&limit=1',
async () => {
const response = await supertest(app).get(
'/planters?organization_id=1&limit=1',
);
expect(response.status).toBe(200);
expect(response.body.planters).toBeInstanceOf(Array);
expect(response.body.planters[0]).toMatchObject({
id: 1,
organization_id: 1,
links: {
featured_trees: expect.stringMatching(/trees/),
associated_organizations: expect.stringMatching(/organizations/),
species: expect.stringMatching(/species/),
},
});
},
1000 * 30,
it('planters?keyword=da&limit=1', async () => {
const keyword = examplePlanter.first_name.slice(0, 2);
const response = await supertest(app).get(
`/planters?keyword=${keyword}&limit=1`,
);

it('planters?keyword=da&limit=1', async () => {
const response = await supertest(app).get('/planters?keyword=da&limit=1');
expect(response.status).toBe(200);
expect(response.body.planters).toBeInstanceOf(Array);
expect(response.body.planters.length <= 1).toBe(true);
expect(
/^da/.test(response.body.planters[0].first_name) ||
/^da/.test(response.body.planters[0].last_name),
).toBe(true);
});
expect(response.status).toBe(200);
expect(response.body.planters).toBeInstanceOf(Array);
expect(response.body.planters.length <= 1).toBe(true);
const regexp = RegExp(`^${keyword}`);
expect(
regexp.test(response.body.planters[0].first_name) ||
regexp.test(response.body.planters[0].last_name),
).toBe(true);
});
Loading