test(api): add API test on contacts

next will be to add CI on it
This commit is contained in:
Edouard Vanbelle
2026-05-11 00:50:39 +02:00
parent 03aac93db3
commit 8ab537797a
14 changed files with 530 additions and 55 deletions
+3
View File
@@ -0,0 +1,3 @@
end to end tests via playwright
-16
View File
@@ -1,16 +0,0 @@
services:
postgres-test:
image: postgres:18.2-alpine3.23
environment:
POSTGRES_USER: oxicloud_test
POSTGRES_PASSWORD: oxicloud_test
POSTGRES_DB: oxicloud_test
ports:
- "5433:5432"
tmpfs:
- /var/lib/postgresql # in-memory: always blank on start (pg18+ uses /var/lib/postgresql/18/data)
healthcheck:
test: ["CMD-SHELL", "pg_isready -U oxicloud_test"]
interval: 2s
timeout: 5s
retries: 10
+2 -2
View File
@@ -4,9 +4,9 @@
"description": "",
"main": "index.js",
"scripts": {
"pretest": "node -e \"(async()=>{await require('./spawn-db.js')()})().catch(e=>{console.error(e);process.exit(1)})\"",
"pretest": "bash ../common/spawn-db.sh",
"test": "npx playwright test",
"posttest": "node -e \"(async()=>{await require('./stop-db.js')()})().catch(e=>{console.error(e);process.exit(1)})\""
"posttest": "bash ../common/stop-db.sh"
},
"keywords": [],
"author": "",
+19 -12
View File
@@ -1,4 +1,21 @@
import { defineConfig, devices } from '@playwright/test';
import * as fs from 'fs';
import * as path from 'path';
/** Parse a KEY=VALUE env file, skipping blank lines and comments. */
function loadEnv(filePath: string): Record<string, string> {
const env: Record<string, string> = {};
for (const line of fs.readFileSync(filePath, 'utf-8').split('\n')) {
const trimmed = line.trim();
if (!trimmed || trimmed.startsWith('#')) continue;
const idx = trimmed.indexOf('=');
if (idx === -1) continue;
env[trimmed.slice(0, idx)] = trimmed.slice(idx + 1);
}
return env;
}
const commonEnv = loadEnv(path.join(__dirname, '../common/server.env'));
export default defineConfig({
testDir: './scenarios',
@@ -39,19 +56,9 @@ export default defineConfig({
stdout: 'pipe',
stderr: 'pipe',
env: {
DATABASE_URL: 'postgres://oxicloud_test:oxicloud_test@localhost:5433/oxicloud_test',
OXICLOUD_SERVER_PORT: 8087,
OXICLOUD_DB_CONNECTION_STRING: 'postgres://oxicloud_test:oxicloud_test@localhost:5433/oxicloud_test',
...commonEnv,
OXICLOUD_SERVER_PORT: '8087',
OXICLOUD_STORAGE_PATH: './tests/e2e/storage',
OXICLOUD_STATIC_PATH: './static',
OXICLOUD_JWT_SECRET: 'test-secret-do-not-use-in-prod-minimum-32-chars',
OXICLOUD_ENABLE_AUTH: 'true',
OXICLOUD_ENABLE_TRASH: 'true',
OXICLOUD_ENABLE_SEARCH: 'true',
OXICLOUD_ENABLE_FILE_SHARING: 'true',
OXICLOUD_WOPI_ENABLED: 'false',
OXICLOUD_OIDC_ENABLED: 'false',
RUST_LOG: 'warn',
},
},
});
-31
View File
@@ -1,31 +0,0 @@
const { execSync, spawnSync } = require('child_process');
const net = require('net');
const path = require('path');
const COMPOSE_FILE = path.join(__dirname, 'docker-compose.test.yml');
const CMD = `docker compose -f ${COMPOSE_FILE}`;
function waitForPort(host, port, timeoutMs = 30_000) {
const deadline = Date.now() + timeoutMs;
return new Promise((resolve, reject) => {
function attempt() {
const sock = net.connect(port, host);
sock.once('connect', () => { sock.destroy(); resolve(); });
sock.once('error', () => {
sock.destroy();
if (Date.now() >= deadline) return reject(new Error(`Timeout waiting for ${host}:${port}`));
setTimeout(attempt, 500);
});
}
attempt();
});
}
module.exports = async function globalSetup() {
console.log('[setup] Starting test postgres (database is empty) ...');
execSync(`${CMD} down`, { stdio: 'inherit' });
execSync(`${CMD} up -d`, { stdio: 'inherit' });
console.log('[setup] Waiting for postgres on port 5433...');
await waitForPort('127.0.0.1', 5433);
console.log('[setup] Postgres is ready.');
};
-9
View File
@@ -1,9 +0,0 @@
const { execSync } = require('child_process');
const path = require('path');
const COMPOSE_FILE = path.join(__dirname, 'docker-compose.test.yml');
module.exports = async function globalTeardown() {
console.log('[teardown] Stopping test postgres...');
execSync(`docker compose -f ${COMPOSE_FILE} down -v`, { stdio: 'inherit' });
};