545e421423
Github action CI workflows added for webdriver tests.
I've also refactored the `./scripts/e2e-*` scripts. These scripts were
somewhat unique compared to the other scripts. They are now more inline
with the other scripts in that directory and run via
```
% yarn e2e --help
Usage: yarn e2e <command> [options]
Commands:
yarn e2e serve start test server
yarn e2e test:ci [env] runner for CI (github-actions)
yarn e2e test:local run webdriver tests locally
yarn e2e test:browserstack run webdriver tests on browserstack
yarn e2e selenium:grid start selenium grid (test linux)
Options:
--help Show help [boolean]
--version Show version number [boolean]
```
I've also added an experimental linux runner see
2cca4ddb77/e2e/README.md (L320-L333)
### Change Type
- [x] `tests` — Changes to any testing-related code only (will not
publish a new version)
### Release Notes
- Github action CI workflows added for webdriver tests
- Refactored e2e test runner
202 lines
5.2 KiB
JavaScript
202 lines
5.2 KiB
JavaScript
// @ts-nocheck
|
|
/* eslint-disable */
|
|
|
|
import browserslist from 'browserslist-to-esbuild'
|
|
import crypto from 'crypto'
|
|
import esbuild from 'esbuild'
|
|
import { createServer as createNonSslServer, request } from 'http'
|
|
import { createServer as createSslServer } from 'https'
|
|
import ip from 'ip'
|
|
import chalk from 'kleur'
|
|
import forge from 'node-forge'
|
|
import * as url from 'url'
|
|
|
|
const LOG_REQUEST_PATHS = false
|
|
|
|
export const generateCert = ({ altNameIPs, altNameURIs, validityDays }) => {
|
|
const keys = forge.pki.rsa.generateKeyPair(2048)
|
|
const cert = forge.pki.createCertificate()
|
|
cert.publicKey = keys.publicKey
|
|
|
|
// NOTE: serialNumber is the hex encoded value of an ASN.1 INTEGER.
|
|
// Conforming CAs should ensure serialNumber is:
|
|
// - no more than 20 octets
|
|
// - non-negative (prefix a '00' if your value starts with a '1' bit)
|
|
cert.serialNumber = '01' + crypto.randomBytes(19).toString('hex') // 1 octet = 8 bits = 1 byte = 2 hex chars
|
|
cert.validity.notBefore = new Date()
|
|
cert.validity.notAfter = new Date(
|
|
new Date().getTime() + 1000 * 60 * 60 * 24 * (validityDays ?? 1)
|
|
)
|
|
const attrs = [
|
|
{
|
|
name: 'countryName',
|
|
value: 'AU',
|
|
},
|
|
{
|
|
shortName: 'ST',
|
|
value: 'Some-State',
|
|
},
|
|
{
|
|
name: 'organizationName',
|
|
value: 'Temporary Testing Department Ltd',
|
|
},
|
|
]
|
|
cert.setSubject(attrs)
|
|
cert.setIssuer(attrs)
|
|
|
|
// add alt names so that the browser won't complain
|
|
cert.setExtensions([
|
|
{
|
|
name: 'subjectAltName',
|
|
altNames: [
|
|
...(altNameURIs !== undefined ? altNameURIs.map((uri) => ({ type: 6, value: uri })) : []),
|
|
...(altNameIPs !== undefined ? altNameIPs.map((uri) => ({ type: 7, ip: uri })) : []),
|
|
],
|
|
},
|
|
])
|
|
// self-sign certificate
|
|
cert.sign(keys.privateKey)
|
|
|
|
// convert a Forge certificate and private key to PEM
|
|
const pem = forge.pki.certificateToPem(cert)
|
|
const privateKey = forge.pki.privateKeyToPem(keys.privateKey)
|
|
|
|
return {
|
|
cert: pem,
|
|
privateKey,
|
|
}
|
|
}
|
|
|
|
const { log } = console
|
|
|
|
const dirname = url.fileURLToPath(new URL('.', import.meta.url))
|
|
|
|
const PORT = 5420
|
|
const SSL_PORT = 5421
|
|
const ENABLE_SSL = process.env.ENABLE_SSL === '1'
|
|
const ENABLE_NETWORK_CACHING = process.env.ENABLE_NETWORK_CACHING === '1'
|
|
const OUT_DIR = dirname + '/../www/'
|
|
|
|
const clients = []
|
|
|
|
async function main() {
|
|
await esbuild.build({
|
|
entryPoints: ['src/index.tsx'],
|
|
outdir: OUT_DIR,
|
|
bundle: true,
|
|
minify: false,
|
|
sourcemap: true,
|
|
incremental: true,
|
|
format: 'cjs',
|
|
external: ['*.woff'],
|
|
target: browserslist(['defaults']),
|
|
define: {
|
|
process: '{ "env": { "NODE_ENV": "development"} }',
|
|
},
|
|
loader: {
|
|
'.woff2': 'file',
|
|
'.svg': 'file',
|
|
'.json': 'file',
|
|
'.png': 'file',
|
|
},
|
|
watch: {
|
|
onRebuild(error) {
|
|
log('rebuilt')
|
|
if (error) {
|
|
log(error)
|
|
}
|
|
clients.forEach((res) => res.write('data: update\n\n'))
|
|
clients.length = 0
|
|
},
|
|
},
|
|
})
|
|
|
|
esbuild.serve({ servedir: OUT_DIR, port: 8009 }, {}).then(({ host, port: esbuildPort }) => {
|
|
const handler = async (req, res) => {
|
|
const { url, method, headers } = req
|
|
if (req.url === '/esbuild')
|
|
return clients.push(
|
|
res.writeHead(200, {
|
|
'Content-Type': 'text/event-stream',
|
|
'Cache-Control': 'no-cache',
|
|
Connection: 'keep-alive',
|
|
})
|
|
)
|
|
|
|
function forwardRequest(url) {
|
|
const path = (url?.split('/').pop()?.indexOf('.') ?? -1) > -1 ? url : `/index.html` //for PWA with router
|
|
|
|
if (LOG_REQUEST_PATHS) {
|
|
console.log('[%s]=', method, path)
|
|
}
|
|
|
|
const req2 = request(
|
|
{ hostname: host, port: esbuildPort, path, method, headers },
|
|
(prxRes) => {
|
|
const newHeaders = {
|
|
...prxRes.headers,
|
|
}
|
|
|
|
if (ENABLE_NETWORK_CACHING) {
|
|
const hrInSeconds = 60*60*60
|
|
newHeaders['cache-control'] = `max-age=${hrInSeconds}`;
|
|
}
|
|
|
|
if (url === '/index.js') {
|
|
const jsReloadCode =
|
|
' (() => new EventSource("/esbuild").onmessage = () => location.reload())();'
|
|
|
|
newHeaders['content-length'] = parseInt(prxRes.headers['content-length'] ?? '0', 10) + jsReloadCode.length,
|
|
|
|
res.writeHead(prxRes.statusCode ?? 0, newHeaders)
|
|
res.write(jsReloadCode)
|
|
} else {
|
|
res.writeHead(prxRes.statusCode ?? 0, newHeaders)
|
|
}
|
|
prxRes.pipe(res, { end: true })
|
|
}
|
|
)
|
|
|
|
req.pipe(req2, { end: true })
|
|
}
|
|
|
|
forwardRequest(url ?? '/')
|
|
}
|
|
|
|
const nonSslServer = createNonSslServer(handler)
|
|
nonSslServer.on('error', function (e) {
|
|
// Handle your error here
|
|
console.log(e)
|
|
})
|
|
nonSslServer.listen(PORT, () => {
|
|
log(`Running on:\n`)
|
|
log(chalk.bold().cyan(` http://localhost:${PORT}`))
|
|
log(`\nNetwork:\n`)
|
|
log(chalk.bold().cyan(` http://${ip.address()}:${PORT}`))
|
|
})
|
|
|
|
if (ENABLE_SSL) {
|
|
const cert = generateCert({
|
|
altNameIPs: ['127.0.0.1'],
|
|
altNameURIs: ['localhost'],
|
|
validityDays: 2,
|
|
})
|
|
const sslServer = createSslServer({ key: cert.privateKey, cert: cert.cert }, handler)
|
|
sslServer.on('error', function (e) {
|
|
// Handle your error here
|
|
console.log(e)
|
|
})
|
|
sslServer.listen(SSL_PORT, () => {
|
|
// TODO: Nasty, but gets detected by script runner
|
|
log('[tldraw:process_ready]');
|
|
|
|
log(`Running on:\n`)
|
|
log(chalk.bold().cyan(` https://localhost:${SSL_PORT}`))
|
|
log(`\nNetwork:\n`)
|
|
log(chalk.bold().cyan(` https://${ip.address()}:${SSL_PORT}`))
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
main()
|