Skip to content
This repository was archived by the owner on Dec 28, 2024. It is now read-only.

Commit 1d63da6

Browse files
committed
feat: add tests with "tape", test coverage with "c8" and "coveralls"
1 parent b683b78 commit 1d63da6

File tree

8 files changed

+1589
-32
lines changed

8 files changed

+1589
-32
lines changed

.c8rc

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"lines": 90,
3+
"statements": 90,
4+
"functions": 90,
5+
"branches": 90,
6+
"include": [
7+
"lib/**/*.js",
8+
"bin/**/*.js"
9+
],
10+
"exclude": [
11+
"lib/**/*.test.js"
12+
],
13+
"all": true,
14+
"reporter": ["text"]
15+
}

.circleci/config.yml

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ jobs:
5555
- attach_workspace:
5656
at: *WORKSPACE_ROOT
5757
- run:
58-
name: "[tape]: Unit tests"
59-
command: "npm test"
58+
name: "[tape, c8]: Unit tests with coverage"
59+
command: "npm run test.coverage"
6060

6161
typecheck:
6262
executor: node-lts
@@ -96,6 +96,18 @@ jobs:
9696
package"
9797
command: "npm run release"
9898

99+
# Required env vars:
100+
# - COVERALLS_REPO_TOKEN: access token to submit data to coveralls.io
101+
submit-coverage:
102+
executor: node-lts
103+
working_directory: *JOB_WORKING_DIR
104+
steps:
105+
- attach_workspace:
106+
at: *WORKSPACE_ROOT
107+
- run:
108+
name: "[c8, coveralls]: Publish test coverage to COVERALLS"
109+
command: "npm run test.coverage-submit"
110+
99111
# Workflows - https://circleci.com/docs/2.0/workflows/
100112
#
101113
# Treat workflows as a jobs/commands pipe:
@@ -119,6 +131,9 @@ workflows:
119131
- release-npm:
120132
requires: [test, typecheck, lint]
121133
context: ["GitHub Auth", "NPM Auth"]
134+
- submit-coverage:
135+
requires: [release-npm]
136+
context: ["Coveralls - tsd-lite-cli"]
122137

123138
test_pr-branches:
124139
jobs:

bin/tsd-lite.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import fastGlob from "fast-glob"
44
import { program } from "commander"
55

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

5555
process.stdout.write(
56-
`${tapReporter.formatIntro({
56+
`${tapReporter.formatPlan({
5757
count: files.length,
5858
patterns,
5959
hasColor,
@@ -86,7 +86,7 @@ program
8686
)
8787

8888
process.stdout.write(
89-
`\n${tapReporter.formatSuite({
89+
`\n${tapReporter.formatSummary({
9090
passCount,
9191
failCount,
9292
duration: process.hrtime(processStartAt),

lib/run-one.tap-reporter.js renamed to lib/tap-reporter.js

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,26 @@ import * as ttext from "./utils/terminal-text.js"
66
import { formatHrTime } from "./utils/node.js"
77

88
/**
9-
* Format intro to TAP format
9+
* Format into TAP plan
1010
*
1111
* @param {object} props
1212
* @param {number} props.count
1313
* @param {string[]} props.patterns
14-
* @param {boolean} props.hasColor
14+
* @param {boolean} [props.hasColor]
1515
*
1616
* @example
17-
* formatIntro({
17+
* formatPlan({
1818
* count: 2,
1919
* patterns: ["src/*.test-d.ts"]
2020
* })
2121
* // => "TAP version 14"
2222
* // => "1..2"
23-
* // => "# Matching patterns src/*.test-d.ts"
23+
* // => '# Matching patterns "src/*.test-d.ts"'
2424
*/
25-
const formatIntro = ({ count, patterns, hasColor }) => {
26-
let description = `# Matching patterns ${patterns.join(",")}`
25+
const formatPlan = ({ count, patterns, hasColor = true }) => {
26+
let description = `# Matching patterns ${patterns
27+
.map(item => `"${item}"`)
28+
.join(",")}`
2729

2830
if (hasColor) {
2931
description = ttext.blue.fg(description)
@@ -61,25 +63,25 @@ const highlightFileName = filePath => {
6163
* @param {string} props.result.name
6264
* @param {[number, number]} props.result.duration
6365
* @param {TestError[]} props.result.errors
64-
* @param {boolean} props.hasColor
66+
* @param {boolean} [props.hasColor]
6567
*
6668
* @example
67-
* formatTestResult({
69+
* formatTest({
6870
* name: "src/__tests__/index.test.js",
6971
* errors: [],
7072
* })
7173
* // => "ok 1 - src/__tests__/index.test.js 0.8s"
7274
*
7375
* @example
74-
* formatTestResult({
76+
* formatTest({
7577
* name: "src/__tests__/index.test.js",
7678
* errors: [
7779
* { row: 1, column: 1, message: "Unexpected token" },
7880
* ],
7981
* })
8082
* // => "not ok 1 - src/__tests__/index.test.js 1.2s"
8183
* // => " ---"
82-
* // => " message: 'Unexpected token'
84+
* // => " message: Unexpected token
8385
* // => " severity: fail"
8486
* // => " data:"
8587
* // => " line: 1"
@@ -89,7 +91,7 @@ const highlightFileName = filePath => {
8991
const formatTest = ({
9092
index,
9193
result: { name, duration, errors },
92-
hasColor,
94+
hasColor = true,
9395
}) => {
9496
let testPointStatus = `${errors.length === 0 ? "ok" : "not ok"} ${index + 1}`
9597
let humanReadableDuration = formatHrTime(duration)
@@ -108,9 +110,7 @@ const formatTest = ({
108110
const output = [testPoint]
109111

110112
for (const error of errors) {
111-
const message = hasColor
112-
? ttext.cyan.fg(`'${error.message}'`)
113-
: error.message
113+
const message = hasColor ? ttext.cyan.fg(error.message) : error.message
114114

115115
output.push(
116116
` ---`,
@@ -133,10 +133,10 @@ const formatTest = ({
133133
* @param {number} props.passCount
134134
* @param {number} props.failCount
135135
* @param {[number, number]} props.duration
136-
* @param {boolean} props.hasColor
136+
* @param {boolean} [props.hasColor]
137137
*
138138
* @example
139-
* formatSuiteResult({
139+
* formatSummary({
140140
* passCount: 1,
141141
* failCount: 1,
142142
* duration: [5, 420000000]
@@ -146,14 +146,14 @@ const formatTest = ({
146146
* // => "# fail 1"
147147
* // => "# duration 5.42s"
148148
*/
149-
const formatSuite = ({ passCount, failCount, duration, hasColor }) => {
149+
const formatSummary = ({ passCount, failCount, duration, hasColor = true }) => {
150150
const hasFailures = failCount > 0
151151
const totalCount = passCount + failCount
152152
let [testsLine, passLine, failLine, durationLine] = [
153-
`# tests ${totalCount}`,
154-
`# pass ${passCount}`,
155-
`# fail ${failCount}`,
156-
`# duration ${formatHrTime(duration)}`,
153+
`# tests ${totalCount}`,
154+
`# pass ${passCount}`,
155+
`# fail ${failCount}`,
156+
`# duration ${formatHrTime(duration)}`,
157157
]
158158

159159
if (hasColor) {
@@ -171,7 +171,7 @@ const formatSuite = ({ passCount, failCount, duration, hasColor }) => {
171171
}
172172

173173
export default {
174-
formatIntro,
174+
formatPlan,
175175
formatTest,
176-
formatSuite,
176+
formatSummary,
177177
}

lib/tap-reporter.test.js

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import test from "tape"
2+
3+
import tapReporter from "./tap-reporter.js"
4+
import { removeANSICodes } from "./utils/terminal-text.js"
5+
6+
test("tap-reporter - formatPlan", t => {
7+
t.plan(2)
8+
9+
const resultColored = tapReporter.formatPlan({
10+
count: 2,
11+
patterns: ["test"],
12+
})
13+
14+
const resultPlain = tapReporter.formatPlan({
15+
count: 2,
16+
patterns: ["test"],
17+
hasColor: false,
18+
})
19+
20+
const expected = [
21+
"TAP version 14",
22+
"1..2",
23+
'# Matching patterns "test"',
24+
].join("\n")
25+
26+
t.equal(
27+
// TODO: snapshots?
28+
removeANSICodes(resultColored),
29+
expected,
30+
"given [count, patterns and default hasColor eq true] should return [a TAP header, plan and colored description]"
31+
)
32+
33+
t.equal(
34+
resultPlain,
35+
expected,
36+
"given [count, patterns and hasColor eq false] should return [a TAP header, plan and description]"
37+
)
38+
})
39+
40+
test("tap-reporter - formatTest", t => {
41+
t.plan(4)
42+
43+
{
44+
const resultColored = tapReporter.formatTest({
45+
index: 1,
46+
result: {
47+
name: "some/path/test-d.ts",
48+
duration: [1, 10_000_000],
49+
errors: [],
50+
},
51+
})
52+
53+
const resultPlain = tapReporter.formatTest({
54+
index: 1,
55+
result: {
56+
name: "some/path/test-d.ts",
57+
duration: [1, 10_000_000],
58+
errors: [],
59+
},
60+
hasColor: false,
61+
})
62+
63+
const expected = "ok 2 - some/path/test-d.ts 1.01s"
64+
65+
t.equal(
66+
// TODO: snapshots?
67+
removeANSICodes(resultColored),
68+
expected,
69+
"given [success test result with default hasColor eq true] should return [a colored string with TAP test point - id, file name and duration]"
70+
)
71+
72+
t.equal(
73+
resultPlain,
74+
expected,
75+
"given [success test result with hasColor eq false] should return [a plain string with TAP test point - id, file name and duration]"
76+
)
77+
}
78+
79+
{
80+
const resultColored = tapReporter.formatTest({
81+
index: 1,
82+
result: {
83+
name: "some/path/test-d.ts",
84+
duration: [1, 10_000_000],
85+
errors: [
86+
{
87+
message: "Some bad thing happened",
88+
row: 1,
89+
column: 2,
90+
},
91+
],
92+
},
93+
})
94+
95+
const resultPlain = tapReporter.formatTest({
96+
index: 1,
97+
result: {
98+
name: "some/path/test-d.ts",
99+
duration: [1, 10_000_000],
100+
errors: [
101+
{
102+
message: "Some bad thing happened",
103+
row: 1,
104+
column: 2,
105+
},
106+
],
107+
},
108+
hasColor: false,
109+
})
110+
111+
const expected = [
112+
"not ok 2 - some/path/test-d.ts 1.01s",
113+
" ---",
114+
" message: Some bad thing happened",
115+
" severity: fail",
116+
" data:",
117+
" line: 1",
118+
" column: 2",
119+
" ...",
120+
].join("\n")
121+
122+
t.equal(
123+
// TODO: snapshots?
124+
removeANSICodes(resultColored),
125+
expected,
126+
"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]"
127+
)
128+
129+
t.equal(
130+
resultPlain,
131+
expected,
132+
"given [error test result with hasColor eq false] should return [a plain string with TAP test point - id, file name, duration and error YAMLBlock]"
133+
)
134+
}
135+
})
136+
137+
test("tap-reporter - formatSummary", t => {
138+
t.plan(2)
139+
140+
const resultColored = tapReporter.formatSummary({
141+
passCount: 2,
142+
failCount: 1,
143+
duration: [1, 10_000_000],
144+
})
145+
146+
const resultPlain = tapReporter.formatSummary({
147+
passCount: 2,
148+
failCount: 1,
149+
duration: [1, 10_000_000],
150+
hasColor: false,
151+
})
152+
153+
const expected = [
154+
"# tests 3",
155+
"# pass 2",
156+
"# fail 1",
157+
"# duration 1.01s",
158+
].join("\n")
159+
160+
t.equal(
161+
// TODO: snapshots?
162+
removeANSICodes(resultColored),
163+
expected,
164+
"given [] should return []"
165+
)
166+
167+
t.equal(resultPlain, expected, "given [] should return []")
168+
})

lib/utils/terminal-text.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,12 @@ export const cyan = {
6363

6464
/** @param {string} input */
6565
export const bold = input => `\u001B[1m${input}\u001B[0m`
66+
67+
/**
68+
* Clean a string from ANSI codes
69+
*
70+
* @param {string} input
71+
*/
72+
export const removeANSICodes = input =>
73+
// eslint-disable-next-line no-control-regex
74+
input.replace(/\u001B\[\d{1,3}m/g, "")

0 commit comments

Comments
 (0)