Skip to content

Instantly share code, notes, and snippets.

@dead-claudia
Last active October 30, 2016 06:28
Show Gist options
  • Save dead-claudia/97239e28a2288f65429c0f58acd0e1c7 to your computer and use it in GitHub Desktop.
Save dead-claudia/97239e28a2288f65429c0f58acd0e1c7 to your computer and use it in GitHub Desktop.
The TAP reporter example from Thallium, if the API accepted an event emitter or an event handler class. It's here together with the original example.
"use strict"
// This is a basic TAP-generating reporter.
const tty = require("tty")
const inspect = require("util").inspect
const EventEmitter = require("events").EventEmitter
const windowWidth = (() => {
if (tty.isatty(1) && tty.isatty(2)) {
if (process.stdout.columns != null) {
return process.stdout.columns
} else if (process.stdout.getWindowSize != null) {
return process.stdout.getWindowSize(1)[0]
} else if (tty.getWindowSize != null) {
return tty.getWindowSize()[1]
}
}
return 75
})()
function print(text) {
return new Promise((resolve, reject) => {
process.stdout.write(text, err => err != null ? reject(err) : resolve())
})
}
function joinPath(report) {
return report.path.map(i => i.name).join(" ")
}
function printLines(value, skipFirst) {
const lines = value.replace(/^/gm, " ").split(/\report?\n/g)
const rest = skipFirst ? lines.slice(1) : lines
return rest.reduce(
(p, line) => p.then(() => print(line)),
Promise.resolve())
}
function printRaw(key, str) {
if (str.length > windowWidth - key.length || /\report?\n|[:?-]/.test(str)) {
return print(` ${key}: |-`)
.then(() => printLines(str, false))
} else {
return print(` ${key}: ${str}`)
}
}
function printError(report) {
const err = report.error
if (!(err instanceof Error)) {
return printRaw("value", inspect(err))
} else if (err.name !== "AssertionError") {
// Let's *not* depend on the constructor being Thallium's...
return print(" stack: |-")
.then(() => printLines(err.stack, false))
} else {
return printRaw("expected", inspect(err.expected))
.then(() => printRaw("actual", inspect(err.actual)))
.then(() => printRaw("message", err.message))
.then(() => print(" stack: |-"))
.then(() => {
const message = err.message
err.message = ""
return printLines(err.stack, true)
.then(() => { err.message = message })
})
}
}
function fixHooks(joined, report) {
if (!report.hook) return joined
if (!report.name) return `${joined} (${report.stage})`
return `${joined} (${report.stage} ‒ ${report.name})`
}
module.exports = () => {
const reporter = new EventEmitter()
let counter = 0
let tests = 0
let pass = 0
let fail = 0
let skip = 0
function template(report, tmpl, skip) {
if (!skip) counter++
const joined = joinPath(report).replace(/\$/g, "$$$$")
return print(
tmpl.replace(/%c/g, counter)
.replace(/%p/g, fixHooks(joined, report)))
}
reporter.on("start", (report, next) => {
counter = tests = pass = fail = skip = 0
print("TAP version 13")
.then(() => next(), next)
})
reporter.on("enter", (report, next) => {
tests++
pass++
// Print a leading comment, to make some TAP formatters prettier.
template(report, "# %p", true)
.then(() => template(report, "ok %c"))
.then(() => next(), next)
})
reporter.on("pass", (report, next) => {
tests++
pass++
template(report, "ok %c %p")
.then(() => next(), next)
})
reporter.on("fail", (report, next) => {
tests++
fail++
template(report, "not ok %c %p")
.then(() => print(" ---"))
.then(() => printError(report))
.then(() => print(" ..."))
.then(() => next(), next)
})
reporter.on("hook", (report, next) => reporter.emit("fail", report, next))
reporter.on("skip", (report, next) => {
skip++
template(report, "ok %c # skip %p")
.then(() => next(), next)
})
reporter.on("end", (report, next) => {
let p = print(`1..${counter}`)
.then(() => print(`# tests ${tests}`))
if (pass) p = p.then(() => print(`# pass ${pass}`))
if (fail) p = p.then(() => print(`# fail ${fail}`))
if (skip) p = p.then(() => print(`# skip ${skip}`))
p.then(() => next(), next)
})
reporter.on("error", (report, next) => {
print("Bail out!")
.then(() => print(" ---"))
.then(() => printError(report))
.then(() => print(" ..."))
.then(() => next(), next)
})
return reporter
}
"use strict"
// This is a basic TAP-generating reporter.
const tty = require("tty")
const inspect = require("util").inspect
const windowWidth = (() => {
if (tty.isatty(1) && tty.isatty(2)) {
if (process.stdout.columns != null) {
return process.stdout.columns
} else if (process.stdout.getWindowSize != null) {
return process.stdout.getWindowSize(1)[0]
} else if (tty.getWindowSize != null) {
return tty.getWindowSize()[1]
}
}
return 75
})()
function print(text) {
return new Promise((resolve, reject) => {
process.stdout.write(text, err => err != null ? reject(err) : resolve())
})
}
function joinPath(report) {
return report.path.map(i => i.name).join(" ")
}
function printLines(value, skipFirst) {
const lines = value.replace(/^/gm, " ").split(/\report?\n/g)
const rest = skipFirst ? lines.slice(1) : lines
return rest.reduce(
(p, line) => p.then(() => print(line)),
Promise.resolve())
}
function printRaw(key, str) {
if (str.length > windowWidth - key.length || /\report?\n|[:?-]/.test(str)) {
return print(` ${key}: |-`)
.then(() => printLines(str, false))
} else {
return print(` ${key}: ${str}`)
}
}
function printError(report) {
const err = report.error
if (!(err instanceof Error)) {
return printRaw("value", inspect(err))
} else if (err.name !== "AssertionError") {
// Let's *not* depend on the constructor being Thallium's...
return print(" stack: |-")
.then(() => printLines(err.stack, false))
} else {
return printRaw("expected", inspect(err.expected))
.then(() => printRaw("actual", inspect(err.actual)))
.then(() => printRaw("message", err.message))
.then(() => print(" stack: |-"))
.then(() => {
const message = err.message
err.message = ""
return printLines(err.stack, true)
.then(() => { err.message = message })
})
}
}
function fixHooks(joined, report) {
if (!report.hook) return joined
if (!report.name) return `${joined} (${report.stage})`
return `${joined} (${report.stage} ‒ ${report.name})`
}
module.exports = class Reporter {
_reset() {
this._counter = 0
this._tests = 0
this._pass = 0
this._fail = 0
this._skip = 0
}
_template(report, tmpl, skip) {
if (!skip) this._counter++
const joined = joinPath(report).replace(/\$/g, "$$$$")
return print(
tmpl.replace(/%c/g, this._counter)
.replace(/%p/g, fixHooks(joined, report)))
}
start() {
this._reset()
return print("TAP version 13")
}
enter(report) {
this._tests++
this._pass++
// Print a leading comment, to make some TAP formatters prettier.
return this._template(report, "# %p", true)
.then(() => this._template(report, "ok %c"))
}
pass(report) {
this._tests++
this._pass++
return this._template(report, "ok %c %p")
}
fail(report) {
this._tests++
this._fail++
return this._template(report, "not ok %c %p")
.then(() => print(" ---"))
.then(() => printError(report))
.then(() => print(" ..."))
}
hook(report) {
return this.fail(report)
}
skip(report) {
this._skip++
return this._template(report, "ok %c # skip %p")
}
end(report) {
let p = print(`1..${this._counter}`)
.then(() => print(`# tests ${this._tests}`))
if (this._pass) p = p.then(() => print(`# pass ${this._pass}`))
if (this._fail) p = p.then(() => print(`# fail ${this._fail}`))
if (this._skip) p = p.then(() => print(`# skip ${this._skip}`))
return p
}
error(report) {
return print("Bail out!")
.then(() => print(" ---"))
.then(() => printError(report))
.then(() => print(" ..."))
}
}
"use strict"
// This is a basic TAP-generating reporter.
const tty = require("tty")
const inspect = require("util").inspect
const windowWidth = (() => {
if (tty.isatty(1) && tty.isatty(2)) {
if (process.stdout.columns != null) {
return process.stdout.columns
} else if (process.stdout.getWindowSize != null) {
return process.stdout.getWindowSize(1)[0]
} else if (tty.getWindowSize != null) {
return tty.getWindowSize()[1]
}
}
return 75
})()
function print(text) {
return new Promise((resolve, reject) => {
process.stdout.write(text, err => err != null ? reject(err) : resolve())
})
}
function joinPath(report) {
return report.path.map(i => i.name).join(" ")
}
function printLines(value, skipFirst) {
const lines = value.replace(/^/gm, " ").split(/\report?\n/g)
const rest = skipFirst ? lines.slice(1) : lines
return rest.reduce(
(p, line) => p.then(() => print(line)),
Promise.resolve())
}
function printRaw(key, str) {
if (str.length > windowWidth - key.length || /\report?\n|[:?-]/.test(str)) {
return print(` ${key}: |-`)
.then(() => printLines(str, false))
} else {
return print(` ${key}: ${str}`)
}
}
function printError(report) {
const err = report.error
if (!(err instanceof Error)) {
return printRaw("value", inspect(err))
} else if (err.name !== "AssertionError") {
// Let's *not* depend on the constructor being Thallium's...
return print(" stack: |-")
.then(() => printLines(err.stack, false))
} else {
return printRaw("expected", inspect(err.expected))
.then(() => printRaw("actual", inspect(err.actual)))
.then(() => printRaw("message", err.message))
.then(() => print(" stack: |-"))
.then(() => {
const message = err.message
err.message = ""
return printLines(err.stack, true)
.then(() => { err.message = message })
})
}
}
function fixHooks(joined, report) {
if (!report.hook) return joined
if (!report.name) return `${joined} (${report.stage})`
return `${joined} (${report.stage} ‒ ${report.name})`
}
module.exports = () => {
let counter = 0
let tests = 0
let pass = 0
let fail = 0
let skip = 0
function template(report, tmpl, skip) {
if (!skip) counter++
const joined = joinPath(report).replace(/\$/g, "$$$$")
return print(
tmpl.replace(/%c/g, counter)
.replace(/%p/g, fixHooks(joined, report)))
}
return report => {
if (report.isStart) {
counter = tests = pass = fail = skip = 0
return print("TAP version 13")
} else if (report.isEnter) {
tests++
pass++
// Print a leading comment, to make some TAP formatters prettier.
return template(report, "# %p", true)
.then(() => template(report, "ok %c"))
} else if (report.isPass) {
tests++
pass++
return template(report, "ok %c %p")
} else if (report.isFail || report.isHook) {
tests++
fail++
return template(report, "not ok %c %p")
.then(() => print(" ---"))
.then(() => printError(report))
.then(() => print(" ..."))
} else if (report.isSkip) {
skip++
return template(report, "ok %c # skip %p")
} else if (report.isEnd) {
let p = print(`1..${counter}`)
.then(() => print(`# tests ${tests}`))
if (pass) p = p.then(() => print(`# pass ${pass}`))
if (fail) p = p.then(() => print(`# fail ${fail}`))
if (skip) p = p.then(() => print(`# skip ${skip}`))
return p
} else if (report.isError) {
return print("Bail out!")
.then(() => print(" ---"))
.then(() => printError(report))
.then(() => print(" ..."))
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment