global-setup.js 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. const { execSync } = require('node:child_process');
  2. const http = require('node:http');
  3. const https = require('node:https');
  4. const COMPOSE_FILE = 'tests/docker-compose-playwright.yml';
  5. function isHttpOk(url, requestTimeoutMs = 10_000) {
  6. return new Promise((resolve) => {
  7. const client = url.startsWith('https://') ? https : http;
  8. let settled = false;
  9. const settle = (value) => {
  10. if (settled) {
  11. return;
  12. }
  13. settled = true;
  14. resolve(value);
  15. };
  16. const req = client.get(url, (res) => {
  17. const status = res.statusCode || 0;
  18. // Drain body so sockets can be reused/closed cleanly.
  19. res.resume();
  20. settle(status >= 200 && status < 300);
  21. });
  22. req.setTimeout(requestTimeoutMs, () => {
  23. req.destroy(new Error(`Request timed out after ${requestTimeoutMs}ms`));
  24. });
  25. req.on('timeout', () => {
  26. req.destroy(new Error(`Request timed out after ${requestTimeoutMs}ms`));
  27. });
  28. req.on('error', () => {
  29. // Connection issues/timeouts are expected while services are starting.
  30. settle(false);
  31. });
  32. });
  33. }
  34. async function waitForReady(name, url, timeoutMs) {
  35. const start = Date.now();
  36. while (Date.now() - start < timeoutMs) {
  37. try {
  38. if (await isHttpOk(url)) {
  39. return;
  40. }
  41. } catch {
  42. // Retry until timeout.
  43. }
  44. await new Promise((resolve) => setTimeout(resolve, 1000));
  45. }
  46. throw new Error(`Timed out waiting for ${name} at ${url}`);
  47. }
  48. module.exports = async () => {
  49. try {
  50. execSync(`docker compose -f ${COMPOSE_FILE} up -d --build`, {
  51. stdio: 'inherit',
  52. });
  53. } catch (error) {
  54. throw new Error(
  55. `Failed to start Docker test stack from ${COMPOSE_FILE}. ` +
  56. `Ensure Docker is running. Original error: ${error.message}`
  57. );
  58. }
  59. const timeoutMs = 180_000;
  60. await waitForReady('standalone', 'http://127.0.0.1:18180/index.html', timeoutMs);
  61. await waitForReady('standalone-new', 'http://127.0.0.1:18185/index.html', timeoutMs);
  62. await waitForReady('backend', 'http://127.0.0.1:18181/empty.php', timeoutMs);
  63. await waitForReady('frontend', 'http://127.0.0.1:18182/index-modern.html', timeoutMs);
  64. await waitForReady('dual', 'http://127.0.0.1:18183/index-modern.html', timeoutMs);
  65. };