@thegetty/quire-cli 1.0.0-rc.45 → 1.0.0-rc.46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +0 -36
- package/README.md +0 -9
- package/bin/cli.js +1 -46
- package/package.json +10 -27
- package/src/Command.js +6 -26
- package/src/commands/README.md +122 -213
- package/src/commands/build.js +37 -45
- package/src/commands/clean.js +19 -33
- package/src/commands/conf.js +43 -0
- package/src/commands/create.js +14 -42
- package/src/commands/epub.js +31 -67
- package/src/commands/index.js +2 -9
- package/src/commands/info.js +86 -88
- package/src/commands/pdf.js +82 -63
- package/src/commands/preview.js +31 -32
- package/src/commands/validate.js +20 -64
- package/src/commands/version.js +43 -0
- package/src/errors/validation/validation-error.js +11 -20
- package/src/helpers/clean.js +1 -1
- package/src/helpers/is-quire.js +31 -0
- package/src/helpers/test-cwd.js +6 -5
- package/src/helpers/which.js +4 -10
- package/src/lib/11ty/README.md +19 -135
- package/src/lib/11ty/api.js +93 -235
- package/src/lib/11ty/cli.js +37 -112
- package/src/lib/11ty/index.js +5 -64
- package/src/lib/11ty/paths.js +103 -0
- package/src/lib/README.md +0 -330
- package/src/lib/conf/README.md +69 -86
- package/src/lib/conf/config.js +3 -5
- package/src/lib/conf/defaults.js +0 -65
- package/src/lib/conf/schema.js +9 -103
- package/src/lib/epub/README.md +2 -133
- package/src/lib/epub/epub.js +11 -36
- package/src/lib/epub/index.js +21 -111
- package/src/lib/epub/pandoc.js +4 -33
- package/src/lib/git/README.md +2 -151
- package/src/lib/git/index.js +13 -217
- package/src/lib/i18n/README.md +3 -0
- package/src/lib/i18n/config.js +53 -0
- package/src/lib/i18n/index.js +43 -0
- package/src/lib/i18n/localeService.js +58 -0
- package/src/lib/pdf/README.md +0 -131
- package/src/lib/pdf/index.js +21 -124
- package/src/lib/pdf/paged.js +52 -100
- package/src/lib/pdf/prince.js +37 -115
- package/src/lib/pdf/split.js +33 -61
- package/src/lib/quire/README.md +19 -0
- package/src/lib/quire/index.js +353 -0
- package/src/lib/reporter/README.md +2 -211
- package/src/lib/reporter/index.js +0 -607
- package/src/main.js +48 -221
- package/src/packageConfig.js +0 -17
- package/src/validators/utils.js +1 -2
- package/man/quire.1 +0 -341
- package/man/quire.1.md +0 -232
- package/schemas/config.schema.json +0 -194
- package/schemas/figures.schema.json +0 -56
- package/schemas/layout.schema.json +0 -5
- package/schemas/objects.schema.json +0 -62
- package/schemas/publication.schema.json +0 -140
- package/schemas/references.schema.json +0 -29
- package/src/Command.spec.js +0 -99
- package/src/commands/build.spec.js +0 -113
- package/src/commands/build.test.js +0 -397
- package/src/commands/clean.spec.js +0 -118
- package/src/commands/clean.test.js +0 -382
- package/src/commands/config.js +0 -238
- package/src/commands/config.spec.js +0 -107
- package/src/commands/config.test.js +0 -845
- package/src/commands/create.spec.js +0 -112
- package/src/commands/create.test.js +0 -415
- package/src/commands/doctor.js +0 -251
- package/src/commands/doctor.spec.js +0 -115
- package/src/commands/doctor.test.js +0 -1409
- package/src/commands/epub.spec.js +0 -114
- package/src/commands/epub.test.js +0 -503
- package/src/commands/help.js +0 -60
- package/src/commands/help.test.js +0 -132
- package/src/commands/info.spec.js +0 -72
- package/src/commands/info.test.js +0 -512
- package/src/commands/pdf.spec.js +0 -114
- package/src/commands/pdf.test.js +0 -464
- package/src/commands/preview.spec.js +0 -97
- package/src/commands/preview.test.js +0 -250
- package/src/commands/use.js +0 -56
- package/src/commands/use.spec.js +0 -61
- package/src/commands/use.test.js +0 -280
- package/src/commands/validate.spec.js +0 -90
- package/src/commands/validate.test.js +0 -378
- package/src/commands/workflows.js +0 -70
- package/src/errors/build/build-failed-error.js +0 -19
- package/src/errors/build/config-field-missing-error.js +0 -20
- package/src/errors/build/config-file-not-found-error.js +0 -20
- package/src/errors/build/index.js +0 -11
- package/src/errors/help/help-topic-not-found-error.js +0 -30
- package/src/errors/help/index.js +0 -8
- package/src/errors/index.js +0 -58
- package/src/errors/input/index.js +0 -8
- package/src/errors/input/invalid-input-error.js +0 -21
- package/src/errors/install/dependency-install-error.js +0 -19
- package/src/errors/install/directory-not-empty-error.js +0 -25
- package/src/errors/install/index.js +0 -12
- package/src/errors/install/invalid-path-error.js +0 -31
- package/src/errors/install/invalid-starter-error.js +0 -27
- package/src/errors/install/version-not-found-error.js +0 -35
- package/src/errors/output/epub-generation-error.js +0 -19
- package/src/errors/output/index.js +0 -14
- package/src/errors/output/invalid-epub-library-error.js +0 -20
- package/src/errors/output/invalid-pdf-library-error.js +0 -20
- package/src/errors/output/missing-build-output-error.js +0 -21
- package/src/errors/output/pdf-generation-error.js +0 -24
- package/src/errors/output/tool-not-found-error.js +0 -37
- package/src/errors/project/index.js +0 -10
- package/src/errors/project/not-in-project-error.js +0 -20
- package/src/errors/project/project-create-error.js +0 -21
- package/src/errors/quire-error.js +0 -27
- package/src/errors/validation/index.js +0 -3
- package/src/errors/validation/unknown-config-key-error.js +0 -27
- package/src/errors/validation/unknown-config-operation-error.js +0 -24
- package/src/helpers/docs-url.js +0 -32
- package/src/helpers/pager.js +0 -59
- package/src/helpers/pager.test.js +0 -85
- package/src/helpers/suggest-similar.js +0 -124
- package/src/helpers/suggest-similar.test.js +0 -108
- package/src/helpers/test-cwd.test.js +0 -192
- package/src/lib/11ty/index.test.js +0 -655
- package/src/lib/commander/index.js +0 -103
- package/src/lib/commander/index.test.js +0 -86
- package/src/lib/commander/options.js +0 -237
- package/src/lib/commander/options.test.js +0 -205
- package/src/lib/conf/build-status.js +0 -103
- package/src/lib/conf/build-status.test.js +0 -247
- package/src/lib/conf/config.test.js +0 -281
- package/src/lib/conf/format.js +0 -60
- package/src/lib/conf/format.test.js +0 -106
- package/src/lib/conf/helpers.js +0 -91
- package/src/lib/conf/helpers.test.js +0 -136
- package/src/lib/conf/index.js +0 -22
- package/src/lib/constants.js +0 -28
- package/src/lib/doctor/README.md +0 -667
- package/src/lib/doctor/checks/environment/cli-version.js +0 -62
- package/src/lib/doctor/checks/environment/cli-version.test.js +0 -132
- package/src/lib/doctor/checks/environment/git-available.js +0 -77
- package/src/lib/doctor/checks/environment/git-available.test.js +0 -52
- package/src/lib/doctor/checks/environment/index.js +0 -13
- package/src/lib/doctor/checks/environment/node-version.js +0 -66
- package/src/lib/doctor/checks/environment/node-version.test.js +0 -17
- package/src/lib/doctor/checks/environment/npm-available.js +0 -66
- package/src/lib/doctor/checks/environment/npm-available.test.js +0 -52
- package/src/lib/doctor/checks/environment/os-info.js +0 -48
- package/src/lib/doctor/checks/environment/os-info.test.js +0 -81
- package/src/lib/doctor/checks/environment/runtime-info.js +0 -51
- package/src/lib/doctor/checks/environment/runtime-info.test.js +0 -132
- package/src/lib/doctor/checks/outputs/epub-output.js +0 -119
- package/src/lib/doctor/checks/outputs/epub-output.test.js +0 -277
- package/src/lib/doctor/checks/outputs/index.js +0 -10
- package/src/lib/doctor/checks/outputs/pdf-output.js +0 -144
- package/src/lib/doctor/checks/outputs/pdf-output.test.js +0 -377
- package/src/lib/doctor/checks/outputs/stale-build.js +0 -122
- package/src/lib/doctor/checks/outputs/stale-build.test.js +0 -282
- package/src/lib/doctor/checks/project/data-files.js +0 -56
- package/src/lib/doctor/checks/project/data-files.test.js +0 -125
- package/src/lib/doctor/checks/project/dependencies.js +0 -53
- package/src/lib/doctor/checks/project/dependencies.test.js +0 -71
- package/src/lib/doctor/checks/project/index.js +0 -11
- package/src/lib/doctor/checks/project/quire-11ty.js +0 -98
- package/src/lib/doctor/checks/project/quire-11ty.test.js +0 -170
- package/src/lib/doctor/checks/project/quire-project.js +0 -38
- package/src/lib/doctor/checks/project/quire-project.test.js +0 -47
- package/src/lib/doctor/checks/tools/index.js +0 -10
- package/src/lib/doctor/checks/tools/pandoc-available.js +0 -82
- package/src/lib/doctor/checks/tools/pandoc-available.test.js +0 -73
- package/src/lib/doctor/checks/tools/prince-available.js +0 -81
- package/src/lib/doctor/checks/tools/prince-available.test.js +0 -73
- package/src/lib/doctor/constants.js +0 -39
- package/src/lib/doctor/formatDuration.js +0 -108
- package/src/lib/doctor/formatDuration.test.js +0 -76
- package/src/lib/doctor/formatters/human.js +0 -257
- package/src/lib/doctor/formatters/human.test.js +0 -463
- package/src/lib/doctor/formatters/index.js +0 -8
- package/src/lib/doctor/formatters/json.js +0 -78
- package/src/lib/doctor/formatters/json.test.js +0 -174
- package/src/lib/doctor/formatters/shared.js +0 -129
- package/src/lib/doctor/formatters/shared.test.js +0 -194
- package/src/lib/doctor/index.js +0 -271
- package/src/lib/doctor/index.test.js +0 -797
- package/src/lib/epub/engines.js +0 -46
- package/src/lib/epub/index.test.js +0 -518
- package/src/lib/epub/pandoc.test.js +0 -122
- package/src/lib/epub/schema.js +0 -21
- package/src/lib/error/README.md +0 -170
- package/src/lib/error/handler.js +0 -107
- package/src/lib/git/index.spec.js +0 -80
- package/src/lib/git/index.test.js +0 -453
- package/src/lib/help/frontmatter.js +0 -77
- package/src/lib/help/frontmatter.test.js +0 -139
- package/src/lib/help/index.js +0 -146
- package/src/lib/help/index.test.js +0 -188
- package/src/lib/help/topics/configuration.md +0 -77
- package/src/lib/help/topics/debugging.md +0 -69
- package/src/lib/help/topics/epub.md +0 -74
- package/src/lib/help/topics/pdf.md +0 -74
- package/src/lib/help/topics/publishing.md +0 -80
- package/src/lib/help/topics/workflows.md +0 -50
- package/src/lib/installer/index.js +0 -309
- package/src/lib/installer/index.spec.js +0 -83
- package/src/lib/installer/index.test.js +0 -545
- package/src/lib/logger/README.md +0 -424
- package/src/lib/logger/debug.js +0 -132
- package/src/lib/logger/debug.spec.js +0 -130
- package/src/lib/logger/debug.test.js +0 -128
- package/src/lib/logger/index.js +0 -228
- package/src/lib/logger/index.spec.js +0 -131
- package/src/lib/logger/index.test.js +0 -578
- package/src/lib/npm/README.md +0 -127
- package/src/lib/npm/index.js +0 -198
- package/src/lib/npm/index.spec.js +0 -60
- package/src/lib/npm/index.test.js +0 -355
- package/src/lib/pdf/engines.js +0 -46
- package/src/lib/pdf/index.test.js +0 -708
- package/src/lib/pdf/paged.test.js +0 -366
- package/src/lib/pdf/prince.test.js +0 -202
- package/src/lib/pdf/schema.js +0 -21
- package/src/lib/pdf/split.test.js +0 -445
- package/src/lib/platform.js +0 -95
- package/src/lib/process/manager.js +0 -110
- package/src/lib/process/manager.test.js +0 -55
- package/src/lib/project/build.js +0 -162
- package/src/lib/project/build.test.js +0 -275
- package/src/lib/project/config.js +0 -48
- package/src/lib/project/config.test.js +0 -134
- package/src/lib/project/detect.js +0 -47
- package/src/lib/project/detect.test.js +0 -157
- package/src/lib/project/index.js +0 -56
- package/src/lib/project/output-paths.js +0 -87
- package/src/lib/project/output-paths.test.js +0 -66
- package/src/lib/project/paths.js +0 -272
- package/src/lib/project/version.js +0 -110
- package/src/lib/project/version.test.js +0 -350
- package/src/lib/reporter/index.test.js +0 -862
- package/src/main.spec.js +0 -61
- package/src/main.test.js +0 -347
- package/src/validators/validate-data-files.js +0 -154
- package/src/validators/validate-data-files.test.js +0 -217
|
@@ -1,862 +0,0 @@
|
|
|
1
|
-
import esmock from 'esmock'
|
|
2
|
-
import sinon from 'sinon'
|
|
3
|
-
import test from 'ava'
|
|
4
|
-
import reporter, { Reporter } from './index.js'
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Reporter Module Tests
|
|
8
|
-
*
|
|
9
|
-
* Tests the Reporter class and singleton behavior for CLI progress feedback.
|
|
10
|
-
* Uses esmock to mock ora for controlled testing.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
test.beforeEach((t) => {
|
|
14
|
-
t.context.sandbox = sinon.createSandbox()
|
|
15
|
-
// Reset reporter state before each test
|
|
16
|
-
reporter.reset()
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
test.afterEach.always((t) => {
|
|
20
|
-
t.context.sandbox.restore()
|
|
21
|
-
reporter.reset()
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
25
|
-
// Singleton behavior tests
|
|
26
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
27
|
-
|
|
28
|
-
test('default export is a Reporter instance', (t) => {
|
|
29
|
-
t.true(reporter instanceof Reporter)
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
test('Reporter class is exported for testing', (t) => {
|
|
33
|
-
t.is(typeof Reporter, 'function')
|
|
34
|
-
const instance = new Reporter()
|
|
35
|
-
t.true(instance instanceof Reporter)
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
39
|
-
// Configuration tests
|
|
40
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
41
|
-
|
|
42
|
-
test('configure() sets quiet mode', (t) => {
|
|
43
|
-
reporter.configure({ quiet: true })
|
|
44
|
-
// Spinner should be suppressed - verify by checking isSpinning after start
|
|
45
|
-
reporter.start('Test')
|
|
46
|
-
t.false(reporter.isSpinning())
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
test('configure() sets json mode', (t) => {
|
|
50
|
-
reporter.configure({ json: true })
|
|
51
|
-
reporter.start('Test')
|
|
52
|
-
t.false(reporter.isSpinning())
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
test('configure() returns this for chaining', (t) => {
|
|
56
|
-
const result = reporter.configure({ quiet: false })
|
|
57
|
-
t.is(result, reporter)
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
test('configure() resets previous configuration', (t) => {
|
|
61
|
-
reporter.configure({ quiet: true })
|
|
62
|
-
reporter.configure({ quiet: false })
|
|
63
|
-
// After reset, spinner should work (if TTY)
|
|
64
|
-
// Can't test TTY directly, but verify configure doesn't throw
|
|
65
|
-
t.notThrows(() => reporter.configure({}))
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
69
|
-
// Start/stop tests
|
|
70
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
71
|
-
|
|
72
|
-
test('start() returns this for chaining', (t) => {
|
|
73
|
-
reporter.configure({ quiet: true })
|
|
74
|
-
const result = reporter.start('Test')
|
|
75
|
-
t.is(result, reporter)
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
test('stop() returns this for chaining', (t) => {
|
|
79
|
-
reporter.configure({ quiet: true })
|
|
80
|
-
reporter.start('Test')
|
|
81
|
-
const result = reporter.stop()
|
|
82
|
-
t.is(result, reporter)
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
test('stop() clears spinner state', (t) => {
|
|
86
|
-
reporter.configure({ quiet: true })
|
|
87
|
-
reporter.start('Test')
|
|
88
|
-
reporter.stop()
|
|
89
|
-
t.false(reporter.isSpinning())
|
|
90
|
-
})
|
|
91
|
-
|
|
92
|
-
test('start() stops previous spinner before starting new one', (t) => {
|
|
93
|
-
reporter.configure({ quiet: true })
|
|
94
|
-
reporter.start('First')
|
|
95
|
-
reporter.start('Second')
|
|
96
|
-
// Should not throw, previous spinner should be stopped
|
|
97
|
-
t.pass()
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
101
|
-
// Update tests
|
|
102
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
103
|
-
|
|
104
|
-
test('update() returns this for chaining', (t) => {
|
|
105
|
-
reporter.configure({ quiet: true })
|
|
106
|
-
reporter.start('Initial')
|
|
107
|
-
const result = reporter.update('Updated')
|
|
108
|
-
t.is(result, reporter)
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
test('update() starts spinner if none running', (t) => {
|
|
112
|
-
reporter.configure({ quiet: true })
|
|
113
|
-
reporter.update('Auto-start')
|
|
114
|
-
// Should not throw
|
|
115
|
-
t.pass()
|
|
116
|
-
})
|
|
117
|
-
|
|
118
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
119
|
-
// Status completion tests
|
|
120
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
121
|
-
|
|
122
|
-
test('succeed() returns this for chaining', (t) => {
|
|
123
|
-
reporter.configure({ quiet: true })
|
|
124
|
-
reporter.start('Test')
|
|
125
|
-
const result = reporter.succeed('Done')
|
|
126
|
-
t.is(result, reporter)
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
test('succeed() clears spinner', (t) => {
|
|
130
|
-
reporter.configure({ quiet: true })
|
|
131
|
-
reporter.start('Test')
|
|
132
|
-
reporter.succeed('Done')
|
|
133
|
-
t.false(reporter.isSpinning())
|
|
134
|
-
})
|
|
135
|
-
|
|
136
|
-
test('succeed() without text uses base text', (t) => {
|
|
137
|
-
reporter.configure({ quiet: true })
|
|
138
|
-
reporter.start('Base message')
|
|
139
|
-
reporter.succeed()
|
|
140
|
-
// Should not throw
|
|
141
|
-
t.pass()
|
|
142
|
-
})
|
|
143
|
-
|
|
144
|
-
test('fail() returns this for chaining', (t) => {
|
|
145
|
-
reporter.configure({ quiet: true })
|
|
146
|
-
reporter.start('Test')
|
|
147
|
-
const result = reporter.fail('Failed')
|
|
148
|
-
t.is(result, reporter)
|
|
149
|
-
})
|
|
150
|
-
|
|
151
|
-
test('fail() clears spinner', (t) => {
|
|
152
|
-
reporter.configure({ quiet: true })
|
|
153
|
-
reporter.start('Test')
|
|
154
|
-
reporter.fail('Failed')
|
|
155
|
-
t.false(reporter.isSpinning())
|
|
156
|
-
})
|
|
157
|
-
|
|
158
|
-
test('warn() returns this for chaining', (t) => {
|
|
159
|
-
reporter.configure({ quiet: true })
|
|
160
|
-
reporter.start('Test')
|
|
161
|
-
const result = reporter.warn('Warning')
|
|
162
|
-
t.is(result, reporter)
|
|
163
|
-
})
|
|
164
|
-
|
|
165
|
-
test('warn() clears spinner', (t) => {
|
|
166
|
-
reporter.configure({ quiet: true })
|
|
167
|
-
reporter.start('Test')
|
|
168
|
-
reporter.warn('Warning')
|
|
169
|
-
t.false(reporter.isSpinning())
|
|
170
|
-
})
|
|
171
|
-
|
|
172
|
-
test('info() returns this for chaining', (t) => {
|
|
173
|
-
reporter.configure({ quiet: true })
|
|
174
|
-
const result = reporter.info('Info message')
|
|
175
|
-
t.is(result, reporter)
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
179
|
-
// Elapsed time tests
|
|
180
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
181
|
-
|
|
182
|
-
test('getElapsed() returns null before start', (t) => {
|
|
183
|
-
reporter.reset()
|
|
184
|
-
t.is(reporter.getElapsed(), null)
|
|
185
|
-
})
|
|
186
|
-
|
|
187
|
-
test('getElapsed() returns elapsed time after start', async (t) => {
|
|
188
|
-
// Create a fresh Reporter instance for this test to avoid singleton issues
|
|
189
|
-
const rep = new Reporter()
|
|
190
|
-
rep.configure({ quiet: true })
|
|
191
|
-
rep.start('Test')
|
|
192
|
-
|
|
193
|
-
// Wait a small amount
|
|
194
|
-
await new Promise((resolve) => setTimeout(resolve, 50))
|
|
195
|
-
|
|
196
|
-
const elapsed = rep.getElapsed()
|
|
197
|
-
t.true(typeof elapsed === 'number', `elapsed should be a number, got: ${elapsed} (${typeof elapsed})`)
|
|
198
|
-
t.true(elapsed >= 40, `elapsed (${elapsed}ms) should be >= 40ms`)
|
|
199
|
-
|
|
200
|
-
// Clean up
|
|
201
|
-
rep.stop()
|
|
202
|
-
})
|
|
203
|
-
|
|
204
|
-
test('elapsed timer is cleared on succeed', async (t) => {
|
|
205
|
-
reporter.configure({ quiet: true })
|
|
206
|
-
reporter.start('Test', { showElapsed: true })
|
|
207
|
-
await new Promise((resolve) => setTimeout(resolve, 10))
|
|
208
|
-
reporter.succeed()
|
|
209
|
-
// Timer should be stopped - no way to directly test, but ensure no errors
|
|
210
|
-
t.pass()
|
|
211
|
-
})
|
|
212
|
-
|
|
213
|
-
test('elapsed timer is cleared on fail', async (t) => {
|
|
214
|
-
reporter.configure({ quiet: true })
|
|
215
|
-
reporter.start('Test', { showElapsed: true })
|
|
216
|
-
await new Promise((resolve) => setTimeout(resolve, 10))
|
|
217
|
-
reporter.fail()
|
|
218
|
-
t.pass()
|
|
219
|
-
})
|
|
220
|
-
|
|
221
|
-
test('elapsed timer is cleared on stop', async (t) => {
|
|
222
|
-
reporter.configure({ quiet: true })
|
|
223
|
-
reporter.start('Test', { showElapsed: true })
|
|
224
|
-
await new Promise((resolve) => setTimeout(resolve, 10))
|
|
225
|
-
reporter.stop()
|
|
226
|
-
t.pass()
|
|
227
|
-
})
|
|
228
|
-
|
|
229
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
230
|
-
// Reset tests
|
|
231
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
232
|
-
|
|
233
|
-
test('reset() returns this for chaining', (t) => {
|
|
234
|
-
const result = reporter.reset()
|
|
235
|
-
t.is(result, reporter)
|
|
236
|
-
})
|
|
237
|
-
|
|
238
|
-
test('reset() clears all state', (t) => {
|
|
239
|
-
reporter.configure({ quiet: true, json: true })
|
|
240
|
-
reporter.start('Test')
|
|
241
|
-
reporter.reset()
|
|
242
|
-
|
|
243
|
-
t.false(reporter.isSpinning())
|
|
244
|
-
t.is(reporter.getElapsed(), null)
|
|
245
|
-
})
|
|
246
|
-
|
|
247
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
248
|
-
// isSpinning tests
|
|
249
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
250
|
-
|
|
251
|
-
test('isSpinning() returns false initially', (t) => {
|
|
252
|
-
reporter.reset()
|
|
253
|
-
t.false(reporter.isSpinning())
|
|
254
|
-
})
|
|
255
|
-
|
|
256
|
-
test('isSpinning() returns false in quiet mode', (t) => {
|
|
257
|
-
reporter.configure({ quiet: true })
|
|
258
|
-
reporter.start('Test')
|
|
259
|
-
t.false(reporter.isSpinning())
|
|
260
|
-
})
|
|
261
|
-
|
|
262
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
263
|
-
// Integration tests with mocked ora
|
|
264
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
265
|
-
|
|
266
|
-
test.serial('start() calls ora with correct text', async (t) => {
|
|
267
|
-
const { sandbox } = t.context
|
|
268
|
-
const mockOraInstance = {
|
|
269
|
-
start: sandbox.stub().returnsThis(),
|
|
270
|
-
stop: sandbox.stub().returnsThis(),
|
|
271
|
-
succeed: sandbox.stub().returnsThis(),
|
|
272
|
-
fail: sandbox.stub().returnsThis(),
|
|
273
|
-
warn: sandbox.stub().returnsThis(),
|
|
274
|
-
info: sandbox.stub().returnsThis(),
|
|
275
|
-
isSpinning: true,
|
|
276
|
-
text: '',
|
|
277
|
-
}
|
|
278
|
-
const mockOra = sandbox.stub().returns(mockOraInstance)
|
|
279
|
-
|
|
280
|
-
const { Reporter: MockedReporter } = await esmock('./index.js', {
|
|
281
|
-
ora: { default: mockOra },
|
|
282
|
-
})
|
|
283
|
-
|
|
284
|
-
// Mock isTTY to enable spinner
|
|
285
|
-
const originalIsTTY = process.stdout.isTTY
|
|
286
|
-
process.stdout.isTTY = true
|
|
287
|
-
|
|
288
|
-
try {
|
|
289
|
-
const rep = new MockedReporter()
|
|
290
|
-
rep.start('Building...')
|
|
291
|
-
|
|
292
|
-
t.true(mockOra.calledOnce)
|
|
293
|
-
t.deepEqual(mockOra.firstCall.args[0], {
|
|
294
|
-
text: 'Building...',
|
|
295
|
-
spinner: 'dots',
|
|
296
|
-
})
|
|
297
|
-
} finally {
|
|
298
|
-
process.stdout.isTTY = originalIsTTY
|
|
299
|
-
}
|
|
300
|
-
})
|
|
301
|
-
|
|
302
|
-
test.serial('succeed() calls ora.succeed with text', async (t) => {
|
|
303
|
-
const { sandbox } = t.context
|
|
304
|
-
const mockOraInstance = {
|
|
305
|
-
start: sandbox.stub().returnsThis(),
|
|
306
|
-
stop: sandbox.stub().returnsThis(),
|
|
307
|
-
succeed: sandbox.stub().returnsThis(),
|
|
308
|
-
fail: sandbox.stub().returnsThis(),
|
|
309
|
-
warn: sandbox.stub().returnsThis(),
|
|
310
|
-
info: sandbox.stub().returnsThis(),
|
|
311
|
-
isSpinning: true,
|
|
312
|
-
text: '',
|
|
313
|
-
}
|
|
314
|
-
const mockOra = sandbox.stub().returns(mockOraInstance)
|
|
315
|
-
|
|
316
|
-
const { Reporter: MockedReporter } = await esmock('./index.js', {
|
|
317
|
-
ora: { default: mockOra },
|
|
318
|
-
})
|
|
319
|
-
|
|
320
|
-
const originalIsTTY = process.stdout.isTTY
|
|
321
|
-
process.stdout.isTTY = true
|
|
322
|
-
|
|
323
|
-
try {
|
|
324
|
-
const rep = new MockedReporter()
|
|
325
|
-
rep.start('Building...')
|
|
326
|
-
rep.succeed('Build complete')
|
|
327
|
-
|
|
328
|
-
t.true(mockOraInstance.succeed.calledOnce)
|
|
329
|
-
t.is(mockOraInstance.succeed.firstCall.args[0], 'Build complete')
|
|
330
|
-
} finally {
|
|
331
|
-
process.stdout.isTTY = originalIsTTY
|
|
332
|
-
}
|
|
333
|
-
})
|
|
334
|
-
|
|
335
|
-
test.serial('fail() calls ora.fail with text', async (t) => {
|
|
336
|
-
const { sandbox } = t.context
|
|
337
|
-
const mockOraInstance = {
|
|
338
|
-
start: sandbox.stub().returnsThis(),
|
|
339
|
-
stop: sandbox.stub().returnsThis(),
|
|
340
|
-
succeed: sandbox.stub().returnsThis(),
|
|
341
|
-
fail: sandbox.stub().returnsThis(),
|
|
342
|
-
warn: sandbox.stub().returnsThis(),
|
|
343
|
-
info: sandbox.stub().returnsThis(),
|
|
344
|
-
isSpinning: true,
|
|
345
|
-
text: '',
|
|
346
|
-
}
|
|
347
|
-
const mockOra = sandbox.stub().returns(mockOraInstance)
|
|
348
|
-
|
|
349
|
-
const { Reporter: MockedReporter } = await esmock('./index.js', {
|
|
350
|
-
ora: { default: mockOra },
|
|
351
|
-
})
|
|
352
|
-
|
|
353
|
-
const originalIsTTY = process.stdout.isTTY
|
|
354
|
-
process.stdout.isTTY = true
|
|
355
|
-
|
|
356
|
-
try {
|
|
357
|
-
const rep = new MockedReporter()
|
|
358
|
-
rep.start('Generating PDF...')
|
|
359
|
-
rep.fail('PDF generation failed')
|
|
360
|
-
|
|
361
|
-
t.true(mockOraInstance.fail.calledOnce)
|
|
362
|
-
t.is(mockOraInstance.fail.firstCall.args[0], 'PDF generation failed')
|
|
363
|
-
} finally {
|
|
364
|
-
process.stdout.isTTY = originalIsTTY
|
|
365
|
-
}
|
|
366
|
-
})
|
|
367
|
-
|
|
368
|
-
test.serial('warn() calls ora.warn with text', async (t) => {
|
|
369
|
-
const { sandbox } = t.context
|
|
370
|
-
const mockOraInstance = {
|
|
371
|
-
start: sandbox.stub().returnsThis(),
|
|
372
|
-
stop: sandbox.stub().returnsThis(),
|
|
373
|
-
succeed: sandbox.stub().returnsThis(),
|
|
374
|
-
fail: sandbox.stub().returnsThis(),
|
|
375
|
-
warn: sandbox.stub().returnsThis(),
|
|
376
|
-
info: sandbox.stub().returnsThis(),
|
|
377
|
-
isSpinning: true,
|
|
378
|
-
text: '',
|
|
379
|
-
}
|
|
380
|
-
const mockOra = sandbox.stub().returns(mockOraInstance)
|
|
381
|
-
|
|
382
|
-
const { Reporter: MockedReporter } = await esmock('./index.js', {
|
|
383
|
-
ora: { default: mockOra },
|
|
384
|
-
})
|
|
385
|
-
|
|
386
|
-
const originalIsTTY = process.stdout.isTTY
|
|
387
|
-
process.stdout.isTTY = true
|
|
388
|
-
|
|
389
|
-
try {
|
|
390
|
-
const rep = new MockedReporter()
|
|
391
|
-
rep.start('Checking...')
|
|
392
|
-
rep.warn('Dependencies outdated')
|
|
393
|
-
|
|
394
|
-
t.true(mockOraInstance.warn.calledOnce)
|
|
395
|
-
t.is(mockOraInstance.warn.firstCall.args[0], 'Dependencies outdated')
|
|
396
|
-
} finally {
|
|
397
|
-
process.stdout.isTTY = originalIsTTY
|
|
398
|
-
}
|
|
399
|
-
})
|
|
400
|
-
|
|
401
|
-
test.serial('update() changes spinner text', async (t) => {
|
|
402
|
-
const { sandbox } = t.context
|
|
403
|
-
const mockOraInstance = {
|
|
404
|
-
start: sandbox.stub().returnsThis(),
|
|
405
|
-
stop: sandbox.stub().returnsThis(),
|
|
406
|
-
succeed: sandbox.stub().returnsThis(),
|
|
407
|
-
fail: sandbox.stub().returnsThis(),
|
|
408
|
-
warn: sandbox.stub().returnsThis(),
|
|
409
|
-
info: sandbox.stub().returnsThis(),
|
|
410
|
-
isSpinning: true,
|
|
411
|
-
text: '',
|
|
412
|
-
}
|
|
413
|
-
const mockOra = sandbox.stub().returns(mockOraInstance)
|
|
414
|
-
|
|
415
|
-
const { Reporter: MockedReporter } = await esmock('./index.js', {
|
|
416
|
-
ora: { default: mockOra },
|
|
417
|
-
})
|
|
418
|
-
|
|
419
|
-
const originalIsTTY = process.stdout.isTTY
|
|
420
|
-
process.stdout.isTTY = true
|
|
421
|
-
|
|
422
|
-
try {
|
|
423
|
-
const rep = new MockedReporter()
|
|
424
|
-
rep.start('Step 1...')
|
|
425
|
-
rep.update('Step 2...')
|
|
426
|
-
|
|
427
|
-
t.is(mockOraInstance.text, 'Step 2...')
|
|
428
|
-
} finally {
|
|
429
|
-
process.stdout.isTTY = originalIsTTY
|
|
430
|
-
}
|
|
431
|
-
})
|
|
432
|
-
|
|
433
|
-
test.serial('spinner is not created when quiet=true', async (t) => {
|
|
434
|
-
const { sandbox } = t.context
|
|
435
|
-
const mockOra = sandbox.stub()
|
|
436
|
-
|
|
437
|
-
const { Reporter: MockedReporter } = await esmock('./index.js', {
|
|
438
|
-
ora: { default: mockOra },
|
|
439
|
-
})
|
|
440
|
-
|
|
441
|
-
const rep = new MockedReporter()
|
|
442
|
-
rep.configure({ quiet: true })
|
|
443
|
-
rep.start('Should not create spinner')
|
|
444
|
-
|
|
445
|
-
t.false(mockOra.called)
|
|
446
|
-
})
|
|
447
|
-
|
|
448
|
-
test.serial('spinner is not created when json=true', async (t) => {
|
|
449
|
-
const { sandbox } = t.context
|
|
450
|
-
const mockOra = sandbox.stub()
|
|
451
|
-
|
|
452
|
-
const { Reporter: MockedReporter } = await esmock('./index.js', {
|
|
453
|
-
ora: { default: mockOra },
|
|
454
|
-
})
|
|
455
|
-
|
|
456
|
-
const rep = new MockedReporter()
|
|
457
|
-
rep.configure({ json: true })
|
|
458
|
-
rep.start('Should not create spinner')
|
|
459
|
-
|
|
460
|
-
t.false(mockOra.called)
|
|
461
|
-
})
|
|
462
|
-
|
|
463
|
-
test.serial('spinner is not created when not TTY', async (t) => {
|
|
464
|
-
const { sandbox } = t.context
|
|
465
|
-
const mockOra = sandbox.stub()
|
|
466
|
-
|
|
467
|
-
const { Reporter: MockedReporter } = await esmock('./index.js', {
|
|
468
|
-
ora: { default: mockOra },
|
|
469
|
-
})
|
|
470
|
-
|
|
471
|
-
const originalIsTTY = process.stdout.isTTY
|
|
472
|
-
process.stdout.isTTY = false
|
|
473
|
-
|
|
474
|
-
try {
|
|
475
|
-
const rep = new MockedReporter()
|
|
476
|
-
rep.start('Should not create spinner')
|
|
477
|
-
|
|
478
|
-
t.false(mockOra.called)
|
|
479
|
-
} finally {
|
|
480
|
-
process.stdout.isTTY = originalIsTTY
|
|
481
|
-
}
|
|
482
|
-
})
|
|
483
|
-
|
|
484
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
485
|
-
// Elapsed time display tests
|
|
486
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
487
|
-
|
|
488
|
-
test.serial('showElapsed option updates spinner text with time', async (t) => {
|
|
489
|
-
const { sandbox } = t.context
|
|
490
|
-
const mockOraInstance = {
|
|
491
|
-
start: sandbox.stub().returnsThis(),
|
|
492
|
-
stop: sandbox.stub().returnsThis(),
|
|
493
|
-
succeed: sandbox.stub().returnsThis(),
|
|
494
|
-
fail: sandbox.stub().returnsThis(),
|
|
495
|
-
warn: sandbox.stub().returnsThis(),
|
|
496
|
-
info: sandbox.stub().returnsThis(),
|
|
497
|
-
isSpinning: true,
|
|
498
|
-
text: '',
|
|
499
|
-
}
|
|
500
|
-
const mockOra = sandbox.stub().returns(mockOraInstance)
|
|
501
|
-
|
|
502
|
-
const { Reporter: MockedReporter } = await esmock('./index.js', {
|
|
503
|
-
ora: { default: mockOra },
|
|
504
|
-
})
|
|
505
|
-
|
|
506
|
-
const originalIsTTY = process.stdout.isTTY
|
|
507
|
-
process.stdout.isTTY = true
|
|
508
|
-
|
|
509
|
-
let rep
|
|
510
|
-
try {
|
|
511
|
-
rep = new MockedReporter()
|
|
512
|
-
rep.start('Building...', { showElapsed: true })
|
|
513
|
-
|
|
514
|
-
// Wait for timer to tick (use 1200ms to account for CI timing variations)
|
|
515
|
-
await new Promise((resolve) => setTimeout(resolve, 1200))
|
|
516
|
-
|
|
517
|
-
// Nota bene: text should include elapsed time in format "(Ns)" where N is a number.
|
|
518
|
-
// We use a regex pattern to avoid flaky tests on slower CI systems.
|
|
519
|
-
t.regex(mockOraInstance.text, /\(\d+s\)/, 'spinner text should include elapsed time')
|
|
520
|
-
t.true(mockOraInstance.text.startsWith('Building...'), 'spinner text should include base text')
|
|
521
|
-
} finally {
|
|
522
|
-
// Ensure timer is stopped
|
|
523
|
-
if (rep) rep.stop()
|
|
524
|
-
process.stdout.isTTY = originalIsTTY
|
|
525
|
-
}
|
|
526
|
-
})
|
|
527
|
-
|
|
528
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
529
|
-
// Method call safety tests
|
|
530
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
531
|
-
|
|
532
|
-
test('calling succeed without start does not throw', (t) => {
|
|
533
|
-
reporter.reset()
|
|
534
|
-
t.notThrows(() => reporter.succeed('Done'))
|
|
535
|
-
})
|
|
536
|
-
|
|
537
|
-
test('calling fail without start does not throw', (t) => {
|
|
538
|
-
reporter.reset()
|
|
539
|
-
t.notThrows(() => reporter.fail('Failed'))
|
|
540
|
-
})
|
|
541
|
-
|
|
542
|
-
test('calling warn without start does not throw', (t) => {
|
|
543
|
-
reporter.reset()
|
|
544
|
-
t.notThrows(() => reporter.warn('Warning'))
|
|
545
|
-
})
|
|
546
|
-
|
|
547
|
-
test('calling stop without start does not throw', (t) => {
|
|
548
|
-
reporter.reset()
|
|
549
|
-
t.notThrows(() => reporter.stop())
|
|
550
|
-
})
|
|
551
|
-
|
|
552
|
-
test('calling update without start does not throw', (t) => {
|
|
553
|
-
reporter.reset()
|
|
554
|
-
t.notThrows(() => reporter.update('Update'))
|
|
555
|
-
})
|
|
556
|
-
|
|
557
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
558
|
-
// Workflow tests
|
|
559
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
560
|
-
|
|
561
|
-
test('typical success workflow', (t) => {
|
|
562
|
-
reporter.configure({ quiet: true })
|
|
563
|
-
reporter.start('Step 1...')
|
|
564
|
-
reporter.update('Step 2...')
|
|
565
|
-
reporter.update('Step 3...')
|
|
566
|
-
reporter.succeed('All steps complete')
|
|
567
|
-
t.pass()
|
|
568
|
-
})
|
|
569
|
-
|
|
570
|
-
test('typical failure workflow', (t) => {
|
|
571
|
-
reporter.configure({ quiet: true })
|
|
572
|
-
reporter.start('Processing...')
|
|
573
|
-
reporter.fail('Processing failed')
|
|
574
|
-
t.pass()
|
|
575
|
-
})
|
|
576
|
-
|
|
577
|
-
test('multi-phase workflow with different outcomes', (t) => {
|
|
578
|
-
reporter.configure({ quiet: true })
|
|
579
|
-
|
|
580
|
-
// Phase 1: success
|
|
581
|
-
reporter.start('Phase 1...')
|
|
582
|
-
reporter.succeed('Phase 1 complete')
|
|
583
|
-
|
|
584
|
-
// Phase 2: warning
|
|
585
|
-
reporter.start('Phase 2...')
|
|
586
|
-
reporter.warn('Phase 2 completed with warnings')
|
|
587
|
-
|
|
588
|
-
// Phase 3: failure
|
|
589
|
-
reporter.start('Phase 3...')
|
|
590
|
-
reporter.fail('Phase 3 failed')
|
|
591
|
-
|
|
592
|
-
t.pass()
|
|
593
|
-
})
|
|
594
|
-
|
|
595
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
596
|
-
// Reduced motion tests
|
|
597
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
598
|
-
|
|
599
|
-
test.serial('reduced motion: start() does not create ora spinner', async (t) => {
|
|
600
|
-
const { sandbox } = t.context
|
|
601
|
-
const mockOra = sandbox.stub()
|
|
602
|
-
|
|
603
|
-
const { Reporter: MockedReporter } = await esmock('./index.js', {
|
|
604
|
-
ora: { default: mockOra },
|
|
605
|
-
})
|
|
606
|
-
|
|
607
|
-
const originalIsTTY = process.stdout.isTTY
|
|
608
|
-
const originalReduceMotion = process.env.REDUCED_MOTION
|
|
609
|
-
const consoleLog = sandbox.stub(console, 'log')
|
|
610
|
-
|
|
611
|
-
try {
|
|
612
|
-
Object.defineProperty(process.stdout, 'isTTY', { value: true, configurable: true })
|
|
613
|
-
process.env.REDUCED_MOTION = '1'
|
|
614
|
-
|
|
615
|
-
const rep = new MockedReporter()
|
|
616
|
-
rep.start('Building...')
|
|
617
|
-
|
|
618
|
-
t.false(mockOra.called, 'ora should not be called in reduced motion mode')
|
|
619
|
-
t.true(consoleLog.calledOnce, 'console.log should be called once')
|
|
620
|
-
t.true(consoleLog.firstCall.args[0].includes('Building...'),
|
|
621
|
-
'output should include the text')
|
|
622
|
-
} finally {
|
|
623
|
-
Object.defineProperty(process.stdout, 'isTTY', { value: originalIsTTY, configurable: true })
|
|
624
|
-
if (originalReduceMotion === undefined) {
|
|
625
|
-
delete process.env.REDUCED_MOTION
|
|
626
|
-
} else {
|
|
627
|
-
process.env.REDUCED_MOTION = originalReduceMotion
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
|
-
})
|
|
631
|
-
|
|
632
|
-
test.serial('reduced motion: update() prints new line instead of overwriting', async (t) => {
|
|
633
|
-
const { sandbox } = t.context
|
|
634
|
-
const mockOra = sandbox.stub()
|
|
635
|
-
|
|
636
|
-
const { Reporter: MockedReporter } = await esmock('./index.js', {
|
|
637
|
-
ora: { default: mockOra },
|
|
638
|
-
})
|
|
639
|
-
|
|
640
|
-
const originalIsTTY = process.stdout.isTTY
|
|
641
|
-
const originalReduceMotion = process.env.REDUCED_MOTION
|
|
642
|
-
const consoleLog = sandbox.stub(console, 'log')
|
|
643
|
-
|
|
644
|
-
try {
|
|
645
|
-
Object.defineProperty(process.stdout, 'isTTY', { value: true, configurable: true })
|
|
646
|
-
process.env.REDUCED_MOTION = '1'
|
|
647
|
-
|
|
648
|
-
const rep = new MockedReporter()
|
|
649
|
-
rep.start('Step 1...')
|
|
650
|
-
rep.update('Step 2...')
|
|
651
|
-
|
|
652
|
-
t.is(consoleLog.callCount, 2, 'should print two separate lines')
|
|
653
|
-
t.true(consoleLog.firstCall.args[0].includes('Step 1...'))
|
|
654
|
-
t.true(consoleLog.secondCall.args[0].includes('Step 2...'))
|
|
655
|
-
} finally {
|
|
656
|
-
Object.defineProperty(process.stdout, 'isTTY', { value: originalIsTTY, configurable: true })
|
|
657
|
-
if (originalReduceMotion === undefined) {
|
|
658
|
-
delete process.env.REDUCED_MOTION
|
|
659
|
-
} else {
|
|
660
|
-
process.env.REDUCED_MOTION = originalReduceMotion
|
|
661
|
-
}
|
|
662
|
-
}
|
|
663
|
-
})
|
|
664
|
-
|
|
665
|
-
test.serial('reduced motion: succeed() prints static success line', async (t) => {
|
|
666
|
-
const { sandbox } = t.context
|
|
667
|
-
const mockOra = sandbox.stub()
|
|
668
|
-
|
|
669
|
-
const { Reporter: MockedReporter } = await esmock('./index.js', {
|
|
670
|
-
ora: { default: mockOra },
|
|
671
|
-
})
|
|
672
|
-
|
|
673
|
-
const originalIsTTY = process.stdout.isTTY
|
|
674
|
-
const originalReduceMotion = process.env.REDUCED_MOTION
|
|
675
|
-
const consoleLog = sandbox.stub(console, 'log')
|
|
676
|
-
|
|
677
|
-
try {
|
|
678
|
-
Object.defineProperty(process.stdout, 'isTTY', { value: true, configurable: true })
|
|
679
|
-
process.env.REDUCED_MOTION = '1'
|
|
680
|
-
|
|
681
|
-
const rep = new MockedReporter()
|
|
682
|
-
rep.start('Building...')
|
|
683
|
-
rep.succeed('Build complete')
|
|
684
|
-
|
|
685
|
-
t.is(consoleLog.callCount, 2)
|
|
686
|
-
// Second call is succeed
|
|
687
|
-
t.true(consoleLog.secondCall.args[0].includes('✔'))
|
|
688
|
-
t.true(consoleLog.secondCall.args[0].includes('Build complete'))
|
|
689
|
-
} finally {
|
|
690
|
-
Object.defineProperty(process.stdout, 'isTTY', { value: originalIsTTY, configurable: true })
|
|
691
|
-
if (originalReduceMotion === undefined) {
|
|
692
|
-
delete process.env.REDUCED_MOTION
|
|
693
|
-
} else {
|
|
694
|
-
process.env.REDUCED_MOTION = originalReduceMotion
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
})
|
|
698
|
-
|
|
699
|
-
test.serial('reduced motion: fail() prints static failure line', async (t) => {
|
|
700
|
-
const { sandbox } = t.context
|
|
701
|
-
const mockOra = sandbox.stub()
|
|
702
|
-
|
|
703
|
-
const { Reporter: MockedReporter } = await esmock('./index.js', {
|
|
704
|
-
ora: { default: mockOra },
|
|
705
|
-
})
|
|
706
|
-
|
|
707
|
-
const originalIsTTY = process.stdout.isTTY
|
|
708
|
-
const originalReduceMotion = process.env.REDUCED_MOTION
|
|
709
|
-
const consoleLog = sandbox.stub(console, 'log')
|
|
710
|
-
|
|
711
|
-
try {
|
|
712
|
-
Object.defineProperty(process.stdout, 'isTTY', { value: true, configurable: true })
|
|
713
|
-
process.env.REDUCED_MOTION = '1'
|
|
714
|
-
|
|
715
|
-
const rep = new MockedReporter()
|
|
716
|
-
rep.start('Generating PDF...')
|
|
717
|
-
rep.fail('PDF generation failed')
|
|
718
|
-
|
|
719
|
-
t.is(consoleLog.callCount, 2)
|
|
720
|
-
t.true(consoleLog.secondCall.args[0].includes('✖'))
|
|
721
|
-
t.true(consoleLog.secondCall.args[0].includes('PDF generation failed'))
|
|
722
|
-
} finally {
|
|
723
|
-
Object.defineProperty(process.stdout, 'isTTY', { value: originalIsTTY, configurable: true })
|
|
724
|
-
if (originalReduceMotion === undefined) {
|
|
725
|
-
delete process.env.REDUCED_MOTION
|
|
726
|
-
} else {
|
|
727
|
-
process.env.REDUCED_MOTION = originalReduceMotion
|
|
728
|
-
}
|
|
729
|
-
}
|
|
730
|
-
})
|
|
731
|
-
|
|
732
|
-
test.serial('reduced motion: warn() prints static warning line', async (t) => {
|
|
733
|
-
const { sandbox } = t.context
|
|
734
|
-
const mockOra = sandbox.stub()
|
|
735
|
-
|
|
736
|
-
const { Reporter: MockedReporter } = await esmock('./index.js', {
|
|
737
|
-
ora: { default: mockOra },
|
|
738
|
-
})
|
|
739
|
-
|
|
740
|
-
const originalIsTTY = process.stdout.isTTY
|
|
741
|
-
const originalReduceMotion = process.env.REDUCED_MOTION
|
|
742
|
-
const consoleLog = sandbox.stub(console, 'log')
|
|
743
|
-
|
|
744
|
-
try {
|
|
745
|
-
Object.defineProperty(process.stdout, 'isTTY', { value: true, configurable: true })
|
|
746
|
-
process.env.REDUCED_MOTION = '1'
|
|
747
|
-
|
|
748
|
-
const rep = new MockedReporter()
|
|
749
|
-
rep.start('Checking...')
|
|
750
|
-
rep.warn('Dependencies outdated')
|
|
751
|
-
|
|
752
|
-
t.is(consoleLog.callCount, 2)
|
|
753
|
-
t.true(consoleLog.secondCall.args[0].includes('⚠'))
|
|
754
|
-
t.true(consoleLog.secondCall.args[0].includes('Dependencies outdated'))
|
|
755
|
-
} finally {
|
|
756
|
-
Object.defineProperty(process.stdout, 'isTTY', { value: originalIsTTY, configurable: true })
|
|
757
|
-
if (originalReduceMotion === undefined) {
|
|
758
|
-
delete process.env.REDUCED_MOTION
|
|
759
|
-
} else {
|
|
760
|
-
process.env.REDUCED_MOTION = originalReduceMotion
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
})
|
|
764
|
-
|
|
765
|
-
test.serial('reduced motion: info() prints static info line', async (t) => {
|
|
766
|
-
const { sandbox } = t.context
|
|
767
|
-
const mockOra = sandbox.stub()
|
|
768
|
-
|
|
769
|
-
const { Reporter: MockedReporter } = await esmock('./index.js', {
|
|
770
|
-
ora: { default: mockOra },
|
|
771
|
-
})
|
|
772
|
-
|
|
773
|
-
const originalIsTTY = process.stdout.isTTY
|
|
774
|
-
const originalReduceMotion = process.env.REDUCED_MOTION
|
|
775
|
-
const consoleLog = sandbox.stub(console, 'log')
|
|
776
|
-
|
|
777
|
-
try {
|
|
778
|
-
Object.defineProperty(process.stdout, 'isTTY', { value: true, configurable: true })
|
|
779
|
-
process.env.REDUCED_MOTION = '1'
|
|
780
|
-
|
|
781
|
-
const rep = new MockedReporter()
|
|
782
|
-
rep.info('Using cached dependencies')
|
|
783
|
-
|
|
784
|
-
t.true(consoleLog.calledOnce)
|
|
785
|
-
t.true(consoleLog.firstCall.args[0].includes('ℹ'))
|
|
786
|
-
t.true(consoleLog.firstCall.args[0].includes('Using cached dependencies'))
|
|
787
|
-
} finally {
|
|
788
|
-
Object.defineProperty(process.stdout, 'isTTY', { value: originalIsTTY, configurable: true })
|
|
789
|
-
if (originalReduceMotion === undefined) {
|
|
790
|
-
delete process.env.REDUCED_MOTION
|
|
791
|
-
} else {
|
|
792
|
-
process.env.REDUCED_MOTION = originalReduceMotion
|
|
793
|
-
}
|
|
794
|
-
}
|
|
795
|
-
})
|
|
796
|
-
|
|
797
|
-
test.serial('reduced motion: multi-phase workflow outputs each phase on new line', async (t) => {
|
|
798
|
-
const { sandbox } = t.context
|
|
799
|
-
const mockOra = sandbox.stub()
|
|
800
|
-
|
|
801
|
-
const { Reporter: MockedReporter } = await esmock('./index.js', {
|
|
802
|
-
ora: { default: mockOra },
|
|
803
|
-
})
|
|
804
|
-
|
|
805
|
-
const originalIsTTY = process.stdout.isTTY
|
|
806
|
-
const originalReduceMotion = process.env.REDUCED_MOTION
|
|
807
|
-
const consoleLog = sandbox.stub(console, 'log')
|
|
808
|
-
|
|
809
|
-
try {
|
|
810
|
-
Object.defineProperty(process.stdout, 'isTTY', { value: true, configurable: true })
|
|
811
|
-
process.env.REDUCED_MOTION = '1'
|
|
812
|
-
|
|
813
|
-
const rep = new MockedReporter()
|
|
814
|
-
rep.start('Cloning starter...')
|
|
815
|
-
rep.update('Installing dependencies...')
|
|
816
|
-
rep.succeed('Project created')
|
|
817
|
-
|
|
818
|
-
t.is(consoleLog.callCount, 3, 'each stage should print on a new line')
|
|
819
|
-
t.true(consoleLog.getCall(0).args[0].includes('Cloning starter...'))
|
|
820
|
-
t.true(consoleLog.getCall(1).args[0].includes('Installing dependencies...'))
|
|
821
|
-
t.true(consoleLog.getCall(2).args[0].includes('✔'))
|
|
822
|
-
t.true(consoleLog.getCall(2).args[0].includes('Project created'))
|
|
823
|
-
t.false(mockOra.called, 'ora should never be called')
|
|
824
|
-
} finally {
|
|
825
|
-
Object.defineProperty(process.stdout, 'isTTY', { value: originalIsTTY, configurable: true })
|
|
826
|
-
if (originalReduceMotion === undefined) {
|
|
827
|
-
delete process.env.REDUCED_MOTION
|
|
828
|
-
} else {
|
|
829
|
-
process.env.REDUCED_MOTION = originalReduceMotion
|
|
830
|
-
}
|
|
831
|
-
}
|
|
832
|
-
})
|
|
833
|
-
|
|
834
|
-
test.serial('reduced motion: quiet mode takes precedence over reduced motion', async (t) => {
|
|
835
|
-
const { sandbox } = t.context
|
|
836
|
-
const mockOra = sandbox.stub()
|
|
837
|
-
|
|
838
|
-
const { Reporter: MockedReporter } = await esmock('./index.js', {
|
|
839
|
-
ora: { default: mockOra },
|
|
840
|
-
})
|
|
841
|
-
|
|
842
|
-
const originalReduceMotion = process.env.REDUCED_MOTION
|
|
843
|
-
const consoleLog = sandbox.stub(console, 'log')
|
|
844
|
-
|
|
845
|
-
try {
|
|
846
|
-
process.env.REDUCED_MOTION = '1'
|
|
847
|
-
|
|
848
|
-
const rep = new MockedReporter()
|
|
849
|
-
rep.configure({ quiet: true })
|
|
850
|
-
rep.start('Building...')
|
|
851
|
-
rep.succeed('Build complete')
|
|
852
|
-
|
|
853
|
-
t.false(consoleLog.called, 'quiet mode should suppress all output')
|
|
854
|
-
t.false(mockOra.called, 'ora should not be called')
|
|
855
|
-
} finally {
|
|
856
|
-
if (originalReduceMotion === undefined) {
|
|
857
|
-
delete process.env.REDUCED_MOTION
|
|
858
|
-
} else {
|
|
859
|
-
process.env.REDUCED_MOTION = originalReduceMotion
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
})
|