PronounsPage/server/initTestDatabase.ts
Adaline Simonian 23a3862ca0
test: introduce snapshot-based smoke tests
- Adds a new test suite with Docker-based smoke tests for all locales.
  Can be run using the ./smoketest.sh script.
- Replaces all calls to Math.random() with a new helper that returns 0.5
  in snapshot testing mode, ensuring deterministic snapshots.
- Similarly replaces all calls to new Date() and Date.now() with new
  helpers that return a fixed date in snapshot testing mode.
- Replaces checks against NODE_ENV with APP_ENV, to ensure that the
  bundles can be built with Nuxt for testing without losing code that
  would otherwise be stripped out by production optimizations.
- Adds a database init script that can be used to initialize the
  database with a single admin user and a long-lived JWT token for use
  in automation tests.
- Adds a JWT decoding/encoding CLI tool for debugging JWTs.

Note: Snapshots are not checked in, and must be generated manually. See
test/__snapshots__/.gitignore for more information.
2025-02-02 23:11:19 -08:00

94 lines
2.5 KiB
TypeScript

import SQL from 'sql-template-strings';
import { ulid } from 'ulid';
import dbConnection from './db.ts';
import dotenv from './dotenv.ts';
import { env } from './env.ts';
import jwt from './jwt.ts';
// This module creates a test user in the database with the username "admin"
// that has the "*" role. It also creates an authentication token for the user,
// and returns the token. This token can be used to authenticate as the admin
// user in tests.
// This module should never be used in production code. It is only for testing
// purposes.
const __dirname = new URL('.', import.meta.url).pathname;
if (env !== 'development') {
throw new Error('This script should only be run in development mode');
}
/**
* Sets up environment variables.
*/
function setupEnv(): void {
dotenv();
// Replace port 3000 in BASE_URL and ALL_LOCALES_URLS with port from PORT
if (process.env.PORT) {
process.env.BASE_URL =
process.env.BASE_URL?.replace(/:3000\b/g, `:${process.env.PORT}`);
process.env.ALL_LOCALES_URLS =
process.env.ALL_LOCALES_URLS?.replaceAll(/:3000\b/g, `:${process.env.PORT}`);
}
}
/**
* Runs the migrations in the migrations directory.
*/
async function migrate(): Promise<void> {
const db = await dbConnection();
await db.migrate({ migrationsPath: `${__dirname}/../migrations` });
await db.close();
}
/**
* Creates a test database with a test user named "admin" with the role "*".
* Creates an authentication token and prints it to stdout.
*/
async function initTestDatabase(): Promise<string> {
const db = await dbConnection();
await db.get(SQL`
INSERT OR IGNORE INTO users (id, username, usernameNorm, email, roles, avatarSource, lastActive)
VALUES (
${ulid()},
'admin',
'admin',
'admin@example.com',
'*',
null,
strftime('%s','now')*1000
)
`);
const adminId = (await db.get(SQL`
SELECT id FROM users WHERE username = 'admin'
`))?.id;
if (typeof adminId !== 'string') {
throw new Error('Admin user not created');
}
const adminUser = {
id: adminId,
username: 'admin',
email: 'admin@example.com',
roles: '*',
authenticated: true,
};
const token = await jwt.sign(adminUser, '3650d');
await db.close();
return token;
}
setupEnv();
await migrate();
const token = await initTestDatabase();
console.log(token);