Skip to content

Commit 714461d

Browse files
committed
ci: add infra setup for integ tests
Adds the Docker foundation for integration testing advanced-wallets. Previously, all tests stubbed the AWM client entirely using Nock, meaning the MBE → AWM HTTP contract was never exercised automatically. This PR establishes the infrastructure to run integ tests where AWM and MBE start as actual HTTP servers and communicate over real TCP sockets. This commit adds a validation test to verify the changes. Follow up PRs will add tests and expand on this PR. Ticket: WAL-1504, WAL-1507
1 parent 87588a6 commit 714461d

8 files changed

Lines changed: 153 additions & 0 deletions

File tree

.mocharc.integ.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module.exports = {
2+
require: ['ts-node/register'],
3+
extension: ['ts'],
4+
timeout: 30000,
5+
ui: 'bdd',
6+
spec: 'src/**/__tests__/integration/**/*.integ.test.ts',
7+
recursive: true,
8+
exit: true,
9+
};

docker-compose.integ.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
services:
2+
integration-tests:
3+
build:
4+
context: .
5+
dockerfile: integration-tests.Dockerfile
6+
environment:
7+
- NODE_ENV=test

integration-tests.Dockerfile

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# Stage 1 — build
2+
FROM node:22.1.0-alpine@sha256:487dc5d5122d578e13f2231aa4ac0f63068becd921099c4c677c850df93bede8 AS builder
3+
4+
ENV NODE_ENV=test \
5+
TZ=UTC \
6+
LANG=C.UTF-8
7+
8+
WORKDIR /usr/src/app
9+
10+
# native addons (e.g. keccak) require build tools
11+
RUN apk add --no-cache python3 make g++ gcc linux-headers
12+
13+
COPY package.json package-lock.json ./
14+
15+
RUN npm ci
16+
17+
COPY . .
18+
19+
RUN npm run build
20+
21+
# Stage 2 — test runner
22+
FROM node:22.1.0-alpine@sha256:487dc5d5122d578e13f2231aa4ac0f63068becd921099c4c677c850df93bede8 AS runner
23+
24+
ENV NODE_ENV=test \
25+
TZ=UTC \
26+
LANG=C.UTF-8
27+
28+
WORKDIR /usr/src/app
29+
30+
COPY --from=builder /usr/src/app/dist ./dist
31+
COPY --from=builder /usr/src/app/node_modules ./node_modules
32+
COPY --from=builder /usr/src/app/bin ./bin
33+
COPY --from=builder /usr/src/app/src ./src
34+
COPY --from=builder /usr/src/app/package.json .
35+
COPY --from=builder /usr/src/app/.mocharc.integ.js .
36+
COPY --from=builder /usr/src/app/tsconfig.integ.json .
37+
COPY --from=builder /usr/src/app/tsconfig.json .
38+
39+
CMD ["npm", "run", "test:integration"]

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
"lint": "eslint --quiet --ignore-pattern scripts/bump-version.ts .",
1818
"lint:fix": "eslint --quiet --ignore-pattern scripts/bump-version.ts . --fix",
1919
"generate-test-ssl": "openssl req -x509 -newkey rsa:2048 -keyout demo.key -out demo.crt -days 365 -nodes -subj '/CN=localhost'",
20+
"test:integration": "NODE_ENV=test TS_NODE_PROJECT=tsconfig.integ.json mocha --config .mocharc.integ.js",
21+
"docker:test:integration": "bash scripts/run-integration-tests.sh",
2022
"generate:openapi:masterExpress": "npx @api-ts/openapi-generator --name @bitgo/master-bitgo-express ./src/masterBitgoExpress/routers/index.ts > masterBitgoExpress.json",
2123
"container:build:master-bitgo-express": "podman build --build-arg PORT=3081 -t master-bitgo-express .",
2224
"container:build:advanced-wallet-manager": "podman build --build-arg PORT=3080 -t advanced-wallet-manager .",

scripts/run-integration-tests.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
echo "Running integration tests..."
6+
7+
docker-compose -f docker-compose.integ.yml up --build --abort-on-container-exit || true
8+
9+
exit_code=$?
10+
11+
docker-compose -f docker-compose.integ.yml down
12+
13+
exit $exit_code
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import 'should';
2+
import * as http from 'http';
3+
import { app as awmApp } from '../../advancedWalletManagerApp';
4+
import { app as mbeApp } from '../../masterBitGoExpressApp';
5+
import { AppMode, TlsMode, SigningMode } from '../../shared/types';
6+
import { listen, close } from './helpers/servers';
7+
8+
describe('integration — health checks', () => {
9+
let awmServer: http.Server;
10+
let mbeServer: http.Server;
11+
let awmPort: number;
12+
let mbePort: number;
13+
14+
before(async () => {
15+
awmServer = http.createServer(
16+
awmApp({
17+
appMode: AppMode.ADVANCED_WALLET_MANAGER,
18+
tlsMode: TlsMode.DISABLED,
19+
signingMode: SigningMode.LOCAL,
20+
port: 0,
21+
bind: '127.0.0.1',
22+
timeout: 30000,
23+
httpLoggerFile: '',
24+
keyProviderUrl: 'http://127.0.0.1:3082',
25+
}),
26+
);
27+
awmPort = await listen(awmServer);
28+
29+
mbeServer = http.createServer(
30+
mbeApp({
31+
appMode: AppMode.MASTER_EXPRESS,
32+
tlsMode: TlsMode.DISABLED,
33+
port: 0,
34+
bind: '127.0.0.1',
35+
timeout: 30000,
36+
httpLoggerFile: '',
37+
env: 'test',
38+
disableEnvCheck: true,
39+
advancedWalletManagerUrl: `http://127.0.0.1:${awmPort}`,
40+
awmServerCertAllowSelfSigned: true,
41+
}),
42+
);
43+
mbePort = await listen(mbeServer);
44+
});
45+
46+
after(async () => {
47+
await close(awmServer);
48+
await close(mbeServer);
49+
});
50+
51+
it('AWM /ping returns 200', async () => {
52+
const res = await fetch(`http://127.0.0.1:${awmPort}/ping`, { method: 'POST' });
53+
res.status.should.equal(200);
54+
});
55+
56+
it('MBE /advancedwallet/ping returns 200', async () => {
57+
const res = await fetch(`http://127.0.0.1:${mbePort}/advancedwallet/ping`, { method: 'POST' });
58+
res.status.should.equal(200);
59+
});
60+
});
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import * as http from 'http';
2+
import * as net from 'net';
3+
4+
export function listen(server: http.Server): Promise<number> {
5+
return new Promise((resolve, reject) => {
6+
server.once('error', reject);
7+
server.listen(0, '127.0.0.1', () => {
8+
resolve((server.address() as net.AddressInfo).port);
9+
});
10+
});
11+
}
12+
13+
export function close(server: http.Server): Promise<void> {
14+
return new Promise((resolve) => server.close(() => resolve()));
15+
}

tsconfig.integ.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"extends": "./tsconfig.json",
3+
"compilerOptions": {
4+
"lib": ["ES2020", "DOM"],
5+
"types": ["mocha", "node"]
6+
},
7+
"include": ["src/__tests__/integration/**/*"]
8+
}

0 commit comments

Comments
 (0)