diff --git a/frontend/test/__runner__/backend.js b/frontend/test/__runner__/cypress-runner-backend.js similarity index 52% rename from frontend/test/__runner__/backend.js rename to frontend/test/__runner__/cypress-runner-backend.js index a42d896623a39510982fcbb5dd7f32c8bf2016ea..1759e6db9a9258b16cb6eb472f13a38563f42c5e 100644 --- a/frontend/test/__runner__/backend.js +++ b/frontend/test/__runner__/cypress-runner-backend.js @@ -7,32 +7,21 @@ const { spawn } = require("child_process"); const fetch = require("isomorphic-fetch"); -let testDbId = 0; -const generateTempDbPath = () => - path.join(os.tmpdir(), `metabase-test-${process.pid}-${testDbId++}.db`); +const CypressBackend = { + createServer(port = 4000) { + const generateTempDbPath = () => + path.join(os.tmpdir(), `metabase-test-${process.pid}.db`); -let port = 4000; -const getPort = () => port++; - -const BackendResource = createSharedResource("BackendResource", { - create({ dbKey }) { - const dbFile = generateTempDbPath(); - const absoluteDbKey = dbKey ? __dirname + dbKey : dbFile; - const port = getPort(); - - return { - dbKey: absoluteDbKey, - dbFile: dbFile, + const server = { + dbFile: generateTempDbPath(), host: `http://localhost:${port}`, - port: port, + port, }; + + return server; }, async start(server) { if (!server.process) { - if (server.dbKey !== server.dbFile) { - fs.copyFileSync(`${server.dbKey}.mv.db`, `${server.dbFile}.mv.db`); - } - const javaFlags = [ "-XX:+IgnoreUnrecognizedVMOptions", // ignore options not recognized by this Java version (e.g. Java 8 should ignore Java 9 options) "-Dh2.bindAddress=localhost", // fix H2 randomly not working (?) @@ -95,32 +84,43 @@ const BackendResource = createSharedResource("BackendResource", { }, ); } + if (!(await isReady(server.host))) { process.stdout.write( - "Waiting for backend (host=" + - server.host + - " dbKey=" + - server.dbKey + - ")", + `Waiting for backend (host=${server.host}, dbFile=${server.dbFile})`, ); while (!(await isReady(server.host))) { if (!process.env["CI"]) { - // disable for CI since it break's CircleCI's no_output_timeout + // disable for CI since it breaks CircleCI's no_output_timeout process.stdout.write("."); } await delay(500); } process.stdout.write("\n"); } - console.log( - "Backend ready (host=" + server.host + " dbKey=" + server.dbKey + ")", - ); + + console.log(`Backend ready host=${server.host}, dbFile=${server.dbFile}`); + + // Copied here from `frontend/src/metabase/lib/promise.js` to decouple Cypress from Typescript + function delay(duration) { + return new Promise((resolve, reject) => setTimeout(resolve, duration)); + } + + async function isReady(host) { + try { + const { status } = await fetch(`${host}/api/health`); + if (status === 200) { + return true; + } + } catch (e) {} + return false; + } }, async stop(server) { if (server.process) { server.process.kill("SIGKILL"); console.log( - "Stopped backend (host=" + server.host + " dbKey=" + server.dbKey + ")", + `Stopped backend (host=${server.host}, dbFile=${server.dbFile})`, ); } try { @@ -129,69 +129,6 @@ const BackendResource = createSharedResource("BackendResource", { } } catch (e) {} }, -}); - -async function isReady(host) { - try { - const response = await fetch(`${host}/api/health`); - if (response.status === 200) { - return true; - } - } catch (e) {} - return false; -} - -function createSharedResource( - resourceName, - { defaultOptions, create, start, stop }, -) { - const entriesByKey = new Map(); - const entriesByResource = new Map(); - - function kill(entry) { - if (entriesByKey.has(entry.key)) { - entriesByKey.delete(entry.key); - entriesByResource.delete(entry.resource); - const p = stop(entry.resource).then(null, err => - console.log("Error stopping resource", resourceName, entry.key, err), - ); - return p; - } - } - - return { - get(options = defaultOptions) { - const dbKey = options; - const key = dbKey || {}; - let entry = entriesByKey.get(key); - if (!entry) { - entry = { - key: key, - references: 0, - resource: create(options), - }; - entriesByKey.set(entry.key, entry); - entriesByResource.set(entry.resource, entry); - } - ++entry.references; - return entry.resource; - }, - async start(resource) { - const entry = entriesByResource.get(resource); - return start(entry.resource); - }, - async stop(resource) { - const entry = entriesByResource.get(resource); - if (entry && --entry.references <= 0) { - await kill(entry); - } - }, - }; -} - -// Copied here from `frontend/src/metabase/lib/promise.js` to decouple Cypress from Typescript -function delay(duration) { - return new Promise((resolve, reject) => setTimeout(resolve, duration)); -} +}; -module.exports = BackendResource; +module.exports = CypressBackend; diff --git a/frontend/test/__runner__/run_cypress_tests.js b/frontend/test/__runner__/run_cypress_tests.js index 57fe23588de106cfce2f785d75eca42ab0901e87..00007475b919af33c764643ddbead59a54811bce 100644 --- a/frontend/test/__runner__/run_cypress_tests.js +++ b/frontend/test/__runner__/run_cypress_tests.js @@ -2,11 +2,11 @@ const { printBold } = require("./cypress-runner-utils"); const runCypress = require("./cypress-runner-run-tests"); const getVersion = require("./cypress-runner-get-version"); const generateSnapshots = require("./cypress-runner-generate-snapshots"); -const BackendResource = require("./backend.js"); +const CypressBackend = require("./cypress-runner-backend"); const e2eHost = process.env["E2E_HOST"]; -const server = BackendResource.get({ dbKey: "" }); +const server = CypressBackend.createServer(); const baseUrl = e2eHost || server.host; const init = async () => { @@ -15,7 +15,7 @@ const init = async () => { await getVersion(); printBold("Starting backend"); - await BackendResource.start(server); + await CypressBackend.start(server); printBold("Generating snapshots"); await generateSnapshots(baseUrl, cleanup); @@ -28,7 +28,7 @@ const init = async () => { const cleanup = async (exitCode = 0) => { if (!e2eHost) { printBold("Cleaning up..."); - await BackendResource.stop(server); + await CypressBackend.stop(server); } process.exit(exitCode);