Skip to content

Commit e0cf2b7

Browse files
Added unit tests scaffolding
1 parent 5f88d81 commit e0cf2b7

File tree

7 files changed

+346
-5
lines changed

7 files changed

+346
-5
lines changed

.ci/test.sh

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
function unit_test() {
2+
registry_login
3+
4+
docker-compose -f docker-compose.test.yml up --build --exit-code-from test
5+
}

.gitlab-ci.yml

+6-5
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,13 @@ lint:
1919

2020
unit:
2121
stage: test
22-
image: node
23-
before_script:
24-
- cd api
25-
- npm install
22+
image: docker:stable
23+
services:
24+
- docker:stable-dind
2625
script:
27-
- npm run test-unit
26+
- apk add docker-compose --update-cache --repository http://dl-3.alpinelinux.org/alpine/edge/testing/ --allow-untrusted
27+
- setup_docker
28+
- unit_test
2829

2930
build:
3031
stage: build

api/test/_waitFor.js

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const {promisify} = require('util');
2+
const {Client} = require('pg').native;
3+
const sleep = promisify((a, f) => setTimeout(f, a));
4+
const loop = async () => {
5+
const client = new Client();
6+
const innerLoop = async () => {
7+
await sleep(1000);
8+
await loop();
9+
};
10+
await client.connect().catch(async () => await innerLoop());
11+
const res = await client.query('SELECT COUNT(*) FROM observations;').catch(() => {});
12+
client.end();
13+
if (!res || res.rows[0].count == 0) {
14+
await innerLoop();
15+
}
16+
};
17+
18+
loop();

docker-compose.test.yml

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
version: '3.4'
2+
3+
x-env:
4+
&env
5+
PGHOST: db_test
6+
PGDATABASE: statcan_api
7+
READONLY_PWD: mypwd
8+
9+
services:
10+
db_test:
11+
image: postgres:11-alpine
12+
environment:
13+
POSTGRES_DB: statcan_api
14+
POSTGRES_USER: postgres
15+
POSTGRES_PASSWORD: pwd1234
16+
networks:
17+
- test
18+
ports:
19+
- '5432:5432'
20+
logging:
21+
driver: none
22+
23+
pg-evolve_test:
24+
image: artifactory.cloud.statcan.ca/docker/pg-evolve
25+
environment:
26+
<< : *env
27+
PGUSER: postgres
28+
PGPASSWORD: pwd1234
29+
PGOPTIONS: "-c custom.readonly_pwd=$${READONLY_PWD}"
30+
volumes:
31+
- ./db:/opt/pg-evolve/evolutions
32+
command: ["sh", "-c", "until psql -c '\\q' 2> /dev/null; do sleep 1; done && pg-evolve && tail -f /dev/null"]
33+
networks:
34+
- test
35+
36+
db_dataloader_test:
37+
image: postgres:11-alpine
38+
environment:
39+
<< : *env
40+
PGUSER: postgres
41+
PGPASSWORD: pwd1234
42+
depends_on:
43+
- db_test
44+
- pg-evolve_test
45+
volumes:
46+
- ./test_data:/init
47+
working_dir: /init
48+
entrypoint: ''
49+
command: ['sh', '-c', './wait-for.sh ./load-data.sh && tail -f /dev/null']
50+
networks:
51+
- test
52+
53+
test:
54+
build:
55+
context: ./api
56+
image: api_test
57+
depends_on:
58+
- db_dataloader_test
59+
environment:
60+
<< : *env
61+
PGUSER: api
62+
PGPASSWORD: "$${READONLY_PWD}"
63+
URL_ROOT: http://localhost:8000
64+
volumes:
65+
- ./api/.eslintrc.json:/home/node/app/.eslintrc.json
66+
- ./api/test:/home/node/app/test
67+
command: ['sh', '-c', 'node test/_waitFor.js && npm run test-unit']
68+
networks:
69+
- test
70+
71+
networks:
72+
test:

test_data/load-data.sh

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/bin/sh
2+
if [ "$(psql -At -c 'SELECT COUNT(*) FROM observations')" -eq 0 ]; then
3+
echo "Loading data" \
4+
&& psql -q1 -v ON_ERROR_STOP=1 -f ./test_data.sql \
5+
&& echo "Loading complete"
6+
fi

test_data/test_data.sql

+223
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
INSERT INTO subjects (name, title)
2+
VALUES
3+
(
4+
'subject_1',
5+
hstore(ARRAY[['en', 'Subject 1'], ['fr', 'Subject 1']])
6+
),
7+
(
8+
'subject_2',
9+
hstore(ARRAY[['en', 'Subject 2'], ['fr', 'Subject 2']])
10+
);
11+
12+
INSERT INTO frequencies (name, sdmx_id, title)
13+
VALUES
14+
(
15+
'quarterly', 'Q',
16+
hstore(ARRAY[['en', 'Quarterly'], ['fr', 'Trimestriel']])
17+
),
18+
(
19+
'monthly', 'M',
20+
hstore(ARRAY[['en', 'Monthly'], ['fr', 'Mensuel']])
21+
);
22+
23+
24+
INSERT INTO status (name, symbol)
25+
VALUES
26+
('not_available', '.');
27+
28+
INSERT INTO dimensions (name, title)
29+
VALUES
30+
(
31+
'geographicArea',
32+
hstore(ARRAY[['en', ''], ['fr', '']])
33+
),
34+
(
35+
'sex',
36+
hstore(ARRAY[['en', ''], ['fr', '']])
37+
);
38+
39+
INSERT INTO type_geographicArea (name)
40+
VALUES
41+
('24'),
42+
('35');
43+
44+
45+
INSERT INTO type_sex (name)
46+
VALUES
47+
('male'),
48+
('female');
49+
50+
INSERT INTO indicators (name, frequency_id, title)
51+
VALUES
52+
(
53+
'indicator1', (SELECT id FROM frequencies WHERE name = 'quarterly'),
54+
hstore(ARRAY[['en', 'Indicator 1'], ['fr', 'Indicateur 1']])
55+
);
56+
57+
INSERT INTO indicators (name, frequency_id, title)
58+
VALUES
59+
(
60+
'indicator2', (SELECT id FROM frequencies WHERE name = 'monthly'),
61+
hstore(ARRAY[['en', 'Indicator 2'], ['fr', 'Indicateur 2']])
62+
);
63+
64+
INSERT INTO indicator_subjects (indicator_id, subject_id)
65+
VALUES (
66+
(SELECT id FROM indicators WHERE name = 'indicator1'),
67+
(SELECT id FROM subjects WHERE name = 'subject1')
68+
);
69+
70+
INSERT INTO indicator_subjects (indicator_id, subject_id)
71+
VALUES (
72+
(SELECT id FROM indicators WHERE name = 'indicator2'),
73+
(SELECT id FROM subjects WHERE name = 'subject2')
74+
);
75+
76+
INSERT INTO indicator_dimensions (indicator_id, dimension_id)
77+
VALUES (
78+
(SELECT id FROM indicators WHERE name = 'indicator1'),
79+
(SELECT id FROM dimensions WHERE name = 'geographicArea')
80+
);
81+
82+
INSERT INTO indicator_dimensions (indicator_id, dimension_id)
83+
VALUES
84+
(
85+
(SELECT id FROM indicators WHERE name = 'indicator2'),
86+
(SELECT id FROM dimensions WHERE name = 'geographicArea')
87+
),
88+
(
89+
(SELECT id FROM indicators WHERE name = 'indicator2'),
90+
(SELECT id FROM dimensions WHERE name = 'sex')
91+
);
92+
93+
INSERT INTO timeseries
94+
VALUES ('d3a06c6b-82a7-4efa-8f0f-6cb453deff2c', (SELECT id FROM indicators WHERE name = 'indicator1'));
95+
96+
INSERT INTO timeseries
97+
VALUES ('3d9e3917-8a39-4eb6-917c-bf485dd0b20b', (SELECT id FROM indicators WHERE name = 'indicator1'));
98+
99+
INSERT INTO timeseries
100+
VALUES ('e052c4b3-ae8b-43ca-a6f7-ff75fcfc49c5', (SELECT id FROM indicators WHERE name = 'indicator2'));
101+
102+
INSERT INTO timeseries
103+
VALUES ('e6c20549-b6a6-4107-8bfe-6f67f962d65a', (SELECT id FROM indicators WHERE name = 'indicator2'));
104+
105+
INSERT INTO timeseries
106+
VALUES ('699b644d-dd26-430d-9f56-b4fc6760569c', (SELECT id FROM indicators WHERE name = 'indicator2'));
107+
108+
INSERT INTO timeseries
109+
VALUES ('ac139d12-22ce-45ba-a63e-14f1dc9f3ec4', (SELECT id FROM indicators WHERE name = 'indicator2'));
110+
111+
INSERT INTO vectors
112+
VALUES (1, 'd3a06c6b-82a7-4efa-8f0f-6cb453deff2c');
113+
114+
INSERT INTO vectors
115+
VALUES (2, '3d9e3917-8a39-4eb6-917c-bf485dd0b20b');
116+
117+
INSERT INTO vectors
118+
VALUES (3, 'e052c4b3-ae8b-43ca-a6f7-ff75fcfc49c5');
119+
120+
INSERT INTO vectors
121+
VALUES (4, 'e6c20549-b6a6-4107-8bfe-6f67f962d65a');
122+
123+
INSERT INTO vectors
124+
VALUES (5, '699b644d-dd26-430d-9f56-b4fc6760569c');
125+
126+
INSERT INTO vectors
127+
VALUES (6, 'ac139d12-22ce-45ba-a63e-14f1dc9f3ec4');
128+
129+
INSERT INTO timeseries_dimension_geographicArea (timeseries_id, value_id)
130+
VALUES ('d3a06c6b-82a7-4efa-8f0f-6cb453deff2c', (SELECT id FROM type_geographicArea WHERE name = '24'));
131+
132+
INSERT INTO timeseries_dimension_geographicArea (timeseries_id, value_id)
133+
VALUES ('3d9e3917-8a39-4eb6-917c-bf485dd0b20b', (SELECT id FROM type_geographicArea WHERE name = '35'));
134+
135+
INSERT INTO timeseries_dimension_geographicArea (timeseries_id, value_id)
136+
VALUES ('e052c4b3-ae8b-43ca-a6f7-ff75fcfc49c5', (SELECT id FROM type_geographicArea WHERE name = '24'));
137+
138+
INSERT INTO timeseries_dimension_geographicArea (timeseries_id, value_id)
139+
VALUES ('e6c20549-b6a6-4107-8bfe-6f67f962d65a', (SELECT id FROM type_geographicArea WHERE name = '35'));
140+
141+
INSERT INTO timeseries_dimension_geographicArea (timeseries_id, value_id)
142+
VALUES ('699b644d-dd26-430d-9f56-b4fc6760569c', (SELECT id FROM type_geographicArea WHERE name = '24'));
143+
144+
INSERT INTO timeseries_dimension_geographicArea (timeseries_id, value_id)
145+
VALUES ('ac139d12-22ce-45ba-a63e-14f1dc9f3ec4', (SELECT id FROM type_geographicArea WHERE name = '35'));
146+
147+
INSERT INTO timeseries_dimension_sex (timeseries_id, value_id)
148+
VALUES ('e052c4b3-ae8b-43ca-a6f7-ff75fcfc49c5', (SELECT id FROM type_sex WHERE name = 'male'));
149+
150+
INSERT INTO timeseries_dimension_sex (timeseries_id, value_id)
151+
VALUES ('e6c20549-b6a6-4107-8bfe-6f67f962d65a', (SELECT id FROM type_sex WHERE name = 'female'));
152+
153+
INSERT INTO timeseries_dimension_sex (timeseries_id, value_id)
154+
VALUES ('699b644d-dd26-430d-9f56-b4fc6760569c', (SELECT id FROM type_sex WHERE name = 'male'));
155+
156+
INSERT INTO timeseries_dimension_sex (timeseries_id, value_id)
157+
VALUES ('ac139d12-22ce-45ba-a63e-14f1dc9f3ec4', (SELECT id FROM type_sex WHERE name = 'female'));
158+
159+
WITH o AS (
160+
INSERT INTO observations (period, timeseries_id)
161+
VALUES ('2019-01-01', 'd3a06c6b-82a7-4efa-8f0f-6cb453deff2c')
162+
RETURNING id
163+
)
164+
INSERT INTO observation_values (observation_id, value)
165+
SELECT id, 29 FROM o;
166+
167+
WITH o AS (
168+
INSERT INTO observations (period, timeseries_id)
169+
VALUES ('2019-02-01', 'd3a06c6b-82a7-4efa-8f0f-6cb453deff2c')
170+
RETURNING id
171+
)
172+
INSERT INTO observation_values (observation_id, value)
173+
SELECT id, 35 FROM o;
174+
175+
---
176+
177+
WITH o AS (
178+
INSERT INTO observations (period, timeseries_id)
179+
VALUES ('2019-01-01', '3d9e3917-8a39-4eb6-917c-bf485dd0b20b')
180+
RETURNING id
181+
)
182+
INSERT INTO observation_values (observation_id, value)
183+
SELECT id, 2.5 FROM o;
184+
185+
WITH o AS (
186+
INSERT INTO observations (period, timeseries_id)
187+
VALUES ('2019-02-01', '3d9e3917-8a39-4eb6-917c-bf485dd0b20b')
188+
RETURNING id
189+
)
190+
INSERT INTO observation_values (observation_id, value)
191+
SELECT id, 2.9 FROM o;
192+
193+
---
194+
195+
WITH o AS (
196+
INSERT INTO observations (period, timeseries_id)
197+
VALUES ('2019-01-01', '3d9e3917-8a39-4eb6-917c-bf485dd0b20b')
198+
RETURNING id
199+
)
200+
INSERT INTO observation_values (observation_id, value)
201+
SELECT id, 29 FROM o;
202+
203+
WITH o AS (
204+
INSERT INTO observations (period, timeseries_id)
205+
VALUES ('2019-02-01', '3d9e3917-8a39-4eb6-917c-bf485dd0b20b')
206+
RETURNING id
207+
)
208+
INSERT INTO observation_values (observation_id, value)
209+
SELECT id, 35 FROM o;
210+
211+
WITH o AS (
212+
INSERT INTO observations (period, timeseries_id)
213+
VALUES ('2019-03-01', '3d9e3917-8a39-4eb6-917c-bf485dd0b20b')
214+
RETURNING id
215+
), v AS (
216+
INSERT INTO observation_values (observation_id)
217+
SELECT id FROM o
218+
RETURNING id
219+
)
220+
INSERT INTO observation_status (observation_value_id, observation_status_id)
221+
SELECT id, (SELECT id FROM status WHERE name = 'not_available') FROM v;
222+
223+
---

test_data/wait-for.sh

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/bin/sh
2+
# wait-for-postgres.sh
3+
4+
set -e
5+
6+
cmd="$@"
7+
8+
until psql -c '\q' 2> /dev/null; do
9+
>&2 echo "Postgres is unavailable - sleeping"
10+
sleep 1
11+
done
12+
13+
sleep 5
14+
15+
>&2 echo "Postgres is up - executing command"
16+
exec $cmd

0 commit comments

Comments
 (0)