forked from AmadeusITGroup/AgnosUI
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(test): only start servers when needed
Note that this change is also a workaround for: microsoft/playwright#18209
- Loading branch information
Showing
7 changed files
with
218 additions
and
81 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,13 @@ | ||
import setupCoverage from '@agnos-ui/code-coverage/setup'; | ||
import serversManager from './serversManager'; | ||
|
||
async function globalSetup() { | ||
return await setupCoverage(import.meta.dirname); | ||
const coverageTeardown = await setupCoverage(import.meta.dirname); | ||
const serversManagerTeardown = await serversManager(); | ||
return async () => { | ||
await serversManagerTeardown(); | ||
await coverageTeardown(); | ||
}; | ||
} | ||
|
||
export default globalSetup; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
import {spawn} from 'child_process'; | ||
import type {Server} from 'http'; | ||
import type {AddressInfo} from 'net'; | ||
import type {SampleInfo} from '../demo/src/lib/layout/sample'; | ||
|
||
interface RequestBody { | ||
project?: string; | ||
framework?: string; | ||
sampleKey?: string; | ||
sampleInfo?: Pick<SampleInfo, 'componentName' | 'sampleName' | 'style'>; | ||
} | ||
|
||
const isPreview = process.env.PREVIEW === 'true'; | ||
const includeCoverage = process.env.COVERAGE === 'true'; | ||
const coverageSuffix = includeCoverage ? ':coverage' : ''; | ||
const previewOrDev = isPreview ? 'preview' : 'dev'; | ||
const allServers = { | ||
angularDemoDevBootstrap: { | ||
command: `npm run -w angular/demo dev:bootstrap${coverageSuffix}`, | ||
url: 'http://localhost:4200', | ||
urlReadyPath: '/angular/samples/bootstrap/', | ||
}, | ||
angularDemoDevDaisyui: { | ||
command: `npm run -w angular/demo dev:daisyui${coverageSuffix}`, | ||
url: 'http://localhost:4201', | ||
urlReadyPath: '/angular/samples/daisyui/', | ||
}, | ||
reactDemoDev: { | ||
command: `npm run -w react/demo dev${coverageSuffix}`, | ||
url: 'http://localhost:3000', | ||
urlReadyPath: '/react/samples/bootstrap/', | ||
}, | ||
svelteDemoDev: { | ||
command: `npm run -w svelte/demo dev${coverageSuffix}`, | ||
url: 'http://localhost:3001', | ||
urlReadyPath: '/svelte/samples/bootstrap/', | ||
}, | ||
demoSite: { | ||
command: `npm run -w demo ${previewOrDev}${coverageSuffix}`, | ||
url: 'http://localhost:4000', | ||
urlReadyPath: '/', | ||
}, | ||
}; | ||
type ServerKey = keyof typeof allServers; | ||
|
||
const getNeededServersAndURL = ({project, framework, sampleInfo}: RequestBody) => { | ||
let url: string | undefined; | ||
const servers: ServerKey[] = []; | ||
switch (project) { | ||
case 'singlebrowser': | ||
case 'main': { | ||
let urlPath = '/'; | ||
if (framework) { | ||
if (sampleInfo) { | ||
urlPath = `/${framework}/samples/${sampleInfo.style}/#/${sampleInfo.componentName}/${sampleInfo.sampleName}`; | ||
} else { | ||
urlPath = `/${framework}/samples/bootstrap/`; | ||
} | ||
} | ||
if (isPreview) { | ||
servers.push('demoSite'); | ||
} else { | ||
switch (framework) { | ||
case 'angular': | ||
if (sampleInfo?.style === 'daisyui') { | ||
servers.push('angularDemoDevDaisyui'); | ||
} else { | ||
servers.push('angularDemoDevBootstrap'); | ||
} | ||
break; | ||
case 'react': | ||
servers.push('reactDemoDev'); | ||
break; | ||
case 'svelte': | ||
servers.push('svelteDemoDev'); | ||
break; | ||
} | ||
} | ||
url = `${allServers[servers[0]].url}${urlPath}`; | ||
break; | ||
} | ||
case 'demo': | ||
servers.push('demoSite'); | ||
if (!isPreview) { | ||
servers.push('angularDemoDevBootstrap', 'angularDemoDevDaisyui', 'reactDemoDev', 'svelteDemoDev'); | ||
} | ||
url = allServers.demoSite.url; | ||
break; | ||
} | ||
return {servers, url}; | ||
}; | ||
|
||
const isURLReady = async (url: string) => { | ||
try { | ||
const res = await fetch(url); | ||
return res.ok; | ||
} catch (error) { | ||
return false; | ||
} | ||
}; | ||
|
||
const startServer = async (serverKey: ServerKey, abortSignal: AbortSignal) => { | ||
const serverInfo = allServers[serverKey]; | ||
const url = `${serverInfo.url}${serverInfo.urlReadyPath}`; | ||
if (await isURLReady(url)) { | ||
// server is already running | ||
return; | ||
} | ||
const proc = spawn(allServers[serverKey].command, { | ||
shell: true, | ||
signal: abortSignal, | ||
stdio: 'inherit', | ||
}); | ||
|
||
proc.on('error', (error) => { | ||
// avoid displaying an error when the abort signal is triggered | ||
if (!abortSignal.aborted) { | ||
console.error(`Failed to start server ${serverKey}: ${error}`); | ||
} | ||
}); | ||
let urlReady = false; | ||
while (!urlReady && !abortSignal.aborted) { | ||
urlReady = await isURLReady(url); | ||
await new Promise((resolve) => setTimeout(resolve, 100)); | ||
} | ||
}; | ||
|
||
export default async () => { | ||
const serversStatus = new Map<ServerKey, Promise<void>>(); | ||
const abortController = new AbortController(); | ||
|
||
const ensureServerRuns = async (serverKey: ServerKey) => { | ||
let status = serversStatus.get(serverKey); | ||
if (!status) { | ||
console.log(`Starting server ${serverKey}`); | ||
status = startServer(serverKey, abortController.signal); | ||
serversStatus.set(serverKey, status); | ||
} | ||
return await status; | ||
}; | ||
|
||
const express = await import('express'); | ||
const app = express.default(); | ||
app.use(express.json()); | ||
|
||
app.post('/', async (req, res) => { | ||
try { | ||
const {servers, url} = getNeededServersAndURL(req.body); | ||
await Promise.all(servers.map(ensureServerRuns)); | ||
res.json({url}); | ||
} catch (error) { | ||
res.status(500).json({error: `${error}`}); | ||
} | ||
}); | ||
|
||
const server = await new Promise<Server>((resolve, reject) => { | ||
const server = app.listen(0, '127.0.0.1', () => resolve(server)).on('error', reject); | ||
}); | ||
const port = (server.address() as AddressInfo).port; | ||
const serverManagerURL = `http://127.0.0.1:${port}`; | ||
process.env.SERVERS_MANAGER_URL = serverManagerURL; | ||
console.log(`Server manager was started on ${serverManagerURL}`); | ||
return async () => { | ||
await new Promise((resolve) => { | ||
abortController.abort(); | ||
console.log('Closing server manager'); | ||
server.close(resolve); | ||
server.closeAllConnections(); | ||
}); | ||
}; | ||
}; |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.