-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
6,235 additions
and
3 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,31 @@ | ||
#! /usr/bin/env node | ||
console.log('hello from qunitx'); | ||
import fs from 'fs/promises'; | ||
import chalk from 'chalk'; | ||
import displayHelpOutput from './lib/commands/help.js'; | ||
|
||
process.title = 'qunitx'; | ||
|
||
(async () => { | ||
if (!process.argv[2]) { | ||
return await displayHelpOutput(); | ||
} else if (['help', 'h', 'p', 'print'].includes(process.argv[2])) { | ||
return await displayHelpOutput(); | ||
} | ||
|
||
const fileOrFolder = process.argv[2]; // then turn this to array of remaining args | ||
try { | ||
const entry = await fs.stat(fileOrFolder); | ||
|
||
if (entry.isDirectory()) { | ||
console.log('entry', entry, ' is directory'); | ||
} else if (entry.isFile()) { | ||
console.log('entry', entry, ' is file'); | ||
} | ||
} catch (error) { | ||
console.log(error); | ||
|
||
return process.exit(1); | ||
} | ||
// if file execute file | ||
})(); | ||
|
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,34 @@ | ||
import fs from 'fs/promises'; | ||
import chalk from 'chalk'; | ||
import { dirname } from 'path'; | ||
import { fileURLToPath } from 'url'; | ||
|
||
const __dirname = dirname(fileURLToPath(import.meta.url)); | ||
const highlight = (text) => chalk.magenta.bold(text); | ||
const color = (text) => chalk.blue(text); | ||
|
||
|
||
export default async function() { | ||
const config = JSON.parse((await fs.readFile(`${__dirname}/../../package.json`))); | ||
|
||
console.log(`${highlight("[qunitx v" + config.version + "] Usage:")} qunitx ${color('[targets] --$flags')} | ||
${highlight("Input options:")} | ||
- File: $ ${color('qunitx test/foo.js')} | ||
- Folder: $ ${color('qunitx test/login')} | ||
- Glob: $ ${color('qunitx test/**/*.ts')} | ||
- Regex: $ ${color('qunit *-test.ts')} | ||
- Combination: $ ${color('qunit test/foo.js test/bar.js test/logout app/e2e/submit-*.ts')} | ||
${highlight("Optional flags:")} | ||
${color('--browser')} [default] : run qunit tests in chromium instead of node.js(with puppeteer) | ||
${color('--node')} : run qunit tests in node.js without spawning a chromium/puppeteer | ||
${color('--debug')} : print console output when tests run in browser | ||
${color('--watch')} : run the target file or folders and watch them for continuous run | ||
${color('--failFast')} : run the target file or folders with immediate abort if a single test fails | ||
${color('--reporter')} : define a reporter | ||
${color('--coverage')} : define a coverage dist folder target(by default ./dist) | ||
${highlight("Example:")} $ ${color('qunitx test/foo.ts#204 app/e2e --debug --watch')} | ||
`); | ||
} |
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,132 @@ | ||
import chalk from 'ansi-colors'; | ||
import Puppeteer from 'puppeteer'; | ||
import WebSocket from 'ws'; | ||
import Console from '../utils/console.js'; | ||
|
||
const defaults = { port: 4200, debug: false, socketPort: 65511 }; | ||
|
||
export default async function(options = { port: 4200, debug: false, socketPort: 65511 }) { | ||
const OPTIONS = Object.assign({}, defaults, options); | ||
const WebSocketServer = new WebSocket.Server({ port: OPTIONS.socketPort }); | ||
|
||
WebSocketServer.on('connection', (webSocket) => { | ||
if (!OPTIONS.debug) { | ||
webSocket.on('message', (message) => { | ||
const { event, details } = JSON.parse(message); | ||
|
||
if (event === 'testDone') { | ||
if (details.failed > 0) { | ||
console.log( | ||
chalk.red('✘'), | ||
details.name, | ||
chalk.gray(`(${turnMStoSecond(details.runtime)}s)`) | ||
); | ||
details.assertions.forEach((assertion, index) => { | ||
if (assertion.result === false) { | ||
console.log( | ||
chalk.red('Assertion #' + (index + 1), ':'), | ||
assertion.message || 'This assertion fails' | ||
); | ||
} | ||
}); | ||
console.log(chalk.yellow('SOURCE:'), details.source); | ||
Console.error('THERE IS A FAILED TEST!'); | ||
|
||
return process.exit(1); | ||
} else if (details.skipped) { | ||
console.log(chalk.yellow('SKIP:'), details.name); | ||
} else if (details.todo) { | ||
console.log(chalk.blue('TODO:'), details.name); | ||
} else if (details.passed > 0) { | ||
console.log( | ||
chalk.green('✔'), | ||
details.name, | ||
chalk.gray(`(${turnMStoSecond(details.runtime)}s)`) | ||
); | ||
} | ||
} else if (event === 'moduleStart') { | ||
console.log(''); | ||
console.log(`${details.name}:`); | ||
} | ||
}); | ||
} | ||
}); | ||
|
||
const browser = await Puppeteer.launch({ | ||
executablePath: process.env.CHROME_BIN || null, | ||
headless: true, | ||
args: ['--no-sandbox', '--disable-gpu', '--remote-debugging-port=0', '--window-size=1440,900'] | ||
}); | ||
const page = await browser.newPage(); | ||
|
||
page.on('console', async (msg) => { | ||
if (OPTIONS.debug) { | ||
const args = await Promise.all(msg.args().map((arg) => turnToObjects(arg))); | ||
|
||
console.log(...args); | ||
} | ||
}); | ||
|
||
await page.goto(`http://localhost:${OPTIONS.port}/tests?hidepassed`, { timeout: 0 }); | ||
await page.addScriptTag({ | ||
content: ` | ||
window.MBER_TEST_TIME_COUNTER = (function() { | ||
const startTime = new Date(); | ||
return { | ||
start: startTime, | ||
stop: () => +(new Date()) - (+startTime) | ||
}; | ||
})(); | ||
window.QUnit.moduleStart((details) => { | ||
console.log('[', details.name, ']'); | ||
window.socket.send(JSON.stringify({ event: 'moduleStart', details: details })); | ||
}); | ||
window.QUnit.testDone((details) => { | ||
console.log(getTestStatusCode(details), \`\${details.module} |\`, details.name); | ||
window.socket.send(JSON.stringify({ event: 'testDone', details: details })); | ||
}); | ||
window.QUnit.done((details) => { | ||
window.QUNIT_RESULT = Object.assign(details, { | ||
timeTaken: window.MBER_TEST_TIME_COUNTER.stop() | ||
}); | ||
}); | ||
function getTestStatusCode(details) { | ||
if (details.failed > 0) { | ||
return 'NOT OK -'; | ||
} else if (details.skipped) { | ||
return 'SKIPPED -'; | ||
} else if (details.todo) { | ||
return 'TODO -'; | ||
} else if (details.passed > 0) { | ||
return 'OK -'; | ||
} | ||
}` | ||
}); | ||
await page.waitForFunction('window.QUNIT_RESULT', { timeout: 0 }); | ||
|
||
const QUNIT_RESULT = await page.evaluate(() => window.QUNIT_RESULT); | ||
|
||
await browser.close(); | ||
|
||
if (QUNIT_RESULT.failed > 0) { | ||
Console.error('THERE IS A FAILED TEST!'); | ||
|
||
return process.exit(1); | ||
} | ||
|
||
Console.log(chalk.green(`ALL TESTS PASS in ${turnMStoSecond(QUNIT_RESULT.timeTaken)} seconds!`)); | ||
process.exit(); | ||
} | ||
|
||
function turnToObjects(jsHandle) { | ||
return jsHandle.jsonValue(); | ||
} | ||
|
||
function turnMStoSecond(timeInMS) { | ||
return (timeInMS / 1000).toFixed(2); | ||
} |
Oops, something went wrong.