Skip to content

Commit

Permalink
E2E Tests WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
djm2k committed Sep 7, 2024
1 parent 80afa11 commit 17ed5fe
Show file tree
Hide file tree
Showing 9 changed files with 1,612 additions and 205 deletions.
14 changes: 12 additions & 2 deletions babel.config.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
{
"presets": ["@babel/preset-typescript"]
}
"presets": [
[
"@babel/preset-env",
{
"targets": {
"node": "current"
}
}
],
"@babel/preset-typescript"
]
}
25 changes: 25 additions & 0 deletions docker/tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Container End to End Tests

- Run with `yarn run e2e-test`

### Prequisites

1. Install testcontainers: `yarn add -D testcontainers`

2. Docker daemon running
- If using WSL and Docker Desktop, requires these steps:
1. Expose the Docker for Windows daemon on tcp port 2375 without TLS.
(Right-click the Docker Desktop icon on the task bar > Change Settings).
2. edit `/etc/docker` and add the following:
```json
{"hosts": [
"tcp://0.0.0.0:2375",
"unix:///var/run/docker.sock"
]}
```

3. Set the DOCKER_HOST environment variable inside the WSL shell to tcp://localhost:2375. It is recommended to add this to your ~/.bashrc file, so it’s available every time you open your terminal: `export DOCKER_HOST=tcp://localhost:2375`
- https://java.testcontainers.org/supported_docker_environment/windows/#windows-subsystem-for-linux-wsl
- https://stackoverflow.com/questions/63416280/how-to-expose-docker-tcp-socket-on-wsl2-wsl-installed-docker-not-docker-deskt
- Debug with: `DEBUG=testcontainers* DOCKER_HOST=unix:///var/run/docker.sock yarn run e2e-test`
- https://node.testcontainers.org/configuration/#logs
47 changes: 0 additions & 47 deletions docker/tests/container-util.js

This file was deleted.

102 changes: 102 additions & 0 deletions docker/tests/container-util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { writeFile } from 'fs/promises';
import { GenericContainer, Wait } from 'testcontainers';


/**
* Start an `actual-server` from the root build context, using port 5006.
*/
export async function startActualContainer(buildContext = './') {
const newContainer = await GenericContainer
.fromDockerfile(buildContext)
.build();

return newContainer
.withExposedPorts(5006)
.withWaitStrategy(Wait.forListeningPorts())
.start();
}

/**
* Start a `caddy` instance with a generated Caddyfile.
*
* https://actualbudget.org/docs/config/reverse-proxies/#caddy
*/
export async function startCaddyContainer(actualServerPort: number):
Promise<import('testcontainers').StartedTestContainer> {
if (typeof actualServerPort !== 'number') throw Error("actualServerPort must be number!");

// write Caddyfile to disk for copying
const source = './Caddyfile';
const testCaddyfileContents = 'http://localhost {\n\tencode gzip zstd\n' +
'\treverse_proxy actual_server:' + actualServerPort.toString() + '\n}\n';
await writeFile(source, testCaddyfileContents);

const caddyContainer = new GenericContainer('caddy:latest')
.withCopyFilesToContainer([{ source, target: '/etc/caddyContainer/Caddyfile' }])
.withExposedPorts(80)
.withWaitStrategy(Wait.forListeningPorts());

return caddyContainer.start();
}

// services:\
export async function startTraefikContainer(actualServerPort: number) {
// write Caddyfile to disk for copying
const source = './traefik.yaml';
const testTraeFikYamlContents = `
logLevel: "DEBUG"
entryPoints:
web:
address: ":80"
providers:
docker: {}
`;
await writeFile(source, testTraeFikYamlContents);

const traefikContainer = new GenericContainer("traefik:latest")
.withExposedPorts(80)
.withCopyFilesToContainer([{ source, target: "/etc/traefik/traefik.yaml" }])
.withBindMounts([{ source: "/var/run/docker.sock", target: "/var/run/docker.sock" }])
.withWaitStrategy(Wait.forListeningPorts())


return traefikContainer.start();


}

/**
* Start an `actual-server` from the root build context, using port 5006.
*/
export async function startActualContainerWithTraefik(buildContext = './') {
const newContainer = await GenericContainer
.fromDockerfile(buildContext)
.build();

return newContainer.withLabels({
// "traefik.enable": "true",
"traefik.http.routers.actual-server.entrypoints": "web",
// "traefik.http.services.actual-server.loadbalancer.server.port": "5006"
})
.withExposedPorts(5006)
.withWaitStrategy(Wait.forListeningPorts())
.start();
}
// traefik:
// image: traefik:latest
// restart: unless-stopped
// ports:
// - "80:80"
// volumes:
// - "./traefik.yaml:/etc/traefik/traefik.yaml"
// - "./traefik/data:/data"
// - "/var/run/docker.sock:/var/run/docker.sock"

// actual-server:
// image: actualbudget/actual-server:latest-alpine
// restart: unless-stopped
// labels:

// volumes:
// - ./actual-data:/data
69 changes: 0 additions & 69 deletions docker/tests/reverse-proxies.test.js

This file was deleted.

81 changes: 81 additions & 0 deletions docker/tests/reverse-proxies.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { unlink } from 'fs/promises';
import request from 'supertest';
import { startActualContainer, startActualContainerWithTraefik, startCaddyContainer, startTraefikContainer } from './container-util.ts';
import { StartedTestContainer } from 'testcontainers';


// describe('Actual Server with Caddy', () => {
// let actualServerContainer;
// let caddyContainer;

// beforeAll(async () => {
// actualServerContainer = await startActualContainer();
// caddyContainer = await startCaddyContainer(
// actualServerContainer.getMappedPort(5006),
// );
// }, 66 * 1000);

// it('should allow login', async () => {
// const hostname = caddyContainer.getHost();
// const port = caddyContainer.getMappedPort(80);
// const caddyHost = `${hostname}:${port}`;
// // console.log('Caddy host: ' + caddyHost);

// const caddyRequest = request(caddyHost);

// caddyRequest.get('/').then(res => {
// expect(res.statusCode).toBe(200)
// });
// });

// afterAll(async () => {
// if (caddyContainer) await caddyContainer.stop();
// if (actualServerContainer) await actualServerContainer.stop();

// // Delete Caddyfile from disk, if it exists
// await unlink('./Caddyfile').catch((_err) => {
// // don't care about ENOENT
// return;
// });
// });
// });

// Traefik, TODO modularise
describe('Actual Server with Traefik', () => {
let actualServerContainer: StartedTestContainer;
let traefikContainer: StartedTestContainer;

beforeAll(async () => {
actualServerContainer = await startActualContainerWithTraefik();
traefikContainer = await startTraefikContainer(
actualServerContainer.getMappedPort(5006),
);
}, 66 * 1000);

it('should allow login', async () => {
const hostname = traefikContainer.getHost();
const port = traefikContainer.getMappedPort(80);
const traefikHost = `${hostname}:${port}`;
// console.log('Traefik host: ' + traefikHost);

const traefikRequest = request(traefikHost);

traefikRequest.get('/').then(res => {
expect(res.statusCode).toBe(200)
});
});

afterAll(async () => {
if (traefikContainer) await traefikContainer.stop();
if (actualServerContainer) await actualServerContainer.stop();

// Delete traefik.yml from disk, if it exists
await unlink('./traefik.yaml').catch((_err) => {
// don't care about ENOENT
return;
});
});
});



14 changes: 10 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
"lint": "eslint . --max-warnings 0",
"lint:fix": "eslint . --fix",
"build": "tsc",
"e2e-test": "DEBUG=testcontainers* NODE_ENV=test yarn node --experimental-vm-modules --no-warnings=ExperimentalWarning $(yarn bin jest) ./docker/tests --detectOpenHandles --forceExit --config {}",
"test": "NODE_ENV=test NODE_OPTIONS='--experimental-vm-modules --no-warnings=ExperimentalWarning --trace-warnings' jest --coverage",
"e2e-test": "yarn cross-env DEBUG='testcontainers:containers' NODE_ENV=test NODE_OPTIONS='--experimental-vm-modules --no-warnings=ExperimentalWarning --trace-warnings' jest ./docker/tests --detectOpenHandles --forceExit --config {}",
"test": "yarn cross-env NODE_ENV=test NODE_OPTIONS='--experimental-vm-modules --no-warnings=ExperimentalWarning --trace-warnings' jest --coverage",
"db:migrate": "NODE_ENV=development node src/run-migrations.js up",
"db:downgrade": "NODE_ENV=development node src/run-migrations.js down",
"db:test-migrate": "NODE_ENV=test node src/run-migrations.js up",
Expand Down Expand Up @@ -41,7 +41,11 @@
"winston": "^3.14.2"
},
"devDependencies": {
"@babel/preset-typescript": "^7.20.2",
"@babel/core": "^7.24.9",
"@babel/preset-env": "^7.25.0",
"@babel/preset-typescript": "^7.24.7",
"@types/babel__core": "^7",
"@types/babel__preset-env": "^7",
"@types/bcrypt": "^5.0.2",
"@types/better-sqlite3": "^7.6.7",
"@types/cors": "^2.8.13",
Expand All @@ -53,6 +57,8 @@
"@types/uuid": "^9.0.0",
"@typescript-eslint/eslint-plugin": "^5.51.0",
"@typescript-eslint/parser": "^5.51.0",
"babel-jest": "^29.7.0",
"cross-env": "^7.0.3",
"eslint": "^8.33.0",
"eslint-plugin-prettier": "^4.2.1",
"jest": "^29.3.1",
Expand All @@ -65,4 +71,4 @@
"node": ">=18.0.0"
},
"packageManager": "[email protected]"
}
}
2 changes: 2 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
// DOM for URL global in Node 16+
"lib": ["ES2021"],
"allowSyntheticDefaultImports": true,
"allowImportingTsExtensions": true,
"noEmit": true,
"esModuleInterop": true,
"experimentalDecorators": true,
"resolveJsonModule": true,
Expand Down
Loading

0 comments on commit 17ed5fe

Please sign in to comment.