UNPKG

koot

Version:

Koot.js - React isomorphic framework created by CMUX

281 lines (242 loc) 9.87 kB
const fs = require('fs-extra') const path = require('path') const util = require('util') const execSync = require('child_process').exec const exec = util.promisify(execSync) const puppeteer = require('puppeteer') const doTerminate = require('terminate') // const { dir: dirProjects, projects, commandTestBuild } = require('../projects') const projectsToUse = projects.filter(project => ( Array.isArray(project.type) && project.type.includes('react-isomorphic') )) const { changeLocaleQueryKey } = require('../../defaults/defines') // const sleep = require('../../utils/sleep') // global.kootTest = true process.env.KOOT_TEST_MODE = JSON.stringify(true) // const addCommand = async (name, command, dir) => { const pathPackage = path.resolve(dir, 'package.json') const p = await fs.readJson(pathPackage) // if (!p.scripts[name]) p.scripts[name] = command await fs.writeJson(pathPackage, p, { spaces: 4 }) } const terminate = async (pid) => new Promise((resolve, reject) => { doTerminate(pid, err => { if (err) return reject(err) resolve() }) }) const waitForPort = async (child, regex = /port.*\[32m([0-9]+)/) => await new Promise(resolve => { let port child.stdout.on('data', msg => { // console.log(msg) try { const obj = JSON.parse(msg) if (obj['koot-test']) { port = obj.port } } catch (e) { } if (!port) { const matches = regex.exec(msg) if (Array.isArray(matches) && matches.length > 1) { port = parseInt(matches[1]) } } if (port) { return resolve(port) } }) }) const testPage = async (port) => { const browser = await puppeteer.launch({ // headless: false }) const page = await browser.newPage() const url = isNaN(port) ? port : `http://127.0.0.1:${port}` { const res = await page.goto(url, { waitUntil: 'networkidle0' }).catch() const pageTitle = await page.evaluate(() => document.querySelector('title').innerText) const $app = await page.$('#app') expect(res.ok()).toBe(true) expect(typeof pageTitle).toBe('string') expect(typeof $app).toBe('object') } { await page.goto(`${url}?${changeLocaleQueryKey}=zh`, { waitUntil: 'networkidle0' }) const localeId = await page.evaluate(() => document.querySelector('meta[name="koot-locale-id"]').getAttribute('content')) expect(localeId).toBe('zh') } { await page.goto(`${url}?${changeLocaleQueryKey}=en`, { waitUntil: 'networkidle0' }) const localeId = await page.evaluate(() => document.querySelector('meta[name="koot-locale-id"]').getAttribute('content')) expect(localeId).toBe('en') } const testLinksToOtherLang = async (urlAppend) => { await page.goto(`${url}${urlAppend}`, { waitUntil: 'networkidle0' }) const localeId = await page.evaluate(() => document.querySelector('meta[name="koot-locale-id"]').getAttribute('content')) const linksToOtherLang = await page.$$eval(`link[rel="alternate"][hreflang][href]:not([hreflang="${localeId}"])`, els => ( Array.from(els).map(el => ({ lang: el.getAttribute('hreflang'), href: el.getAttribute('href') })) )) expect(Array.isArray(linksToOtherLang)).toBe(true) expect(linksToOtherLang.length).toBeGreaterThan(0) for (let { lang, href } of linksToOtherLang) { await page.goto(href, { waitUntil: 'networkidle0' }) const localeId = await page.evaluate(() => document.querySelector('meta[name="koot-locale-id"]').getAttribute('content')) expect(lang).toBe(localeId) } } await testLinksToOtherLang('') await testLinksToOtherLang(`?${changeLocaleQueryKey}=zh`) await testLinksToOtherLang('?test=a') await testLinksToOtherLang(`?test=a&${changeLocaleQueryKey}=zh`) await browser.close() } // describe('测试: React 同构项目', async () => { for (let project of projectsToUse) { const { name } = project const dir = path.resolve(dirProjects, name) describe(`项目: ${name}`, async () => { test(`[Production] 使用 koot-build 命令进行打包`, async () => { const commandName = `${commandTestBuild}-isomorphic-build` const command = `koot-build --env prod --koot-test` await addCommand(commandName, command, dir) const { /*stdout,*/ stderr } = await exec( `npm run ${commandName}`, { cwd: dir, } ) expect(typeof stderr).toBe('string') expect(stderr).toBe('') }) test(`[Production] 使用 koot-start (--no-build) 命令启动服务器并访问`, async () => { const commandName = `${commandTestBuild}-isomorphic-start-server` const command = `koot-start --no-build` await addCommand(commandName, command, dir) const child = execSync( `npm run ${commandName}`, { cwd: dir, }, // (err, stdout, stderr) => { // console.log('err', err) // console.log('stdout', stdout) // console.log('stderr', stderr) // } ) const errors = [] // child.stdin.pipe(process.stdin) // child.stdout.pipe(process.stdout) // child.stderr.pipe(process.stderr) const port = await waitForPort(child) child.stderr.on('data', err => { errors.push(err) }) // console.log({ // port, // errors, // }) expect(errors.length).toBe(0) await testPage(port) await terminate(child.pid) }) test(`[Production] 使用 koot-start (--no-build) 命令启动服务器并访问 (自定义端口号)`, async () => { const port = '8316' const commandName = `${commandTestBuild}-isomorphic-start-server-custom-port` const command = `koot-start --no-build --port ${port}` await addCommand(commandName, command, dir) const child = execSync( `npm run ${commandName}`, { cwd: dir, }, // (err, stdout, stderr) => { // console.log('err', err) // console.log('stdout', stdout) // console.log('stderr', stderr) // } ) const errors = [] // child.stdin.pipe(process.stdin) // child.stdout.pipe(process.stdout) // child.stderr.pipe(process.stderr) child.stderr.on('data', err => { errors.push(err) }) // console.log(111) await waitForPort(child) // console.log(222) // console.log({ // port, // errors, // }) expect(errors.length).toBe(0) await testPage(port) await terminate(child.pid) }) test(`[Production] 使用打包后的执行文件启动服务器并访问`, async () => { const cwd = path.resolve(dir, 'dist') const child = execSync( `node ${path.resolve(cwd, 'index.js')}`, { cwd, }, ) const errors = [] const port = await waitForPort(child) child.stderr.on('data', err => { errors.push(err) }) // console.log({ // port, // errors, // }) expect(errors.length).toBe(0) await testPage(port) await terminate(child.pid) }) test(`[Development] 启动开发模式并访问`, async () => { // const port = '8316' const commandName = `${commandTestBuild}-isomorphic-dev` const command = `koot-dev --no-open` await addCommand(commandName, command, dir) const child = execSync( `npm run ${commandName}`, { cwd: dir, }, ) const errors = [] const port = await waitForPort(child, / on.*http:.*:([0-9]+)/) child.stderr.on('data', err => { errors.push(err) }) // console.log({ // port, // errors, // }) expect(errors.length).toBe(0) await testPage(port) await terminate(child.pid) }) }) } })