Skip to content

Commit

Permalink
feat: add tests with "tape", test coverage with "c8" and "coveralls"
Browse files Browse the repository at this point in the history
  • Loading branch information
andreidmt committed Feb 11, 2023
1 parent b683b78 commit 1d63da6
Show file tree
Hide file tree
Showing 8 changed files with 1,589 additions and 32 deletions.
15 changes: 15 additions & 0 deletions .c8rc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"lines": 90,
"statements": 90,
"functions": 90,
"branches": 90,
"include": [
"lib/**/*.js",
"bin/**/*.js"
],
"exclude": [
"lib/**/*.test.js"
],
"all": true,
"reporter": ["text"]
}
19 changes: 17 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ jobs:
- attach_workspace:
at: *WORKSPACE_ROOT
- run:
name: "[tape]: Unit tests"
command: "npm test"
name: "[tape, c8]: Unit tests with coverage"
command: "npm run test.coverage"

typecheck:
executor: node-lts
Expand Down Expand Up @@ -96,6 +96,18 @@ jobs:
package"
command: "npm run release"

# Required env vars:
# - COVERALLS_REPO_TOKEN: access token to submit data to coveralls.io
submit-coverage:
executor: node-lts
working_directory: *JOB_WORKING_DIR
steps:
- attach_workspace:
at: *WORKSPACE_ROOT
- run:
name: "[c8, coveralls]: Publish test coverage to COVERALLS"
command: "npm run test.coverage-submit"

# Workflows - https://circleci.com/docs/2.0/workflows/
#
# Treat workflows as a jobs/commands pipe:
Expand All @@ -119,6 +131,9 @@ workflows:
- release-npm:
requires: [test, typecheck, lint]
context: ["GitHub Auth", "NPM Auth"]
- submit-coverage:
requires: [release-npm]
context: ["Coveralls - tsd-lite-cli"]

test_pr-branches:
jobs:
Expand Down
6 changes: 3 additions & 3 deletions bin/tsd-lite.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import fastGlob from "fast-glob"
import { program } from "commander"

import tapReporter from "../lib/run-one.tap-reporter.js"
import tapReporter from "../lib/tap-reporter.js"
import { getNodeVersion, getPackageInfo } from "../lib/utils/node.js"
import { green, red } from "../lib/utils/terminal-text.js"
import { runSuite } from "../lib/run-many.js"
Expand Down Expand Up @@ -53,7 +53,7 @@ program
const files = fastGlob.sync(patterns, { absolute: true })

process.stdout.write(
`${tapReporter.formatIntro({
`${tapReporter.formatPlan({
count: files.length,
patterns,
hasColor,
Expand Down Expand Up @@ -86,7 +86,7 @@ program
)

process.stdout.write(
`\n${tapReporter.formatSuite({
`\n${tapReporter.formatSummary({
passCount,
failCount,
duration: process.hrtime(processStartAt),
Expand Down
46 changes: 23 additions & 23 deletions lib/run-one.tap-reporter.js → lib/tap-reporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,26 @@ import * as ttext from "./utils/terminal-text.js"
import { formatHrTime } from "./utils/node.js"

/**
* Format intro to TAP format
* Format into TAP plan
*
* @param {object} props
* @param {number} props.count
* @param {string[]} props.patterns
* @param {boolean} props.hasColor
* @param {boolean} [props.hasColor]
*
* @example
* formatIntro({
* formatPlan({
* count: 2,
* patterns: ["src/*.test-d.ts"]
* })
* // => "TAP version 14"
* // => "1..2"
* // => "# Matching patterns src/*.test-d.ts"
* // => '# Matching patterns "src/*.test-d.ts"'
*/
const formatIntro = ({ count, patterns, hasColor }) => {
let description = `# Matching patterns ${patterns.join(",")}`
const formatPlan = ({ count, patterns, hasColor = true }) => {
let description = `# Matching patterns ${patterns
.map(item => `"${item}"`)
.join(",")}`

if (hasColor) {
description = ttext.blue.fg(description)
Expand Down Expand Up @@ -61,25 +63,25 @@ const highlightFileName = filePath => {
* @param {string} props.result.name
* @param {[number, number]} props.result.duration
* @param {TestError[]} props.result.errors
* @param {boolean} props.hasColor
* @param {boolean} [props.hasColor]
*
* @example
* formatTestResult({
* formatTest({
* name: "src/__tests__/index.test.js",
* errors: [],
* })
* // => "ok 1 - src/__tests__/index.test.js 0.8s"
*
* @example
* formatTestResult({
* formatTest({
* name: "src/__tests__/index.test.js",
* errors: [
* { row: 1, column: 1, message: "Unexpected token" },
* ],
* })
* // => "not ok 1 - src/__tests__/index.test.js 1.2s"
* // => " ---"
* // => " message: 'Unexpected token'
* // => " message: Unexpected token
* // => " severity: fail"
* // => " data:"
* // => " line: 1"
Expand All @@ -89,7 +91,7 @@ const highlightFileName = filePath => {
const formatTest = ({
index,
result: { name, duration, errors },
hasColor,
hasColor = true,
}) => {
let testPointStatus = `${errors.length === 0 ? "ok" : "not ok"} ${index + 1}`
let humanReadableDuration = formatHrTime(duration)
Expand All @@ -108,9 +110,7 @@ const formatTest = ({
const output = [testPoint]

for (const error of errors) {
const message = hasColor
? ttext.cyan.fg(`'${error.message}'`)
: error.message
const message = hasColor ? ttext.cyan.fg(error.message) : error.message

output.push(
` ---`,
Expand All @@ -133,10 +133,10 @@ const formatTest = ({
* @param {number} props.passCount
* @param {number} props.failCount
* @param {[number, number]} props.duration
* @param {boolean} props.hasColor
* @param {boolean} [props.hasColor]
*
* @example
* formatSuiteResult({
* formatSummary({
* passCount: 1,
* failCount: 1,
* duration: [5, 420000000]
Expand All @@ -146,14 +146,14 @@ const formatTest = ({
* // => "# fail 1"
* // => "# duration 5.42s"
*/
const formatSuite = ({ passCount, failCount, duration, hasColor }) => {
const formatSummary = ({ passCount, failCount, duration, hasColor = true }) => {
const hasFailures = failCount > 0
const totalCount = passCount + failCount
let [testsLine, passLine, failLine, durationLine] = [
`# tests ${totalCount}`,
`# pass ${passCount}`,
`# fail ${failCount}`,
`# duration ${formatHrTime(duration)}`,
`# tests ${totalCount}`,
`# pass ${passCount}`,
`# fail ${failCount}`,
`# duration ${formatHrTime(duration)}`,
]

if (hasColor) {
Expand All @@ -171,7 +171,7 @@ const formatSuite = ({ passCount, failCount, duration, hasColor }) => {
}

export default {
formatIntro,
formatPlan,
formatTest,
formatSuite,
formatSummary,
}
168 changes: 168 additions & 0 deletions lib/tap-reporter.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
import test from "tape"

import tapReporter from "./tap-reporter.js"
import { removeANSICodes } from "./utils/terminal-text.js"

test("tap-reporter - formatPlan", t => {
t.plan(2)

const resultColored = tapReporter.formatPlan({
count: 2,
patterns: ["test"],
})

const resultPlain = tapReporter.formatPlan({
count: 2,
patterns: ["test"],
hasColor: false,
})

const expected = [
"TAP version 14",
"1..2",
'# Matching patterns "test"',
].join("\n")

t.equal(
// TODO: snapshots?
removeANSICodes(resultColored),
expected,
"given [count, patterns and default hasColor eq true] should return [a TAP header, plan and colored description]"
)

t.equal(
resultPlain,
expected,
"given [count, patterns and hasColor eq false] should return [a TAP header, plan and description]"
)
})

test("tap-reporter - formatTest", t => {
t.plan(4)

{
const resultColored = tapReporter.formatTest({
index: 1,
result: {
name: "some/path/test-d.ts",
duration: [1, 10_000_000],
errors: [],
},
})

const resultPlain = tapReporter.formatTest({
index: 1,
result: {
name: "some/path/test-d.ts",
duration: [1, 10_000_000],
errors: [],
},
hasColor: false,
})

const expected = "ok 2 - some/path/test-d.ts 1.01s"

t.equal(
// TODO: snapshots?
removeANSICodes(resultColored),
expected,
"given [success test result with default hasColor eq true] should return [a colored string with TAP test point - id, file name and duration]"
)

t.equal(
resultPlain,
expected,
"given [success test result with hasColor eq false] should return [a plain string with TAP test point - id, file name and duration]"
)
}

{
const resultColored = tapReporter.formatTest({
index: 1,
result: {
name: "some/path/test-d.ts",
duration: [1, 10_000_000],
errors: [
{
message: "Some bad thing happened",
row: 1,
column: 2,
},
],
},
})

const resultPlain = tapReporter.formatTest({
index: 1,
result: {
name: "some/path/test-d.ts",
duration: [1, 10_000_000],
errors: [
{
message: "Some bad thing happened",
row: 1,
column: 2,
},
],
},
hasColor: false,
})

const expected = [
"not ok 2 - some/path/test-d.ts 1.01s",
" ---",
" message: Some bad thing happened",
" severity: fail",
" data:",
" line: 1",
" column: 2",
" ...",
].join("\n")

t.equal(
// TODO: snapshots?
removeANSICodes(resultColored),
expected,
"given [error test result with default hasColor eq true] should return [a colored string with TAP test point - id, file name, duration and error YAMLBlock]"
)

t.equal(
resultPlain,
expected,
"given [error test result with hasColor eq false] should return [a plain string with TAP test point - id, file name, duration and error YAMLBlock]"
)
}
})

test("tap-reporter - formatSummary", t => {
t.plan(2)

const resultColored = tapReporter.formatSummary({
passCount: 2,
failCount: 1,
duration: [1, 10_000_000],
})

const resultPlain = tapReporter.formatSummary({
passCount: 2,
failCount: 1,
duration: [1, 10_000_000],
hasColor: false,
})

const expected = [
"# tests 3",
"# pass 2",
"# fail 1",
"# duration 1.01s",
].join("\n")

t.equal(
// TODO: snapshots?
removeANSICodes(resultColored),
expected,
"given [] should return []"
)

t.equal(resultPlain, expected, "given [] should return []")
})
9 changes: 9 additions & 0 deletions lib/utils/terminal-text.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,12 @@ export const cyan = {

/** @param {string} input */
export const bold = input => `\u001B[1m${input}\u001B[0m`

/**
* Clean a string from ANSI codes
*
* @param {string} input
*/
export const removeANSICodes = input =>
// eslint-disable-next-line no-control-regex
input.replace(/\u001B\[\d{1,3}m/g, "")
Loading

0 comments on commit 1d63da6

Please sign in to comment.