Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add e2e test framework #31

Merged
merged 2 commits into from
Sep 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
40 changes: 39 additions & 1 deletion .github/workflows/actions-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,42 @@ jobs:
if: steps.cache-node-modules.outputs.cache-hit != 'true'
run: npm install
- name: Run unit tests with coverage
run: npm run test
run: npm run test
e2e-tests:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup node
uses: actions/setup-node@v4
with:
node-version: 20.12.x
cache: npm
- name: Start test containers
run: docker compose -f "./e2e/helpers/docker/docker-compose.yml" up -d
- name: Cache node modules
id: cache-node-modules
uses: actions/cache@v4
with:
path: node_modules
key: node-modules-${{ hashFiles('package-lock.json') }}
- name: Install Dependencies
if: steps.cache-node-modules.outputs.cache-hit != 'true'
run: npm install
- name: Start indexer
run: npm run start:e2e > indexer.log 2>&1 &
- name: Wait for indexer to become available
Comment on lines +46 to +59
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems Good to me . What is your opinion regarding putting indexer also in a container ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean, creating a Dokcerfile, building the image, and running that image here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we can create a docker image of the indexer and run it in the same service as bitcoind

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem here is that we'd need to build the image again and again for every run. This could slow down the CI considerably.
This will definitely be a good change but let's do it in a future PR.

run: |
for i in {1..24}; do
curl --fail -X GET http://localhost:3000/health && break || sleep 2
done
- name: Run e2e tests
run: npm run test:e2e
- name: Fetch bitcoin core logs
if: always()
run: docker compose -f "./e2e/helpers/docker/docker-compose.yml" logs bitcoin
- name: Fetch indexer logs
if: always()
run: cat indexer.log
- name: Stop test containers
run: docker compose -f "./e2e/helpers/docker/docker-compose.yml" down
13 changes: 13 additions & 0 deletions config/e2e.config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
db:
path: ./.silent-pay-indexer/db/database.sqlite
synchronize: true
app:
port: 3000
network: regtest
providerType: BITCOIN_CORE_RPC
bitcoinCore:
protocol: http
rpcHost: localhost
rpcUser: alice
rpcPass: password
rpcPort: 18443
17 changes: 17 additions & 0 deletions e2e/heath-check.e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { ApiHelper } from '@e2e/helpers/api.helper';
import { ServiceStatus } from '@/common/enum';

describe('Health check', () => {
let apiHelper: ApiHelper;

beforeAll(() => {
apiHelper = new ApiHelper();
});

it('should check health of indexer', async () => {
const { data, status } = await apiHelper.get(`/health`);

expect(status).toBe(200);
expect(data).toEqual(ServiceStatus.HEALTHY);
});
});
32 changes: 32 additions & 0 deletions e2e/helpers/api.helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';
import { readFileSync } from 'fs';
import * as yaml from 'js-yaml';

export class ApiHelper {
private readonly baseUrl: string;

constructor(configPath = './config/e2e.config.yaml') {
const config = yaml.load(readFileSync(configPath, 'utf8')) as Record<
string,
any
>;
this.baseUrl = `http://localhost:${config.app.port}`;
}

async get<TResponseData = any>(path: string, params?: any) {
return this.makeRequest<TResponseData>({
method: 'get',
url: `${this.baseUrl}${path}`,
params,
validateStatus: () => true,
});
}

private async makeRequest<TResponseData = any, TBody = any>(
config: AxiosRequestConfig<TBody>,
) {
return axios<TResponseData, AxiosResponse<TResponseData>, TBody>(
config,
);
}
}
21 changes: 21 additions & 0 deletions e2e/helpers/docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
services:
bitcoin:
image: btcpayserver/bitcoin:24.0.1-1
environment:
BITCOIN_NETWORK: regtest
BITCOIN_EXTRA_ARGS: |
server=1
rest=1
rpcbind=0.0.0.0:18443
rpcallowip=0.0.0.0/0
rpcauth=alice:88cae77e34048eff8b9f0be35527dd91$$d5c4e7ff4dfe771808e9c00a1393b90d498f54dcab0ee74a2d77bd01230cd4cc
debug=1
logips=1
logtimemicros=1
blockmintxfee=0
deprecatedrpc=signrawtransaction
listenonion=0
fallbackfee=0.00001
txindex=1
ports:
- '18443:18443'
20 changes: 20 additions & 0 deletions jest-e2e.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { Config } from '@jest/types';

const config: Config.InitialOptions = {
preset: 'ts-jest',
verbose: true,
moduleFileExtensions: ['js', 'json', 'ts'],
rootDir: '.',
roots: ['<rootDir>/e2e/'],
testRegex: '.*\\.e2e-spec\\.ts$',
transform: {
'^.+\\.(t|j)s$': 'ts-jest',
},
testEnvironment: 'node',
moduleNameMapper: {
'@/(.*)': '<rootDir>/src/$1',
'@e2e/(.*)': '<rootDir>/e2e/$1',
},
testTimeout: 60000, // 1 minutes
};
export default config;
Loading