(@wdio/spec-reporter): introduce color option to disable colors for spec reporter (#12092)
* disable colored output in @wdio/spec-reporter * issue's test cases added and comments resolved * enums added and snapshot updated - ChalkColor and State enum added - snapshot updated - code is refactored accordingly * comments resolved * chalk usage updated
This commit is contained in:
parent
694ea755ee
commit
0bd4db52c2
10 changed files with 212 additions and 136 deletions
|
|
@ -1,10 +1,11 @@
|
|||
import { vi } from 'vitest'
|
||||
|
||||
import { EventEmitter } from 'node:events'
|
||||
import HookStats from '../../packages/wdio-reporter/src/stats/hook'
|
||||
import RunnerStats from '../../packages/wdio-reporter/src/stats/runner'
|
||||
import SuiteStats from '../../packages/wdio-reporter/src/stats/suite'
|
||||
import TestStats from '../../packages/wdio-reporter/src/stats/test'
|
||||
import HookStats from '../../packages/wdio-reporter/src/stats/hook.ts'
|
||||
import RunnerStats from '../../packages/wdio-reporter/src/stats/runner.ts'
|
||||
import SuiteStats from '../../packages/wdio-reporter/src/stats/suite.ts'
|
||||
import TestStats from '../../packages/wdio-reporter/src/stats/test.ts'
|
||||
import { Chalk } from '../chalk.ts'
|
||||
|
||||
export default class WDIOReporter extends EventEmitter {
|
||||
outputStream: { write: Function }
|
||||
|
|
@ -22,6 +23,7 @@ export default class WDIOReporter extends EventEmitter {
|
|||
failures: number
|
||||
}
|
||||
retries: number
|
||||
_chalk: Chalk
|
||||
runnerStat?: RunnerStats
|
||||
constructor (public options: any) {
|
||||
super()
|
||||
|
|
@ -41,6 +43,7 @@ export default class WDIOReporter extends EventEmitter {
|
|||
failures: 0
|
||||
}
|
||||
this.retries = 0
|
||||
this._chalk = new Chalk(!options.color ? { level : 0 } : {})
|
||||
}
|
||||
|
||||
get isSynchronised () {
|
||||
|
|
@ -79,4 +82,4 @@ export default class WDIOReporter extends EventEmitter {
|
|||
onRunnerEnd () {}
|
||||
}
|
||||
|
||||
export { HookStats, RunnerStats, SuiteStats, TestStats }
|
||||
export { HookStats, RunnerStats, SuiteStats, TestStats }
|
||||
|
|
|
|||
|
|
@ -1,26 +1,33 @@
|
|||
import { vi } from 'vitest'
|
||||
|
||||
const chalkMock: any = {}
|
||||
chalkMock.cyanBright = vi.fn().mockImplementation((msg) => `cyanBright ${msg}`)
|
||||
chalkMock.greenBright = vi.fn().mockImplementation((msg) => `greenBright ${msg}`)
|
||||
chalkMock.whiteBright = vi.fn().mockImplementation((msg) => `whiteBright ${msg}`)
|
||||
chalkMock.redBright = vi.fn().mockImplementation((msg) => `redBright ${msg}`)
|
||||
chalkMock.cyan = vi.fn().mockImplementation((msg) => `cyan ${msg}`)
|
||||
chalkMock.blue = vi.fn().mockImplementation((msg) => `blue ${msg}`)
|
||||
chalkMock.grey = vi.fn().mockImplementation((msg) => `grey ${msg}`)
|
||||
chalkMock.green = vi.fn().mockImplementation((msg) => `green ${msg}`)
|
||||
chalkMock.red = vi.fn().mockImplementation((...msg: string[]) => `red ${msg.join(' ')}`)
|
||||
chalkMock.gray = vi.fn().mockImplementation((...msg: string[]) => `gray ${msg.join(' ')}`)
|
||||
chalkMock.black = vi.fn().mockImplementation((msg) => `black ${msg}`)
|
||||
chalkMock.white = chalkMock
|
||||
chalkMock.yellow = vi.fn().mockImplementation((...msg: string[]) => `yellow ${msg.join(' ')}`)
|
||||
chalkMock.magenta = vi.fn().mockImplementation((msg) => `magenta ${msg}`)
|
||||
chalkMock.bgGreen = vi.fn().mockImplementation((msg) => `bgGreen ${msg}`)
|
||||
chalkMock.dim = vi.fn().mockImplementation((msg) => `dim ${msg}`)
|
||||
chalkMock.supportsColor = { hasBasic: true }
|
||||
chalkMock.bgYellow = chalkMock
|
||||
chalkMock.bgRed = chalkMock
|
||||
chalkMock.bold = function (msg: string) { return `bold ${msg}` }
|
||||
chalkMock.bold.__proto__ = chalkMock
|
||||
class Chalk {
|
||||
supportsColor = { hasBasic: true }
|
||||
|
||||
export default chalkMock
|
||||
private color = true
|
||||
constructor(options:{level?:number}){
|
||||
this.color = options.level === 0 ? false : this.color
|
||||
}
|
||||
|
||||
bold(msg: string) { return `bold ${msg}` }
|
||||
bgYellow(msg: string) { return `bgYellow ${msg}` }
|
||||
bgRed(msg: string) { return `bgRed ${msg}` }
|
||||
cyanBright = vi.fn().mockImplementation((msg) => this.color ? `cyanBright ${msg}` : msg)
|
||||
greenBright = vi.fn().mockImplementation((msg) => this.color ? `greenBright ${msg}` : msg)
|
||||
whiteBright = vi.fn().mockImplementation((msg) => this.color ? `whiteBright ${msg}` : msg)
|
||||
redBright = vi.fn().mockImplementation((msg) => this.color ? `redBright ${msg}` : msg)
|
||||
cyan = vi.fn().mockImplementation((msg) => this.color ? `cyan ${msg}` : msg)
|
||||
white = vi.fn().mockImplementation((msg) => this.color ? `white ${msg}` : msg)
|
||||
blue = vi.fn().mockImplementation((msg) => this.color ? `blue ${msg}` : msg)
|
||||
grey = vi.fn().mockImplementation((msg) => this.color ? `grey ${msg}` : msg)
|
||||
green = vi.fn().mockImplementation((msg) => this.color ? `green ${msg}` : msg)
|
||||
red = vi.fn().mockImplementation((...msg: string[]) => this.color ? `red ${msg.join(' ')}` : msg.join(' '))
|
||||
gray = vi.fn().mockImplementation((...msg: string[]) => this.color ? `gray ${msg.join(' ')}` : msg.join(' '))
|
||||
black = vi.fn().mockImplementation((msg) => this.color ? `black ${msg}` : msg)
|
||||
yellow = vi.fn().mockImplementation((...msg: string[]) => this.color ? `yellow ${msg.join(' ')}` : msg.join(' '))
|
||||
magenta = vi.fn().mockImplementation((msg) => this.color ? `magenta ${msg}` : msg)
|
||||
bgGreen = vi.fn().mockImplementation((msg) => this.color ? `bgGreen ${msg}` : msg)
|
||||
dim = vi.fn().mockImplementation((msg) => this.color ? `dim ${msg}` : msg)
|
||||
}
|
||||
|
||||
export default new Chalk({})
|
||||
export { Chalk }
|
||||
|
|
|
|||
|
|
@ -112,16 +112,16 @@ export default class WDIOCLInterface extends EventEmitter {
|
|||
: ''
|
||||
this.log(chalk.bold(`\nExecution of ${chalk.blue(this.totalWorkerCnt)} workers${shardNote} started at`), this._start.toISOString())
|
||||
if (this._inDebugMode) {
|
||||
this.log(chalk.bgYellow.black('DEBUG mode enabled!'))
|
||||
this.log(chalk.bgYellow(chalk.black('DEBUG mode enabled!')))
|
||||
}
|
||||
if (this._isWatchMode) {
|
||||
this.log(chalk.bgYellow.black('WATCH mode enabled!'))
|
||||
this.log(chalk.bgYellow(chalk.black('WATCH mode enabled!')))
|
||||
}
|
||||
this.log('')
|
||||
}
|
||||
|
||||
onSpecRunning (rid: string) {
|
||||
this.onJobComplete(rid, this._jobs.get(rid), 0, chalk.bold.cyan('RUNNING'))
|
||||
this.onJobComplete(rid, this._jobs.get(rid), 0, chalk.bold(chalk.cyan('RUNNING')))
|
||||
}
|
||||
|
||||
onSpecRetry (rid: string, job?: Workers.Job, retries = 0) {
|
||||
|
|
@ -130,11 +130,11 @@ export default class WDIOCLInterface extends EventEmitter {
|
|||
}
|
||||
|
||||
onSpecPass (rid: string, job?: Workers.Job, retries = 0) {
|
||||
this.onJobComplete(rid, job, retries, chalk.bold.green('PASSED'))
|
||||
this.onJobComplete(rid, job, retries, chalk.bold(chalk.green('PASSED')))
|
||||
}
|
||||
|
||||
onSpecFailure (rid: string, job?: Workers.Job, retries = 0) {
|
||||
this.onJobComplete(rid, job, retries, chalk.bold.red('FAILED'))
|
||||
this.onJobComplete(rid, job, retries, chalk.bold(chalk.red('FAILED')))
|
||||
}
|
||||
|
||||
onSpecSkip (rid: string, job?: Workers.Job) {
|
||||
|
|
@ -261,7 +261,7 @@ export default class WDIOCLInterface extends EventEmitter {
|
|||
if (event.name === 'error') {
|
||||
return this.log(
|
||||
`[${event.cid}]`,
|
||||
chalk.white.bgRed.bold(' Error: '),
|
||||
chalk.white(chalk.bgRed(chalk.bold(' Error: '))),
|
||||
event.content ? (event.content.message || event.content.stack || event.content) : ''
|
||||
)
|
||||
}
|
||||
|
|
@ -310,7 +310,7 @@ export default class WDIOCLInterface extends EventEmitter {
|
|||
const reporter = this._messages.reporter
|
||||
this._messages.reporter = {}
|
||||
for (const [reporterName, messages] of Object.entries(reporter)) {
|
||||
this.log('\n', chalk.bold.magenta(`"${reporterName}" Reporter:`))
|
||||
this.log('\n', chalk.bold(chalk.magenta(`"${reporterName}" Reporter:`)))
|
||||
this.log(messages.join(''))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -718,7 +718,7 @@ export async function createPackageJSON(parsedAnswers: ParsedAnswers) {
|
|||
dependencies: {},
|
||||
devDependencies: {}
|
||||
}, null, 2))
|
||||
console.log(chalk.green.bold('✔ Success!\n'))
|
||||
console.log(chalk.green(chalk.bold('✔ Success!\n')))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -808,7 +808,7 @@ export async function npmInstall(parsedAnswers: ParsedAnswers, npmTag: string) {
|
|||
console.log(`Installing packages using ${pm}:${SEP}${parsedAnswers.packagesToInstall.join(SEP)}`)
|
||||
const success = await installPackages(cwd, parsedAnswers.packagesToInstall, true)
|
||||
if (success) {
|
||||
console.log(chalk.green.bold('✔ Success!\n'))
|
||||
console.log(chalk.green(chalk.bold('✔ Success!\n')))
|
||||
}
|
||||
} else {
|
||||
const installationCommand = getInstallCommand(pm, parsedAnswers.packagesToInstall, true)
|
||||
|
|
@ -936,7 +936,7 @@ export async function setupTypeScript(parsedAnswers: ParsedAnswers) {
|
|||
JSON.stringify(config, null, 4)
|
||||
)
|
||||
|
||||
console.log(chalk.green.bold('✔ Success!\n'))
|
||||
console.log(chalk.green(chalk.bold('✔ Success!\n')))
|
||||
}
|
||||
|
||||
function getPreset (parsedAnswers: ParsedAnswers) {
|
||||
|
|
@ -989,7 +989,7 @@ export async function setupBabel(parsedAnswers: ParsedAnswers) {
|
|||
]
|
||||
}, null, 4)}`
|
||||
)
|
||||
console.log(chalk.green.bold('✔ Success!\n'))
|
||||
console.log(chalk.green(chalk.bold('✔ Success!\n')))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1002,12 +1002,12 @@ export async function createWDIOConfig(parsedAnswers: ParsedAnswers) {
|
|||
_: new EjsHelpers({ useEsm: parsedAnswers.esmSupport, useTypeScript: parsedAnswers.isUsingTypeScript })
|
||||
})
|
||||
await fs.writeFile(parsedAnswers.wdioConfigPath, renderedTpl)
|
||||
console.log(chalk.green.bold('✔ Success!\n'))
|
||||
console.log(chalk.green(chalk.bold('✔ Success!\n')))
|
||||
|
||||
if (parsedAnswers.generateTestFiles) {
|
||||
console.log('Autogenerating test files...')
|
||||
await generateTestFiles(parsedAnswers)
|
||||
console.log(chalk.green.bold('✔ Success!\n'))
|
||||
console.log(chalk.green(chalk.bold('✔ Success!\n')))
|
||||
}
|
||||
} catch (err: any) {
|
||||
throw new Error(`⚠️ Couldn't write config file: ${err.stack}`)
|
||||
|
|
@ -1065,7 +1065,7 @@ export async function createWDIOScript(parsedAnswers: ParsedAnswers) {
|
|||
return false
|
||||
}
|
||||
}
|
||||
console.log(chalk.green.bold('✔ Success!'))
|
||||
console.log(chalk.green(chalk.bold('✔ Success!')))
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ describe('cli interface', () => {
|
|||
})
|
||||
|
||||
expect(wdioClInterface.log).toBeCalledTimes(1)
|
||||
expect(wdioClInterface.log).toBeCalledWith('[0-0]', 'bold Error: ', 'foo')
|
||||
expect(wdioClInterface.log).toBeCalledWith('[0-0]', 'white bgRed bold Error: ', 'foo')
|
||||
})
|
||||
|
||||
it('should print message on worker error', () => {
|
||||
|
|
@ -160,7 +160,7 @@ describe('cli interface', () => {
|
|||
})
|
||||
|
||||
expect(wdioClInterface.log).toBeCalledTimes(1)
|
||||
expect(wdioClInterface.log).toBeCalledWith('[0-0]', 'bold Error: ', 'bar')
|
||||
expect(wdioClInterface.log).toBeCalledWith('[0-0]', 'white bgRed bold Error: ', 'bar')
|
||||
})
|
||||
|
||||
it('should ignore messages that do not contain a proper origin', () => {
|
||||
|
|
@ -280,7 +280,7 @@ describe('cli interface', () => {
|
|||
cid,
|
||||
job,
|
||||
retries: 0,
|
||||
message: chalk.bold.cyan('RUNNING')
|
||||
message: chalk.bold(chalk.cyan('RUNNING'))
|
||||
}, {
|
||||
method: 'onSpecRetry',
|
||||
cid,
|
||||
|
|
@ -292,13 +292,13 @@ describe('cli interface', () => {
|
|||
cid,
|
||||
job,
|
||||
retries,
|
||||
message: chalk.bold.green('PASSED')
|
||||
message: chalk.bold(chalk.green('PASSED'))
|
||||
}, {
|
||||
method: 'onSpecFailure',
|
||||
cid,
|
||||
job,
|
||||
retries,
|
||||
message: chalk.bold.red('FAILED')
|
||||
message: chalk.bold(chalk.red('FAILED'))
|
||||
}]
|
||||
|
||||
scenarios.forEach(scenario => {
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ Default: `false`
|
|||
```
|
||||
|
||||
### addConsoleLogs
|
||||
Set to true to show console logs from steps in final report
|
||||
Set to `true` to show console logs from steps in final report
|
||||
|
||||
Type: `boolean`
|
||||
Default: `false`
|
||||
|
|
@ -100,7 +100,7 @@ Default: `false`
|
|||
```
|
||||
|
||||
### realtimeReporting
|
||||
Set to true to display test status realtime than just at the end of the run
|
||||
Set to `true` to display test status realtime than just at the end of the run
|
||||
|
||||
Type: `boolean`
|
||||
Default: `false`
|
||||
|
|
@ -115,7 +115,7 @@ Default: `false`
|
|||
```
|
||||
|
||||
### showPreface
|
||||
Set to false to disable `[ MutliRemoteBrowser ... ]` preface in the reports.
|
||||
Set to `false` to disable `[ MutliRemoteBrowser ... ]` preface in the reports.
|
||||
|
||||
Type: `boolean`
|
||||
Default: `true`
|
||||
|
|
@ -164,6 +164,21 @@ and with `true` (default) each line will be prefixed with the preface:
|
|||
[loremipsum 50 Windows 10 #0-0]
|
||||
```
|
||||
|
||||
### color
|
||||
Set to `true` to display colored output in terminal
|
||||
|
||||
Type: `boolean`
|
||||
Default: `true`
|
||||
|
||||
```js
|
||||
[
|
||||
"spec",
|
||||
{
|
||||
color: true,
|
||||
},
|
||||
]
|
||||
```
|
||||
|
||||
## Environment Options
|
||||
|
||||
There are certain options you can set through environment variables:
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
import { format } from 'node:util'
|
||||
import chalk from 'chalk'
|
||||
import prettyMs from 'pretty-ms'
|
||||
import type { SuiteStats, HookStats, RunnerStats, Argument } from '@wdio/reporter'
|
||||
import WDIOReporter, { TestStats } from '@wdio/reporter'
|
||||
import { format } from 'node:util'
|
||||
import type { Capabilities } from '@wdio/types'
|
||||
|
||||
import { Chalk, type ChalkInstance } from 'chalk'
|
||||
import WDIOReporter, { TestStats } from '@wdio/reporter'
|
||||
import type { SuiteStats, HookStats, RunnerStats, Argument } from '@wdio/reporter'
|
||||
import { buildTableData, printTable, getFormattedRows, sauceAuthenticationToken } from './utils.js'
|
||||
import type { StateCount, Symbols, SpecReporterOptions, TestLink } from './types.js'
|
||||
import { ChalkColors, type SpecReporterOptions, type TestLink, type StateCount, type Symbols, State } from './types.js'
|
||||
|
||||
const DEFAULT_INDENT = ' '
|
||||
|
||||
|
|
@ -43,7 +42,7 @@ export default class SpecReporter extends WDIOReporter {
|
|||
pending: '?',
|
||||
failed: '✖'
|
||||
}
|
||||
|
||||
private _chalk: ChalkInstance
|
||||
private _onlyFailures = false
|
||||
private _sauceLabsSharableLinks = true
|
||||
|
||||
|
|
@ -69,7 +68,16 @@ export default class SpecReporter extends WDIOReporter {
|
|||
return this._originalStdoutWrite(chunk, encoding, callback)
|
||||
}
|
||||
}
|
||||
this._chalk = new Chalk(options.color === false ? { level:0 } : {})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param state state of test execution
|
||||
* @param msg the message to print in terminal
|
||||
* @returns colord value based on chalk to print in terminal
|
||||
*/
|
||||
setMessageColor(message:string, state?: State): string{
|
||||
return this._chalk[this.getColor(state)](message)
|
||||
}
|
||||
|
||||
onRunnerStart (runner: RunnerStats) {
|
||||
|
|
@ -134,7 +142,7 @@ export default class SpecReporter extends WDIOReporter {
|
|||
return
|
||||
}
|
||||
|
||||
const title = stat.title, state = (stat as TestStats).state
|
||||
const title = stat.title, state = (stat as TestStats).state as State
|
||||
const divider = '------------------------------------------------------------------'
|
||||
|
||||
const indent = (stat.type==='test') ?
|
||||
|
|
@ -148,8 +156,8 @@ export default class SpecReporter extends WDIOReporter {
|
|||
|
||||
const content = stat.type === 'test'
|
||||
? `${this._preface} ${indent}` +
|
||||
`${chalk[this.getColor(state)](this.getSymbol(state))} ${title}` +
|
||||
` » ${chalk[this.getColor(state)]('[')} ${this._suiteName} ${chalk[this.getColor(state)](']')}`
|
||||
`${this.setMessageColor(this.getSymbol(state), state)} ${title}` +
|
||||
` » ${this.setMessageColor('[', state)} ${this._suiteName} ${this.setMessageColor(']', state)}`
|
||||
: stat.type !== 'hook' ?
|
||||
`${suiteStartBanner}${this._preface} ${title}` :
|
||||
title
|
||||
|
|
@ -351,24 +359,24 @@ export default class SpecReporter extends WDIOReporter {
|
|||
// display suite description (Cucumber only)
|
||||
if (suite.description) {
|
||||
output.push(...suite.description.trim().split('\n')
|
||||
.map((l) => `${suiteIndent}${chalk.grey(l.trim())}`))
|
||||
.map((l) => `${suiteIndent}${this.setMessageColor(l.trim())}`))
|
||||
output.push('') // empty line
|
||||
}
|
||||
|
||||
// display suite rule (Cucumber only)
|
||||
if (suite.rule) {
|
||||
output.push(...suite.rule.trim().split('\n')
|
||||
.map((l) => `${suiteIndent}${chalk.grey(l.trim())}`))
|
||||
.map((l) => `${suiteIndent}${this.setMessageColor(l.trim())}`))
|
||||
}
|
||||
|
||||
const eventsToReport = this.getEventsToReport(suite)
|
||||
for (const test of eventsToReport) {
|
||||
const testTitle = `${test.title} ${(test instanceof TestStats && test.retries && test.retries > 0) ? `(${test.retries} retries)` : ''}`
|
||||
const state = test.state
|
||||
const state = test.state as State
|
||||
const testIndent = `${DEFAULT_INDENT}${suiteIndent}`
|
||||
|
||||
// Output for a single test
|
||||
output.push(`${testIndent}${chalk[this.getColor(state)](this.getSymbol(state))} ${testTitle.trim()}`)
|
||||
output.push(`${testIndent}${this.setMessageColor(this.getSymbol(state), state)} ${testTitle.trim()}`)
|
||||
|
||||
// print cucumber data table cells and docstring
|
||||
const arg = (test as TestStats).argument
|
||||
|
|
@ -427,21 +435,21 @@ export default class SpecReporter extends WDIOReporter {
|
|||
// Get the passes
|
||||
if (this._stateCounts.passed > 0) {
|
||||
const text = `${this._stateCounts.passed} passing ${duration}`
|
||||
output.push(chalk[this.getColor('passed')](text))
|
||||
output.push(this.setMessageColor(text, State.PASSED))
|
||||
duration = ''
|
||||
}
|
||||
|
||||
// Get the failures
|
||||
if (this._stateCounts.failed > 0) {
|
||||
const text = `${this._stateCounts.failed} failing ${duration}`.trim()
|
||||
output.push(chalk[this.getColor('failed')](text))
|
||||
output.push(this.setMessageColor(text, State.FAILED))
|
||||
duration = ''
|
||||
}
|
||||
|
||||
// Get the skipped tests
|
||||
if (this._stateCounts.skipped > 0) {
|
||||
const text = `${this._stateCounts.skipped} skipped ${duration}`.trim()
|
||||
output.push(chalk[this.getColor('skipped')](text))
|
||||
output.push(this.setMessageColor(text, State.SKIPPED))
|
||||
}
|
||||
|
||||
return output
|
||||
|
|
@ -460,7 +468,7 @@ export default class SpecReporter extends WDIOReporter {
|
|||
const suiteTitle = suite.title
|
||||
const eventsToReport = this.getEventsToReport(suite)
|
||||
for (const test of eventsToReport) {
|
||||
if (test.state !== 'failed') {
|
||||
if (test.state !== State.FAILED) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
@ -474,10 +482,10 @@ export default class SpecReporter extends WDIOReporter {
|
|||
)
|
||||
for (const error of errors) {
|
||||
!error?.stack?.includes('new AssertionError')
|
||||
? output.push(chalk.red(error.message))
|
||||
? output.push(this.setMessageColor(error.message, State.FAILED))
|
||||
: output.push(...error.message.split('\n'))
|
||||
if (error.stack) {
|
||||
output.push(...error.stack.split(/\n/g).map(value => chalk.gray(value)))
|
||||
output.push(...error.stack.split(/\n/g).map(value => this.setMessageColor(value)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -557,20 +565,20 @@ export default class SpecReporter extends WDIOReporter {
|
|||
* @param {string} state Test state
|
||||
* @return {String} State color
|
||||
*/
|
||||
getColor (state?: string) {
|
||||
getColor (state?: string): ChalkColors {
|
||||
// In case of an unknown state
|
||||
let color: keyof typeof chalk = 'gray'
|
||||
let color = ChalkColors.GRAY
|
||||
|
||||
switch (state) {
|
||||
case 'passed':
|
||||
color = 'green'
|
||||
case State.PASSED:
|
||||
color = ChalkColors.GREEN
|
||||
break
|
||||
case 'pending':
|
||||
case 'skipped':
|
||||
color = 'cyan'
|
||||
case State.PENDING:
|
||||
case State.SKIPPED:
|
||||
color = ChalkColors.CYAN
|
||||
break
|
||||
case 'failed':
|
||||
color = 'red'
|
||||
case State.FAILED:
|
||||
color = ChalkColors.RED
|
||||
break
|
||||
}
|
||||
|
||||
|
|
@ -579,11 +587,12 @@ export default class SpecReporter extends WDIOReporter {
|
|||
|
||||
/**
|
||||
* Get information about the enviroment
|
||||
* @param {Object} caps Enviroment details
|
||||
* @param capability
|
||||
* @param {Boolean} verbose
|
||||
* @param isMultiremote
|
||||
* @return {String} Enviroment string
|
||||
*/
|
||||
getEnviromentCombo (capability: Capabilities.RemoteCapability, verbose = true, isMultiremote = false) {
|
||||
getEnviromentCombo (capability: Capabilities.RemoteCapability, verbose = true, isMultiremote = false): string {
|
||||
if (isMultiremote) {
|
||||
const browserNames = Object.values(capability).map((c) => c.browserName)
|
||||
const browserName = browserNames.length > 1
|
||||
|
|
|
|||
|
|
@ -47,13 +47,39 @@ export interface SpecReporterOptions {
|
|||
*
|
||||
* @default: `false`
|
||||
*/
|
||||
realtimeReporting?: boolean
|
||||
realtimeReporting?: boolean
|
||||
/**
|
||||
* Ability to show or hide preface on each line of the report ('[MultiRemote ...]')
|
||||
*
|
||||
* @default: `true`
|
||||
*/
|
||||
showPreface?: boolean
|
||||
showPreface?: boolean
|
||||
/**
|
||||
* Ability to enable or disable colored output in terminal')
|
||||
*
|
||||
* @default: `true`
|
||||
*/
|
||||
color?: boolean
|
||||
}
|
||||
|
||||
export enum ChalkColors {
|
||||
RED = 'red',
|
||||
GREEN = 'green',
|
||||
CYAN = 'cyan',
|
||||
GRAY = 'gray',
|
||||
GREY = 'grey',
|
||||
BLACCK = 'black',
|
||||
YELLOW = 'yellow',
|
||||
BLUE = 'blue',
|
||||
MAGENTA = 'magenta',
|
||||
WHITE = 'white',
|
||||
}
|
||||
|
||||
export enum State {
|
||||
FAILED = 'failed',
|
||||
PASSED = 'passed',
|
||||
PENDING = 'pending',
|
||||
SKIPPED = 'skipped',
|
||||
}
|
||||
|
||||
export interface TestLink {
|
||||
|
|
|
|||
|
|
@ -24,10 +24,10 @@ exports[`SpecReporter > getResultDisplay > should not print if argument is a sin
|
|||
[
|
||||
"» /foo/bar/loo.e2e.js",
|
||||
"Foo test",
|
||||
"grey Some important",
|
||||
"grey description to read!",
|
||||
"gray Some important",
|
||||
"gray description to read!",
|
||||
"",
|
||||
"grey Very important business rule",
|
||||
"gray Very important business rule",
|
||||
" green ✓ foo",
|
||||
" """",
|
||||
" some different format",
|
||||
|
|
@ -41,10 +41,10 @@ exports[`SpecReporter > getResultDisplay > should not print if data table is emp
|
|||
[
|
||||
"» /foo/bar/loo.e2e.js",
|
||||
"Foo test",
|
||||
"grey Some important",
|
||||
"grey description to read!",
|
||||
"gray Some important",
|
||||
"gray description to read!",
|
||||
"",
|
||||
"grey Very important business rule",
|
||||
"gray Very important business rule",
|
||||
" green ✓ foo",
|
||||
" green ✓ bar",
|
||||
"",
|
||||
|
|
@ -55,10 +55,10 @@ exports[`SpecReporter > getResultDisplay > should not print if the argument is u
|
|||
[
|
||||
"» /foo/bar/loo.e2e.js",
|
||||
"Foo test",
|
||||
"grey Some important",
|
||||
"grey description to read!",
|
||||
"gray Some important",
|
||||
"gray description to read!",
|
||||
"",
|
||||
"grey Very important business rule",
|
||||
"gray Very important business rule",
|
||||
" green ✓ foo",
|
||||
" green ✓ bar",
|
||||
"",
|
||||
|
|
@ -69,10 +69,10 @@ exports[`SpecReporter > getResultDisplay > should print data tables 1`] = `
|
|||
[
|
||||
"» /foo/bar/loo.e2e.js",
|
||||
"Foo test",
|
||||
"grey Some important",
|
||||
"grey description to read!",
|
||||
"gray Some important",
|
||||
"gray description to read!",
|
||||
"",
|
||||
"grey Very important business rule",
|
||||
"gray Very important business rule",
|
||||
" green ✓ foo",
|
||||
" │ Vegetable │ Rating │",
|
||||
" │ Apricot │ 5 │",
|
||||
|
|
@ -87,10 +87,10 @@ exports[`SpecReporter > getResultDisplay > should print if the doc string is a b
|
|||
[
|
||||
"» /foo/bar/loo.e2e.js",
|
||||
"Foo test",
|
||||
"grey Some important",
|
||||
"grey description to read!",
|
||||
"gray Some important",
|
||||
"gray description to read!",
|
||||
"",
|
||||
"grey Very important business rule",
|
||||
"gray Very important business rule",
|
||||
" green ✓ foo",
|
||||
" """",
|
||||
" """",
|
||||
|
|
@ -105,10 +105,10 @@ exports[`SpecReporter > getResultDisplay > should print multiple lines doc strin
|
|||
[
|
||||
"» /foo/bar/loo.e2e.js",
|
||||
"Foo test",
|
||||
"grey Some important",
|
||||
"grey description to read!",
|
||||
"gray Some important",
|
||||
"gray description to read!",
|
||||
"",
|
||||
"grey Very important business rule",
|
||||
"gray Very important business rule",
|
||||
" green ✓ foo",
|
||||
" """",
|
||||
" Docstring line 1",
|
||||
|
|
|
|||
|
|
@ -1,18 +1,19 @@
|
|||
import path from 'node:path'
|
||||
import { describe, expect, it, vi, beforeEach, beforeAll } from 'vitest'
|
||||
import { runnerEnd } from '../../wdio-allure-reporter/tests/__fixtures__/runner.js'
|
||||
import SpecReporter from '../src/index.js'
|
||||
import {
|
||||
RUNNER,
|
||||
SUITE_UIDS,
|
||||
SUITES,
|
||||
SUITE_UIDS,
|
||||
SUITES_NO_TESTS,
|
||||
SUITES_WITH_RETRY,
|
||||
SUITES_WITH_DATA_TABLE,
|
||||
SUITES_NO_TESTS_WITH_HOOK_ERROR,
|
||||
SUITES_MULTIPLE_ERRORS,
|
||||
SUITES_WITH_DOC_STRING,
|
||||
SUITES_WITH_RETRY
|
||||
SUITES_NO_TESTS_WITH_HOOK_ERROR,
|
||||
} from './__fixtures__/testdata.js'
|
||||
import { State } from '../src/types.js'
|
||||
import SpecReporter from '../src/index.js'
|
||||
import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { runnerEnd } from '../../wdio-allure-reporter/tests/__fixtures__/runner.js'
|
||||
|
||||
vi.mock('chalk')
|
||||
vi.mock('@wdio/reporter', () => import(path.join(process.cwd(), '__mocks__', '@wdio/reporter')))
|
||||
|
|
@ -94,7 +95,7 @@ describe('SpecReporter', () => {
|
|||
beforeAll(() => {
|
||||
reporter.onTestPass({
|
||||
title:'test1',
|
||||
state:'passed'
|
||||
state:State.PASSED
|
||||
} as any)
|
||||
})
|
||||
|
||||
|
|
@ -107,7 +108,7 @@ describe('SpecReporter', () => {
|
|||
beforeAll(() => {
|
||||
reporter.onTestFail({
|
||||
title:'test1',
|
||||
state:'failed'
|
||||
state:State.FAILED
|
||||
} as any)
|
||||
})
|
||||
|
||||
|
|
@ -120,7 +121,7 @@ describe('SpecReporter', () => {
|
|||
beforeAll(() => {
|
||||
reporter.onTestSkip({
|
||||
title:'test1',
|
||||
state:'skipped',
|
||||
state:State.SKIPPED,
|
||||
pendingReason: 'some random reason'
|
||||
} as any)
|
||||
})
|
||||
|
|
@ -409,8 +410,7 @@ describe('SpecReporter', () => {
|
|||
|
||||
it('should print multiple lines doc string', () => {
|
||||
tmpReporter.getOrderedSuites = vi.fn(() => {
|
||||
const suites = Object.values(JSON.parse(JSON.stringify(SUITES_WITH_DOC_STRING))) as any[]
|
||||
return suites
|
||||
return Object.values(JSON.parse(JSON.stringify(SUITES_WITH_DOC_STRING))) as any[]
|
||||
})
|
||||
const result = tmpReporter.getResultDisplay()
|
||||
expect(result).toMatchSnapshot()
|
||||
|
|
@ -555,7 +555,7 @@ describe('SpecReporter', () => {
|
|||
hooks: [{
|
||||
type: 'hook',
|
||||
title: '"before all" hook in "{root}"',
|
||||
state: 'failed'
|
||||
state: State.FAILED
|
||||
}, {
|
||||
type: 'hook',
|
||||
title: '"after all" hook in "{root}"',
|
||||
|
|
@ -563,7 +563,7 @@ describe('SpecReporter', () => {
|
|||
}, {
|
||||
type: 'hook',
|
||||
title: '"after all" hook in "{root}"',
|
||||
state: 'failed'
|
||||
state: State.FAILED
|
||||
}]
|
||||
}] as any
|
||||
const result = tmpReporter.getOrderedSuites()
|
||||
|
|
@ -593,15 +593,15 @@ describe('SpecReporter', () => {
|
|||
|
||||
describe('getSymbol', () => {
|
||||
it('should get the checkbox symbol', () => {
|
||||
expect(tmpReporter.getSymbol('passed')).toBe('✓')
|
||||
expect(tmpReporter.getSymbol(State.PASSED)).toBe('✓')
|
||||
})
|
||||
|
||||
it('should get the x symbol', () => {
|
||||
expect(tmpReporter.getSymbol('failed')).toBe('✖')
|
||||
expect(tmpReporter.getSymbol(State.FAILED)).toBe('✖')
|
||||
})
|
||||
|
||||
it('should get the - symbol', () => {
|
||||
expect(tmpReporter.getSymbol('skipped')).toBe('-')
|
||||
expect(tmpReporter.getSymbol(State.SKIPPED)).toBe('-')
|
||||
})
|
||||
|
||||
it('should get the ? symbol', () => {
|
||||
|
|
@ -616,15 +616,15 @@ describe('SpecReporter', () => {
|
|||
})
|
||||
|
||||
it('should get new passed symbol', () => {
|
||||
expect(tmpReporter.getSymbol('passed')).toBe(options.symbols.passed)
|
||||
expect(tmpReporter.getSymbol(State.PASSED)).toBe(options.symbols.passed)
|
||||
})
|
||||
|
||||
it('should get new failed symbol', () => {
|
||||
expect(tmpReporter.getSymbol('failed')).toBe(options.symbols.failed)
|
||||
expect(tmpReporter.getSymbol(State.FAILED)).toBe(options.symbols.failed)
|
||||
})
|
||||
|
||||
it('should get the skipped symbol that is not set', () => {
|
||||
expect(tmpReporter.getSymbol('skipped')).toBe('-')
|
||||
expect(tmpReporter.getSymbol(State.SKIPPED)).toBe('-')
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -639,7 +639,7 @@ describe('SpecReporter', () => {
|
|||
tmpReporter['_consoleOutput']='Printing to console spec'
|
||||
tmpReporter.onTestPass({
|
||||
title:'test1',
|
||||
state:'passed'
|
||||
state:State.PASSED
|
||||
} as any)
|
||||
expect(tmpReporter.getResultDisplay().toString()).toContain('Printing to console spec')
|
||||
tmpReporter.onSuiteEnd()
|
||||
|
|
@ -654,7 +654,7 @@ describe('SpecReporter', () => {
|
|||
tmpReporter['_consoleOutput']='Printing to console spec'
|
||||
tmpReporter.onTestFail({
|
||||
title:'test1',
|
||||
state:'failed'
|
||||
state:State.FAILED
|
||||
} as any)
|
||||
expect(tmpReporter.getResultDisplay().toString()).toContain('Printing to console spec')
|
||||
tmpReporter.onSuiteEnd()
|
||||
|
|
@ -669,7 +669,7 @@ describe('SpecReporter', () => {
|
|||
tmpReporter['_consoleOutput']='Printing to console spec'
|
||||
tmpReporter.onTestSkip({
|
||||
title:'test1',
|
||||
state:'skipped'
|
||||
state:State.SKIPPED
|
||||
} as any)
|
||||
expect(tmpReporter.getResultDisplay().toString()).toContain('Printing to console spec')
|
||||
tmpReporter.onSuiteEnd()
|
||||
|
|
@ -683,7 +683,7 @@ describe('SpecReporter', () => {
|
|||
tmpReporter['_orderedSuites'] = Object.values(SUITES) as any
|
||||
tmpReporter.onTestSkip({
|
||||
title:'test1',
|
||||
state:'skipped',
|
||||
state:State.SKIPPED,
|
||||
pendingReason:'some random Reasons'
|
||||
} as any)
|
||||
expect(tmpReporter.getResultDisplay().toString()).toContain('Pending Reasons')
|
||||
|
|
@ -801,16 +801,16 @@ describe('SpecReporter', () => {
|
|||
|
||||
describe('getColor', () => {
|
||||
it('should get green', () => {
|
||||
expect(tmpReporter.getColor('passed')).toBe('green')
|
||||
expect(tmpReporter.getColor(State.PASSED)).toBe('green')
|
||||
})
|
||||
|
||||
it('should get red', () => {
|
||||
expect(tmpReporter.getColor('failed')).toBe('red')
|
||||
expect(tmpReporter.getColor(State.FAILED)).toBe('red')
|
||||
})
|
||||
|
||||
it('should get cyan', () => {
|
||||
expect(tmpReporter.getColor('skipped')).toBe('cyan')
|
||||
expect(tmpReporter.getColor('pending')).toBe('cyan')
|
||||
expect(tmpReporter.getColor(State.SKIPPED)).toBe('cyan')
|
||||
expect(tmpReporter.getColor(State.PENDING)).toBe('cyan')
|
||||
})
|
||||
|
||||
it('should get null', () => {
|
||||
|
|
@ -818,6 +818,22 @@ describe('SpecReporter', () => {
|
|||
})
|
||||
})
|
||||
|
||||
describe('colors in terminal', () => {
|
||||
it('should give colors', () => {
|
||||
const tmpReporter = new SpecReporter({})
|
||||
expect(tmpReporter.setMessageColor('test', State.PASSED)).toEqual('green test')
|
||||
expect(tmpReporter.setMessageColor('test', State.FAILED)).toEqual('red test')
|
||||
expect(tmpReporter.setMessageColor('test', State.SKIPPED)).toEqual('cyan test')
|
||||
})
|
||||
|
||||
it('should not give any color', () => {
|
||||
const tmpReporter = new SpecReporter({ color: false })
|
||||
expect(tmpReporter.setMessageColor('test', State.PASSED)).toEqual('test')
|
||||
expect(tmpReporter.setMessageColor('test', State.FAILED)).toEqual('test')
|
||||
expect(tmpReporter.setMessageColor('test', State.SKIPPED)).toEqual('test')
|
||||
})
|
||||
})
|
||||
|
||||
describe('getEnviromentCombo', () => {
|
||||
it('should return Multibrowser as capability if multiremote is used', () => {
|
||||
expect(tmpReporter.getEnviromentCombo({
|
||||
|
|
@ -997,11 +1013,11 @@ describe('SpecReporter', () => {
|
|||
tmpReporter['_consoleOutput']='Printing to console spec'
|
||||
tmpReporter.onTestPass({
|
||||
title:'test1',
|
||||
state:'passed'
|
||||
state:State.PASSED
|
||||
} as any)
|
||||
expect(tmpReporter.printCurrentStats).toBeCalledWith({
|
||||
title:'test1',
|
||||
state:'passed'
|
||||
state:State.PASSED
|
||||
})
|
||||
tmpReporter.onSuiteEnd()
|
||||
tmpReporter.onRunnerEnd(runnerEnd())
|
||||
|
|
@ -1016,11 +1032,11 @@ describe('SpecReporter', () => {
|
|||
tmpReporter['_consoleOutput']='Printing to console spec'
|
||||
tmpReporter.onTestPass({
|
||||
title:'test1',
|
||||
state:'failed'
|
||||
state:State.FAILED
|
||||
} as any)
|
||||
expect(tmpReporter.printCurrentStats).toBeCalledWith({
|
||||
title:'test1',
|
||||
state:'failed'
|
||||
state:State.FAILED
|
||||
})
|
||||
tmpReporter.onSuiteEnd()
|
||||
tmpReporter.onRunnerEnd(runnerEnd())
|
||||
|
|
@ -1035,11 +1051,11 @@ describe('SpecReporter', () => {
|
|||
tmpReporter['_consoleOutput']='Printing to console spec'
|
||||
tmpReporter.onTestPass({
|
||||
title:'test1',
|
||||
state:'skipped'
|
||||
state:State.SKIPPED
|
||||
} as any)
|
||||
expect(tmpReporter.printCurrentStats).toBeCalledWith({
|
||||
title:'test1',
|
||||
state:'skipped'
|
||||
state:State.SKIPPED
|
||||
})
|
||||
tmpReporter.onSuiteEnd()
|
||||
tmpReporter.onRunnerEnd(runnerEnd())
|
||||
|
|
@ -1055,11 +1071,11 @@ describe('SpecReporter', () => {
|
|||
tmpReporter['_consoleOutput']='Printing to console spec'
|
||||
tmpReporter.onHookEnd({
|
||||
title:'test1',
|
||||
state:'failed'
|
||||
state:State.FAILED
|
||||
} as any)
|
||||
expect(tmpReporter.printCurrentStats).toBeCalledWith({
|
||||
title:'test1',
|
||||
state:'failed'
|
||||
state:State.FAILED
|
||||
})
|
||||
tmpReporter.onSuiteEnd()
|
||||
tmpReporter.onRunnerEnd(runnerEnd())
|
||||
|
|
|
|||
Loading…
Reference in a new issue