2021-03-25 12:40:04 +00:00
|
|
|
'use strict'
|
|
|
|
|
|
|
|
const fs = require('fs')
|
|
|
|
const http = require('http')
|
|
|
|
const path = require('path')
|
|
|
|
const pkgJson = require('../../../package.json')
|
2022-04-20 21:55:44 +00:00
|
|
|
require('dotenv').config()
|
2021-03-25 12:40:04 +00:00
|
|
|
|
|
|
|
const rollup = require('rollup')
|
|
|
|
const resolve = require('@rollup/plugin-node-resolve').nodeResolve
|
|
|
|
const replace = require('@rollup/plugin-replace')
|
|
|
|
const multi = require('@rollup/plugin-multi-entry')
|
2022-04-20 21:55:44 +00:00
|
|
|
const typescriptPlugin = require('@rollup/plugin-typescript')
|
2021-03-25 12:40:04 +00:00
|
|
|
const commonjs = require('@rollup/plugin-commonjs')
|
2022-04-20 21:55:44 +00:00
|
|
|
const json = require('@rollup/plugin-json')
|
2022-10-03 17:57:08 +00:00
|
|
|
const runScript = require('../../run-script.cjs')
|
2021-03-25 12:40:04 +00:00
|
|
|
|
|
|
|
const rootDir = path.join(__dirname, '..', '..', '..')
|
|
|
|
|
|
|
|
const regex = /^(?:(?<scope>@.*?)\/)?(?<name>.*)/ // We are going to take only the package name part if there is a scope, e.g. @my-org/package-name
|
|
|
|
const { name } = pkgJson.name.match(regex).groups
|
|
|
|
|
|
|
|
const indexHtml = `<!DOCTYPE html>
|
|
|
|
<html>
|
|
|
|
<head>
|
|
|
|
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
|
|
|
<title>${name}</title>
|
|
|
|
<script src="/mocha.js"></script>
|
|
|
|
<script src="/chai.js"></script>
|
|
|
|
</head>
|
|
|
|
|
|
|
|
<body>
|
|
|
|
|
|
|
|
</body>
|
|
|
|
<div id="mocha"></div>
|
|
|
|
<script>
|
|
|
|
mocha.setup({
|
|
|
|
ui: 'bdd',
|
|
|
|
reporter: 'spec',
|
|
|
|
color: 'true',
|
|
|
|
timeout: 90000
|
|
|
|
})
|
|
|
|
</script>
|
2022-04-20 21:55:44 +00:00
|
|
|
<script type="module">
|
2021-03-25 12:40:04 +00:00
|
|
|
import './tests.js'
|
|
|
|
window._mocha = mocha.run()
|
|
|
|
</script>
|
|
|
|
</html>`
|
|
|
|
|
2022-04-20 21:55:44 +00:00
|
|
|
const tsBundleOptions = {
|
|
|
|
tsconfig: path.join(rootDir, 'tsconfig.json'),
|
|
|
|
outDir: undefined // ignore outDir in tsconfig.json
|
|
|
|
}
|
|
|
|
|
|
|
|
async function buildTests (testFiles) {
|
2021-03-25 12:40:04 +00:00
|
|
|
// create a bundle
|
2022-04-20 21:55:44 +00:00
|
|
|
const input = testFiles ?? [path.join(rootDir, pkgJson.directories.test, '**/*.ts'), path.join(rootDir, pkgJson.directories.src, '**/*.spec.ts')]
|
2021-03-25 12:40:04 +00:00
|
|
|
const inputOptions = {
|
2022-04-20 21:55:44 +00:00
|
|
|
input,
|
2021-03-25 12:40:04 +00:00
|
|
|
plugins: [
|
|
|
|
multi({ exports: true }),
|
2022-10-03 17:57:08 +00:00
|
|
|
replace({
|
|
|
|
'#pkg': `/${name}.esm.js`,
|
|
|
|
delimiters: ['', ''],
|
|
|
|
preventAssignment: true
|
|
|
|
}),
|
2021-03-25 12:40:04 +00:00
|
|
|
replace({
|
|
|
|
IS_BROWSER: true,
|
|
|
|
preventAssignment: true
|
|
|
|
}),
|
2022-04-20 21:55:44 +00:00
|
|
|
typescriptPlugin(tsBundleOptions),
|
2021-03-25 12:40:04 +00:00
|
|
|
resolve({
|
|
|
|
browser: true,
|
2022-10-03 17:57:08 +00:00
|
|
|
exportConditions: ['browser', 'default']
|
2021-03-25 12:40:04 +00:00
|
|
|
}),
|
2022-04-20 21:55:44 +00:00
|
|
|
commonjs(),
|
|
|
|
json()
|
2021-08-06 08:10:32 +00:00
|
|
|
],
|
2022-10-03 17:57:08 +00:00
|
|
|
external: [`/${name}.esm.js`]
|
2021-03-25 12:40:04 +00:00
|
|
|
}
|
|
|
|
const bundle = await rollup.rollup(inputOptions)
|
|
|
|
const { output } = await bundle.generate({ format: 'esm' })
|
|
|
|
await bundle.close()
|
2022-04-20 21:55:44 +00:00
|
|
|
let bundledCode = output[0].code
|
|
|
|
const replacements = _getEnvVarsReplacements(bundledCode)
|
|
|
|
for (const replacement in replacements) {
|
2022-10-03 17:57:08 +00:00
|
|
|
const regExp = new RegExp(replacement, 'g')
|
|
|
|
bundledCode = bundledCode.replace(regExp, replacements[replacement])
|
2022-04-20 21:55:44 +00:00
|
|
|
}
|
|
|
|
return bundledCode
|
2021-03-25 12:40:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
class TestServer {
|
|
|
|
constructor () {
|
|
|
|
this.server = http.createServer()
|
|
|
|
}
|
|
|
|
|
2022-04-20 21:55:44 +00:00
|
|
|
async init (testFiles) {
|
2022-10-03 17:57:08 +00:00
|
|
|
/** Let us first check if the necessary files are built, and if not, build */
|
|
|
|
if (!fs.existsSync(pkgJson.exports['./esm-browser-bundle'])) {
|
|
|
|
await runScript(path.join(rootDir, 'node_modules', '.bin', 'rollup'), ['-c', 'build/rollup.config.js'])
|
|
|
|
}
|
|
|
|
|
2022-04-20 21:55:44 +00:00
|
|
|
const tests = await buildTests(testFiles)
|
2021-03-25 12:40:04 +00:00
|
|
|
this.server.on('request', function (req, res) {
|
|
|
|
if (req.url === `/${name}.esm.js`) {
|
2022-10-03 17:57:08 +00:00
|
|
|
fs.readFile(path.join(rootDir, pkgJson.exports['./esm-browser-bundle']), function (err, data) {
|
2021-03-25 12:40:04 +00:00
|
|
|
if (err) {
|
|
|
|
res.writeHead(404)
|
|
|
|
res.end(JSON.stringify(err))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
res.writeHead(200, { 'Content-Type': 'text/javascript' })
|
|
|
|
res.end(data)
|
|
|
|
})
|
|
|
|
} else if (req.url === '/index.html' || req.url === '/') {
|
|
|
|
res.writeHead(200)
|
|
|
|
res.end(indexHtml)
|
|
|
|
} else if (req.url === '/tests.js') {
|
|
|
|
res.writeHead(200, { 'Content-Type': 'text/javascript' })
|
|
|
|
res.end(tests)
|
|
|
|
} else if (req.url === '/mocha.js') {
|
|
|
|
fs.readFile(path.join(rootDir, 'node_modules/mocha/mocha.js'), function (err, data) {
|
|
|
|
if (err) {
|
|
|
|
res.writeHead(404)
|
|
|
|
res.end(JSON.stringify(err))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
res.writeHead(200, { 'Content-Type': 'text/javascript' })
|
|
|
|
res.end(data)
|
|
|
|
})
|
|
|
|
} else if (req.url === '/chai.js' || req.url === '/chai') {
|
|
|
|
fs.readFile(path.join(rootDir, 'node_modules/chai/chai.js'), function (err, data) {
|
|
|
|
if (err) {
|
|
|
|
res.writeHead(404)
|
|
|
|
res.end(JSON.stringify(err))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
res.writeHead(200, { 'Content-Type': 'text/javascript' })
|
|
|
|
res.end(data)
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
res.writeHead(404)
|
|
|
|
res.end()
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
listen (port = 38080) {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
this.server.listen(port, error => {
|
|
|
|
if (error) return reject(error)
|
|
|
|
console.log(`Testing server listenning at http://localhost:${port}`)
|
|
|
|
return resolve()
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
close () {
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
this.server.close(error => (error) ? reject(error) : resolve())
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-20 21:55:44 +00:00
|
|
|
function _getEnvVarsReplacements (testsCode) {
|
|
|
|
const replacements = {}
|
|
|
|
const missingEnvVars = []
|
|
|
|
for (const match of testsCode.matchAll(/process\.env\.(\w+)/g)) {
|
|
|
|
const envVar = match[1]
|
|
|
|
if (process.env[envVar] !== undefined) {
|
|
|
|
replacements[match[0]] = '`' + process.env[envVar] + '`'
|
|
|
|
} else {
|
|
|
|
missingEnvVars.push(envVar)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (const match of testsCode.matchAll(/process\.env\[['"](\w+)['"]\]/g)) {
|
|
|
|
const envVar = match[1]
|
|
|
|
if (process.env[envVar] !== undefined) {
|
|
|
|
replacements[match[0]] = '`' + process.env[envVar] + '`'
|
|
|
|
} else {
|
|
|
|
missingEnvVars.push(envVar)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (missingEnvVars.length > 0) {
|
|
|
|
throw EvalError('The folloinwg environment variables are missing in your .env file: ' + missingEnvVars)
|
|
|
|
}
|
|
|
|
return replacements
|
|
|
|
}
|
|
|
|
|
2021-03-25 12:40:04 +00:00
|
|
|
exports.server = new TestServer()
|