/* eslint-disable no-console */ import axios from 'axios'; import { spawn, spawnSync } from 'child_process'; import knex from 'knex'; import { Listr } from 'listr2'; import { clone } from 'lodash-es'; import fs from 'node:fs/promises'; import { join } from 'node:path'; import config, { getUrl, paths } from '../common/config'; import vendors from '../common/get-dbs-to-test'; import { USER } from '../common/variables'; import { awaitDatabaseConnection, awaitDirectusConnection } from '../utils/await-connection'; import global from './global'; export async function setup() { console.log(`👮‍♀️ Starting tests!\n`); await new Listr([ { title: 'Bootstrap databases and start servers', task: async () => { return new Listr( vendors.map((vendor) => { return { title: config.names[vendor], task: async () => { const database = knex(config.knexConfig[vendor]); await awaitDatabaseConnection(database, config.knexConfig[vendor].waitTestSQL); if (vendor === 'sqlite3') { await fs.writeFile(join(paths.cwd, 'test.db'), ''); } const bootstrap = spawnSync('node', [paths.cli, 'bootstrap'], { cwd: paths.cwd, env: config.envs[vendor], }); if (bootstrap.status !== null && bootstrap.status !== 0) { throw new Error( `Directus-${vendor} bootstrap failed (${bootstrap.status}): \n ${bootstrap.stderr.toString()}`, ); } await database.migrate.latest(); await database.seed.run(); await database.destroy(); if (!process.env['TEST_LOCAL']) { const server = spawn('node', [paths.cli, 'start'], { cwd: paths.cwd, env: config.envs[vendor], }); global.directus[vendor] = server; let serverOutput = ''; server.stdout.setEncoding('utf8'); server.stdout.on('data', (data) => { serverOutput += data.toString(); }); server.stderr.on('data', (data) => { console.log(data.toString()); }); server.on('exit', async (code) => { if (process.env['TEST_SAVE_LOGS']) { await fs.writeFile(join(paths.cwd, `server-log-${vendor}.txt`), serverOutput); } if (code !== null) throw new Error(`Directus-${vendor} server failed (${code}): \n ${serverOutput}`); }); // Give the server some time to start await awaitDirectusConnection(Number(config.envs[vendor].PORT)); // Set up separate directus instance without system cache const noCacheEnv = clone(config.envs[vendor]); noCacheEnv['CACHE_SCHEMA'] = 'false'; noCacheEnv['PORT'] = String(parseInt(noCacheEnv.PORT) + 50); const serverNoCache = spawn('node', [paths.cli, 'start'], { cwd: paths.cwd, env: noCacheEnv }); global.directusNoCache[vendor] = serverNoCache; let serverNoCacheOutput = ''; serverNoCache.stdout.setEncoding('utf8'); serverNoCache.stdout.on('data', (data) => { serverNoCacheOutput += data.toString(); }); serverNoCache.on('exit', async (code) => { if (process.env['TEST_SAVE_LOGS']) { await fs.writeFile(join(paths.cwd, `server-log-${vendor}-no-cache.txt`), serverNoCacheOutput); } if (code !== null) { throw new Error(`Directus-${vendor}-no-cache server failed (${code}): \n ${serverNoCacheOutput}`); } }); // Give the server some time to start await awaitDirectusConnection(Number(noCacheEnv['PORT'])); } }, }; }), { concurrent: true, rendererOptions: { collapseErrors: false } }, ); }, }, { title: 'Test server connectivity', task: async () => { for (const vendor of vendors) { try { const serverUrl = getUrl(vendor); const response = await axios.get( `${serverUrl}/items/tests_flow_data?access_token=${USER.TESTS_FLOW.TOKEN}`, ); if (response.status === 200) { process.env['serverUrl'] = serverUrl; break; } } catch { continue; } } if (!process.env['serverUrl']) { throw new Error('Unable to connect to any Directus server'); } }, }, ]) .run() .catch((reason) => { for (const server of Object.values(global.directus)) { server?.kill(); } for (const serverNoCache of Object.values(global.directusNoCache)) { serverNoCache?.kill(); } throw new Error(reason); }); console.log('\n'); } export async function teardown() { try { await fs.unlink('sequencer-data.json'); } catch { // Ignore } if (!process.env['TEST_LOCAL']) { await new Listr([ { title: 'Stop Directus servers', task: () => { return new Listr( vendors.map((vendor) => { return { title: config.names[vendor]!, task: async () => { const directus = global.directus[vendor]; directus?.kill(); const directusNoCache = global.directusNoCache[vendor]; directusNoCache?.kill(); }, }; }), { concurrent: true, exitOnError: false }, ); }, }, ]).run(); } console.log('\n'); console.log(`👮‍♀️ Tests complete!\n`); }