jest-audio-reporter 2.2.1 → 2.2.2

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/README.md CHANGED
@@ -2,12 +2,14 @@
2
2
 
3
3
  [![NPM version][npm-image]][npm-url]
4
4
  [![NPM downloads][downloads-image]][downloads-url]
5
- [![Build status][travis-image]][travis-url]
5
+
6
+ [![Github NodeJS][github-nodejs]][github-action-url]
6
7
  [![Codecov][codecov-image]][codecov-url]
7
- [![Coverage Status][coveralls-image]][coveralls-url]
8
8
 
9
- [![Greenkeeper badge][green-keeper-image]][green-keeper-url]
10
- [![semantic-release][semantic-release-image]][semantic-release-url]
9
+ [![Semantic Release][semantic-release-image]][semantic-release-url]
10
+
11
+ [![Visual Studio Code][vscode-image]][vscode-url]
12
+ [![Wallaby.js][wallaby-image]][wallaby-url]
11
13
 
12
14
  Play a tune while running [`jest`](https://jestjs.io/).
13
15
 
@@ -76,18 +78,19 @@ The audio files used for testing in this repository comes from <https://dova-s.j
76
78
 
77
79
  Please refer to them for copyright information.
78
80
 
79
- [npm-image]: https://img.shields.io/npm/v/jest-audio-reporter.svg?style=flat
80
- [npm-url]: https://npmjs.org/package/jest-audio-reporter
81
- [downloads-image]: https://img.shields.io/npm/dm/jest-audio-reporter.svg?style=flat
82
- [downloads-url]: https://npmjs.org/package/jest-audio-reporter
83
- [travis-image]: https://img.shields.io/travis/unional/jest-audio-reporter/master.svg?style=flat
84
- [travis-url]: https://travis-ci.org/unional/jest-audio-reporter?branch=master
85
81
  [codecov-image]: https://codecov.io/gh/unional/jest-audio-reporter/branch/master/graph/badge.svg
86
82
  [codecov-url]: https://codecov.io/gh/unional/jest-audio-reporter
87
83
  [coveralls-image]: https://coveralls.io/repos/github/unional/jest-audio-reporter/badge.svg
88
84
  [coveralls-url]: https://coveralls.io/github/unional/jest-audio-reporter
89
- [green-keeper-image]:
90
- https://badges.greenkeeper.io/unional/jest-audio-reporter.svg
91
- [green-keeper-url]:https://greenkeeper.io/
92
- [semantic-release-image]:https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg
93
- [semantic-release-url]:https://github.com/semantic-release/semantic-release
85
+ [downloads-image]: https://img.shields.io/npm/dm/jest-audio-reporter.svg?style=flat
86
+ [downloads-url]: https://npmjs.org/package/jest-audio-reporter
87
+ [github-nodejs]: https://github.com/unional/jest-audio-reporter/workflows/nodejs/badge.svg
88
+ [github-action-url]: https://github.com/unional/jest-audio-reporter/actions
89
+ [npm-image]: https://img.shields.io/npm/v/jest-audio-reporter.svg?style=flat
90
+ [npm-url]: https://npmjs.org/package/jest-audio-reporter
91
+ [semantic-release-image]: https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg
92
+ [semantic-release-url]: https://github.com/semantic-release/semantic-release
93
+ [vscode-image]: https://img.shields.io/badge/vscode-ready-green.svg
94
+ [vscode-url]: https://code.visualstudio.com/
95
+ [wallaby-image]: https://img.shields.io/badge/wallaby.js-configured-green.svg
96
+ [wallaby-url]: https://wallabyjs.com
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jest-audio-reporter",
3
- "version": "2.2.1",
3
+ "version": "2.2.2",
4
4
  "description": "Plays audio on jest events",
5
5
  "keywords": [
6
6
  "jest",
@@ -16,28 +16,61 @@
16
16
  "url": "https://github.com/unional/jest-audio-reporter.git"
17
17
  },
18
18
  "license": "MIT",
19
- "files": [
20
- "dist"
21
- ],
22
19
  "main": "dist/index.js",
23
20
  "typings": "dist/index.d.ts",
21
+ "files": [
22
+ "dist",
23
+ "ts"
24
+ ],
24
25
  "scripts": {
25
26
  "build": "tsc -p tsconfig.base.json",
26
27
  "clean": "rimraf dist",
27
- "dc": "npm run dependency-check",
28
- "dependency-check": "dependency-check . --unused --no-dev && dependency-check . --missing --no-dev",
29
- "lint": "tslint -p tsconfig.json",
28
+ "coverage": "jest --coverage",
29
+ "depscheck": "run-p dependency-check:unused dependency-check:missing",
30
+ "dependency-check": "run-p dependency-check:unused dependency-check:missing",
31
+ "dependency-check:unused": "dependency-check . --unused --no-dev -i @jest/reporters -i @jest/test-result -i @jest/types",
32
+ "dependency-check:missing": "dependency-check . --missing --no-dev",
33
+ "lint": "eslint --ext=ts,js .",
34
+ "release": "npx semantic-release",
35
+ "size-limit": "echo no size-limit",
30
36
  "test": "jest",
31
- "verify": "npm run lint && npm run build && npm run dependency-check && jest --coverage",
37
+ "verify": "run-p verify:build lint coverage",
38
+ "verify:build": "npm-run-all clean build --parallel dependency-check size-limit",
32
39
  "watch": "jest --watch"
33
40
  },
41
+ "husky": {
42
+ "hooks": {
43
+ "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
44
+ }
45
+ },
34
46
  "dependencies": {
35
- "play-sound": "^1.1.3",
47
+ "@jest/reporters": "^27.4.6",
48
+ "@jest/test-result": "^27.4.6",
49
+ "@jest/types": "^27.2.5",
50
+ "play-sound": "^1.1.5",
36
51
  "rc": "^1.2.8"
37
52
  },
38
53
  "devDependencies": {
39
- "@unional/devpkg-node": "^1.1.1",
40
- "assertron": "^5.2.3",
41
- "satisfier": "^4.5.0"
54
+ "@commitlint/cli": "^16.0.0",
55
+ "@commitlint/config-conventional": "^16.0.0",
56
+ "@types/jest": "^27.0.2",
57
+ "assertron": "^9.0.0",
58
+ "dependency-check": "^4.1.0",
59
+ "eslint": "^8.0.0",
60
+ "eslint-plugin-harmony": "^6.0.0",
61
+ "husky": "^7.0.4",
62
+ "jest": "^27.4.7",
63
+ "jest-junit": "^13.0.0",
64
+ "jest-progress-tracker": "^3.0.0",
65
+ "jest-validate": "^27.4.6",
66
+ "jest-watch-suspend": "^1.1.2",
67
+ "jest-watch-toggle-config": "^2.0.1",
68
+ "jest-watch-typeahead": "^1.0.0",
69
+ "npm-check-updates": "^12.0.0",
70
+ "npm-run-all": "^4.1.5",
71
+ "rimraf": "^3.0.2",
72
+ "satisfier": "^5.1.0",
73
+ "ts-jest": "^27.1.2",
74
+ "typescript": "^4.4.4"
42
75
  }
43
76
  }
@@ -0,0 +1,355 @@
1
+ import { ReporterOnStartOptions } from '@jest/reporters'
2
+ import { AggregatedResult } from '@jest/test-result'
3
+ import { Config } from '@jest/types'
4
+ import t from 'assert'
5
+ import { AssertOrder } from 'assertron'
6
+ import AudioReporter from '.'
7
+ import { RuntimeOptions } from './options'
8
+ import { store } from './store'
9
+
10
+ test('Will not play onSuitePass if no test ran', () => {
11
+ const subject = new AudioReporter(gc(), {})
12
+ subject.options = runtimeOptions({ onSuitePass: ['audio/onSuitePass/昇格.mp3'] })
13
+
14
+ subject.player = { play() { throw new Error('should not play') } }
15
+ subject.onRunComplete({}, ar({ numTotalTestSuites: 0 }))
16
+ })
17
+
18
+ test('Will not play onStart if test estimated to take less than 10s to run', () => {
19
+ const subject = new AudioReporter(gc(), {})
20
+ subject.options = runtimeOptions({
21
+ onSuitePass: ['audio/onSuitePass/昇格.mp3']
22
+ })
23
+
24
+ subject.player = { play() { throw new Error('should not play') } }
25
+ subject.onRunStart(ar(), { estimatedTime: 10, showStatus: false })
26
+ })
27
+
28
+ test('Will play onStart if test estimated to take more than 10s to run', () => {
29
+ const subject = new AudioReporter(gc(), {})
30
+ subject.options = runtimeOptions({ onSuitePass: ['audio/onSuitePass/昇格.mp3'] })
31
+
32
+ const o = new AssertOrder(1)
33
+ subject.player = { play() { o.once(1) } }
34
+ subject.onRunStart(ar(), { estimatedTime: 10.01, showStatus: false })
35
+
36
+ o.end()
37
+ })
38
+
39
+ test('Will play onStart if there is no estimate', () => {
40
+ const subject = new AudioReporter(gc(), {})
41
+ subject.options = runtimeOptions({ onSuitePass: ['audio/onSuitePass/昇格.mp3'] })
42
+
43
+ const o = new AssertOrder(1)
44
+ subject.player = { play() { o.once(1) } }
45
+ subject.onRunStart(ar({ numTotalTestSuites: 1 }), { estimatedTime: 0, showStatus: false })
46
+
47
+ o.end()
48
+ })
49
+
50
+ test('pick one if onStart has more than one entry', () => {
51
+ const subject = new AudioReporter(gc(), {})
52
+ subject.options = runtimeOptions({
53
+ onStart: ['audio/onSuitePass/昇格.mp3', 'audio/onSuitePass/勝利ジングル.mp3']
54
+ })
55
+
56
+ const calls = [0, 0]
57
+ subject.player = {
58
+ play(file) {
59
+ calls[subject.options.onStart.indexOf(file)]++
60
+ }
61
+ }
62
+ for (let i = 0; i < 100; i++)
63
+ subject.onRunStart(ar(), { estimatedTime: 10.01, showStatus: false })
64
+
65
+ t(calls[0] * calls[1] > 0)
66
+ })
67
+ test('pick one if onSuitePass is an array', () => {
68
+ const subject = new AudioReporter(gc(), {})
69
+ subject.options = runtimeOptions({
70
+ onSuitePass: ['audio/onSuitePass/昇格.mp3', 'audio/onSuitePass/勝利ジングル.mp3']
71
+ })
72
+ const calls = [0, 0]
73
+ subject.player = {
74
+ play(file) {
75
+ calls[subject.options.onSuitePass.indexOf(file)]++
76
+ }
77
+ }
78
+ for (let i = 0; i < 100; i++)
79
+ subject.onRunComplete({}, ar({ numTotalTestSuites: 1, numFailedTestSuites: 0 }))
80
+
81
+ t(calls[0] * calls[1] > 0)
82
+ })
83
+ test('pick one if onSuiteFailure is an array', () => {
84
+ const subject = new AudioReporter(gc(), {})
85
+ subject.options = runtimeOptions({
86
+ onSuiteFailure: ['audio/onSuitePass/昇格.mp3', 'audio/onSuitePass/勝利ジングル.mp3']
87
+ })
88
+ const calls = [0, 0]
89
+ subject.player = {
90
+ play(file) {
91
+ calls[subject.options.onSuiteFailure.indexOf(file)]++
92
+ }
93
+ }
94
+ for (let i = 0; i < 100; i++)
95
+ subject.onRunComplete({}, ar({ numTotalTestSuites: 1, numFailedTestSuites: 1 }))
96
+
97
+ t(calls[0] * calls[1] > 0)
98
+ })
99
+
100
+ describe('watch mode', () => {
101
+ test('play onSuitePass on first run', () => {
102
+ const subject = new AudioReporter(gc({ watch: true }), {})
103
+ subject.options = runtimeOptions({
104
+ onSuitePass: ['audio/onSuitePass/昇格.mp3']
105
+ })
106
+ store.reset()
107
+
108
+ const o = new AssertOrder(1)
109
+ subject.player = { play() { o.once(1) } }
110
+ subject.onRunComplete({}, ar({ numTotalTestSuites: 1, numFailedTestSuites: 0 }))
111
+ o.end()
112
+ })
113
+ test('do not play onSuitePass on second pass', () => {
114
+ const subject = new AudioReporter(gc({ watch: true }), {})
115
+ subject.options = runtimeOptions({
116
+ onSuitePass: ['audio/onSuitePass/昇格.mp3']
117
+ })
118
+ store.reset()
119
+
120
+ const o = new AssertOrder(1)
121
+ subject.player = { play() { o.once(1) } }
122
+ subject.onRunComplete({}, ar({ numTotalTestSuites: 1, numFailedTestSuites: 0 }))
123
+ subject.onRunComplete({}, ar({ numTotalTestSuites: 1, numFailedTestSuites: 0 }))
124
+ o.end()
125
+ })
126
+ test('play onSuitePass again on pass after failure', () => {
127
+ const subject = new AudioReporter(gc({ watch: true }), {})
128
+ subject.options = runtimeOptions({
129
+ onSuitePass: ['audio/onSuitePass/昇格.mp3'],
130
+ onSuiteFailure: ['audio/onSuitePass/昇格.mp3']
131
+ })
132
+ store.reset()
133
+ const o = new AssertOrder(1)
134
+ subject.player = {
135
+ play() {
136
+ o.exactly(1, 3)
137
+ }
138
+ }
139
+ subject.onRunComplete({}, ar({ numTotalTestSuites: 1, numFailedTestSuites: 0 }))
140
+ subject.onRunComplete({}, ar({ numTotalTestSuites: 1, numFailedTestSuites: 1 }))
141
+ subject.onRunComplete({}, ar({ numTotalTestSuites: 1, numFailedTestSuites: 0 }))
142
+ o.end()
143
+ })
144
+ test('do not play onSuitePass/Failure on interruption', () => {
145
+ const subject = new AudioReporter(gc({ watch: true }), {})
146
+ subject.options = runtimeOptions({
147
+ onSuitePass: ['audio/onSuitePass/昇格.mp3'],
148
+ onSuiteFailure: ['audio/onSuitePass/昇格.mp3']
149
+ })
150
+ store.reset()
151
+
152
+ subject.player = { play() { throw new Error('should not play') } }
153
+ subject.onRunComplete({}, ar({ numTotalTestSuites: 1, numFailedTestSuites: 0, wasInterrupted: true }))
154
+ subject.onRunComplete({}, ar({ numTotalTestSuites: 1, numFailedTestSuites: 1, wasInterrupted: true }))
155
+ })
156
+ test('kill onStart when run completes', () => {
157
+ const subject = new AudioReporter(gc({ watch: true }), {})
158
+ subject.options = runtimeOptions({
159
+ onStart: ['audio/onSuitePass/昇格.mp3']
160
+ })
161
+ store.reset()
162
+
163
+ const o = new AssertOrder(1)
164
+ subject.player = { play() { return { kill() { o.once(1) } } } }
165
+ subject.onRunStart(ar(), { estimatedTime: 11, showStatus: false })
166
+ subject.onRunComplete({}, ar())
167
+ o.end()
168
+ })
169
+ test('kill onSuitePass when run starts', () => {
170
+ const subject = new AudioReporter(gc({ watch: true }), {})
171
+ subject.options = runtimeOptions({
172
+ onStart: ['audio/onSuitePass/昇格.mp3'],
173
+ onSuitePass: ['audio/onSuitePass/昇格.mp3']
174
+ })
175
+ store.reset()
176
+
177
+ const o = new AssertOrder(1)
178
+ subject.player = { play() { return { kill() { o.once(1) } } } }
179
+ subject.onRunComplete({}, ar({ numTotalTestSuites: 1, numFailedTestSuites: 0 }))
180
+ subject.onRunStart(ar(), { estimatedTime: 11, showStatus: false })
181
+ o.end()
182
+ })
183
+ test('kill onSuiteFailure when run starts', () => {
184
+ const subject = new AudioReporter(gc({ watch: true }), {})
185
+ subject.options = runtimeOptions({
186
+ onStart: ['audio/onSuitePass/昇格.mp3'],
187
+ onSuiteFailure: ['audio/onSuitePass/昇格.mp3']
188
+ })
189
+ store.reset()
190
+
191
+ const o = new AssertOrder(1)
192
+ subject.player = { play() { return { kill() { o.once(1) } } } }
193
+ subject.onRunComplete({}, ar({ numTotalTestSuites: 1, numFailedTestSuites: 1 }))
194
+ subject.onRunStart(ar(), { estimatedTime: 11, showStatus: false })
195
+ o.end()
196
+ })
197
+ })
198
+
199
+ test('when debug = true, log is enabled', () => {
200
+ store.devel = true
201
+ try {
202
+ const subject = new AudioReporter(gc(), { debug: true })
203
+ t.strictEqual(subject.log.enabled, true)
204
+ }
205
+ catch {
206
+ store.devel = false
207
+ }
208
+ })
209
+
210
+ test('when debug = false, log is not enabled', () => {
211
+ const subject = new AudioReporter(gc(), { debug: false })
212
+ t.strictEqual(subject.log.enabled, false)
213
+ })
214
+
215
+ test('lower master volume in OSX affect onStart', () => {
216
+ const subject = new AudioReporter(gc(), { volume: 0.25 })
217
+ let actual
218
+ subject.player = { player: 'afplay', play(_file, option) { actual = option } }
219
+
220
+ subject.onRunStart(ar({ numTotalTestSuites: 1 }), roso({ estimatedTime: 11 }))
221
+ t.deepStrictEqual(actual, { afplay: ['-v', 0.01] })
222
+ })
223
+
224
+ test('lower master volume in OSX affect onComplete', () => {
225
+ const subject = new AudioReporter(gc(), { volume: 0.25 })
226
+ let actual
227
+ subject.player = { player: 'afplay', play(_file, option) { actual = option } }
228
+
229
+ subject.onRunComplete(undefined, ar({ numTotalTestSuites: 1 }))
230
+ t.deepStrictEqual(actual, { afplay: ['-v', 0.01] })
231
+ })
232
+
233
+ test('lower master volume in Windows affect onStart', () => {
234
+ const subject = new AudioReporter(gc(), { volume: 0.25 })
235
+ let actual
236
+ subject.player = { player: 'mplayer', play(_file, option) { actual = option } }
237
+
238
+ subject.onRunStart(ar({ numTotalTestSuites: 1 }), roso({ estimatedTime: 11 }))
239
+ t.deepStrictEqual(actual, { mplayer: ['-volume', 25] })
240
+ })
241
+
242
+ test('lower master volume in Windows affect onComplete', () => {
243
+ const subject = new AudioReporter(gc(), { volume: 0.25 })
244
+ let actual
245
+ subject.player = { player: 'mplayer', play(_file, option) { actual = option } }
246
+
247
+ subject.onRunComplete(undefined, ar({ numTotalTestSuites: 1 }))
248
+ t.deepStrictEqual(actual, { mplayer: ['-volume', 25] })
249
+ })
250
+
251
+ test('lower onStartVolume in OSX affect onStart', () => {
252
+ const subject = new AudioReporter(gc(), { onStartVolume: 0.25 })
253
+ let actual
254
+ subject.player = { player: 'afplay', play(_file, option) { actual = option } }
255
+
256
+ subject.onRunStart(ar({ numTotalTestSuites: 1 }), roso({ estimatedTime: 11 }))
257
+ t.deepStrictEqual(actual, { afplay: ['-v', 0.01] })
258
+ })
259
+
260
+ test('lower onStartVolume in OSX will not affect onComplete', () => {
261
+ const subject = new AudioReporter(gc(), { onStartVolume: 0.25 })
262
+ let actual
263
+ subject.player = { player: 'afplay', play(_file, option) { actual = option } }
264
+
265
+ subject.onRunComplete(undefined, ar({ numTotalTestSuites: 1 }))
266
+ t.deepStrictEqual(actual, { afplay: ['-v', 1] })
267
+ })
268
+
269
+ test('lower onStartVolume in Windows affect onStart', () => {
270
+ const subject = new AudioReporter(gc(), { onStartVolume: 0.25 })
271
+ let actual
272
+ subject.player = { player: 'mplayer', play(_file, option) { actual = option } }
273
+
274
+ subject.onRunStart(ar({ numTotalTestSuites: 1 }), roso({ estimatedTime: 11 }))
275
+ t.deepStrictEqual(actual, { mplayer: ['-volume', 25] })
276
+ })
277
+
278
+ test('lower onStartVolume in Windows will not affect onComplete', () => {
279
+ const subject = new AudioReporter(gc(), { onStartVolume: 0.25 })
280
+ let actual
281
+ subject.player = { player: 'mplayer', play(_file, option) { actual = option } }
282
+
283
+ subject.onRunComplete(undefined, ar({ numTotalTestSuites: 1 }))
284
+ t.deepStrictEqual(actual, { mplayer: ['-volume', 100] })
285
+ })
286
+
287
+ test('lower onCompleteVolume in OSX will not affect onStart', () => {
288
+ const subject = new AudioReporter(gc(), { onCompleteVolume: 0.25 })
289
+ let actual
290
+ subject.player = { player: 'afplay', play(_file, option) { actual = option } }
291
+
292
+ subject.onRunStart(ar({ numTotalTestSuites: 1 }), roso({ estimatedTime: 11 }))
293
+ t.deepStrictEqual(actual, { afplay: ['-v', 0.1] })
294
+ })
295
+
296
+ test('lower onCompleteVolume in OSX affect onComplete', () => {
297
+ const subject = new AudioReporter(gc(), { onCompleteVolume: 0.25 })
298
+ let actual
299
+ subject.player = { player: 'afplay', play(_file, option) { actual = option } }
300
+
301
+ subject.onRunComplete(undefined, ar({ numTotalTestSuites: 1 }))
302
+ t.deepStrictEqual(actual, { afplay: ['-v', 0.01] })
303
+ })
304
+
305
+ test('lower onCompleteVolume in Windows will not affect onStart', () => {
306
+ const subject = new AudioReporter(gc(), { onCompleteVolume: 0.25 })
307
+ let actual
308
+ subject.player = { player: 'mplayer', play(_file, option) { actual = option } }
309
+
310
+ subject.onRunStart(ar({ numTotalTestSuites: 1 }), roso({ estimatedTime: 11 }))
311
+ t.deepStrictEqual(actual, { mplayer: ['-volume', 50] })
312
+ })
313
+
314
+ test('lower onCompleteVolume in Windows affect onComplete', () => {
315
+ const subject = new AudioReporter(gc(), { onCompleteVolume: 0.25 })
316
+ let actual
317
+ subject.player = { player: 'mplayer', play(_file, option) { actual = option } }
318
+
319
+ subject.onRunComplete(undefined, ar({ numTotalTestSuites: 1 }))
320
+ t.deepStrictEqual(actual, { mplayer: ['-volume', 25] })
321
+ })
322
+
323
+ test('disable will not play when complete', async () => {
324
+ const subject = new AudioReporter(gc(), { disable: true })
325
+ subject.player = { player: 'mplayer', play() { throw new Error('should not call') } }
326
+ await subject.onRunComplete(undefined, ar({ numTotalTestSuites: 1 }))
327
+ })
328
+
329
+ test('disable will not play when complete', () => {
330
+ const subject = new AudioReporter(gc(), { disable: true })
331
+ subject.player = { player: 'mplayer', play() { throw new Error('should not call') } }
332
+ subject.onRunStart(ar({ numTotalTestSuites: 1 }), roso({ estimatedTime: 11 }))
333
+ })
334
+
335
+ function gc(config: Partial<Config.GlobalConfig> = {}) {
336
+ return config as Config.GlobalConfig
337
+ }
338
+
339
+ function ar(results: Partial<AggregatedResult> = {}) {
340
+ return results as AggregatedResult
341
+ }
342
+
343
+ function roso(options: Partial<ReporterOnStartOptions> = {}) {
344
+ return options as ReporterOnStartOptions
345
+ }
346
+
347
+ function runtimeOptions(options: Partial<RuntimeOptions>) {
348
+ return {
349
+ onStart: [],
350
+ onSuitePass: [],
351
+ onSuiteFailure: [],
352
+ onStartThreshold: 10,
353
+ ...options
354
+ }
355
+ }
@@ -0,0 +1,123 @@
1
+ import type { ReporterOnStartOptions } from '@jest/reporters'
2
+ import type { AggregatedResult } from '@jest/test-result'
3
+ import type { Config } from '@jest/types'
4
+ import Player from 'play-sound'
5
+ import rc from 'rc'
6
+
7
+ import { createLog, logOptions } from './log'
8
+ import { Options, processOptions, RuntimeOptions } from './options'
9
+ import { store } from './store'
10
+
11
+ export class AudioReporter {
12
+ log = createLog()
13
+ player
14
+ disable: boolean
15
+ options: RuntimeOptions
16
+ volume: number | undefined
17
+ onStartVolume: number
18
+ onCompleteVolume: number | undefined
19
+ constructor(public globalConfig: Config.GlobalConfig, jestOptions: Partial<Options>) {
20
+ if (jestOptions.debug) {
21
+ this.log.enabled = true
22
+ }
23
+ this.player = Player({})
24
+ this.disable = !!jestOptions.disable
25
+ this.volume = jestOptions.volume
26
+ this.onStartVolume = jestOptions.onStartVolume || 0.5
27
+ this.onCompleteVolume = jestOptions.onCompleteVolume
28
+
29
+ const rawRCOptions = rc('jest-audio-reporter')
30
+ const rcOptions = processOptions(rawRCOptions)
31
+ logOptions({ log: this.log }, rawRCOptions, rcOptions)
32
+ this.options = rcOptions
33
+ }
34
+ onRunStart(results: AggregatedResult, options: ReporterOnStartOptions) {
35
+ if (this.disable) return
36
+
37
+ if (store.completeAudio) {
38
+ store.completeAudio.kill()
39
+ store.completeAudio = undefined
40
+ }
41
+
42
+ if (results.numTotalTestSuites === 0 ||
43
+ options.estimatedTime > 0 &&
44
+ options.estimatedTime <= this.options.onStartThreshold) return
45
+
46
+ const file = pickOne(this.options.onStart)
47
+ const volume = this.getEffectiveOnStartVolume()
48
+ store.startAudio = this.player.play(file, this.getPlayOption({ volume }))
49
+ }
50
+ onRunComplete(_contexts, results: AggregatedResult) {
51
+ if (this.disable) return
52
+
53
+ if (store.startAudio) {
54
+ store.startAudio.kill()
55
+ store.startAudio = undefined
56
+ }
57
+ if (results.numTotalTestSuites === 0) return
58
+ if (results.wasInterrupted) return
59
+
60
+ if (results.numFailedTestSuites === 0) {
61
+ if (isWatch(this.globalConfig) && store.doesLastRunPass) return
62
+ store.doesLastRunPass = true
63
+ return this.playComplete(pickOne(this.options.onSuitePass))
64
+ }
65
+ else {
66
+ store.doesLastRunPass = false
67
+ return this.playComplete(pickOne(this.options.onSuiteFailure))
68
+ }
69
+ }
70
+ private playComplete(file: string | undefined) {
71
+ if (!file) return
72
+ const volume = this.getEffectiveOnCompleteVolume()
73
+ if (isWatch(this.globalConfig)) {
74
+ store.completeAudio = this.player.play(file, this.getPlayOption({ volume }))
75
+ }
76
+ else {
77
+ return new Promise(a => {
78
+ store.completeAudio = this.player.play(file, this.getPlayOption({ volume }), a)
79
+ })
80
+ }
81
+ }
82
+ private getEffectiveOnStartVolume() {
83
+ return Math.min(this.volume || 1, this.onStartVolume)
84
+ }
85
+ private getEffectiveOnCompleteVolume() {
86
+ return Math.min(this.volume || 1, this.onCompleteVolume || 1)
87
+ }
88
+ private getPlayOption(option) {
89
+ switch (this.player.player) {
90
+ case 'afplay':
91
+ return getAfPlayOption(option)
92
+ case 'mplayer':
93
+ return getMplayerOption(option)
94
+ default:
95
+ return {}
96
+ }
97
+ }
98
+ }
99
+
100
+ function pickOne(arr: Array<any>) {
101
+ if (arr.length === 0) return undefined
102
+ return arr[Math.floor(Math.random() * arr.length)]
103
+ }
104
+
105
+ function isWatch(globalConfig) {
106
+ return globalConfig.watch || globalConfig.watchAll
107
+ }
108
+
109
+ function getAfPlayOption({ volume }: { volume: number }) {
110
+ // https://ss64.com/osx/afplay.html
111
+ // According to the link, the volume is logarithmic,
112
+ // but I'm not sure what does it mean, as:
113
+ // log(1) = 0
114
+ // log(0.1) = -1
115
+ // log(0) = -infinity
116
+ // So for now, I treat [0, 1] as linear
117
+ return { afplay: ['-v', 1 / (Math.pow(10, Math.log2(1 / volume)))] }
118
+ }
119
+
120
+ function getMplayerOption({ volume }: { volume: number }) {
121
+ // http://www.mplayerhq.hu/DOCS/man/en/mplayer.1.html search for "-volume"
122
+ return { mplayer: ['-volume', volume * 100] }
123
+ }
package/ts/index.ts ADDED
@@ -0,0 +1,11 @@
1
+ import { store } from './store'
2
+
3
+ // istanbul ignore next
4
+ process.on('exit', () => {
5
+ if (store.startAudio) store.startAudio.kill()
6
+ if (store.completeAudio) store.completeAudio.kill()
7
+ })
8
+
9
+ import { AudioReporter } from './AudioReporter'
10
+
11
+ export default AudioReporter
package/ts/log.spec.ts ADDED
@@ -0,0 +1,55 @@
1
+ import t from 'assert'
2
+ import { logOptions, createLog } from './log';
3
+
4
+ test('enabled log will print', () => {
5
+ const log = createLog()
6
+ log.enabled = true
7
+ let actual
8
+ log.writer = { info(msg) { actual = msg } } as any
9
+ log.debug('should print')
10
+ t.strictEqual(actual, 'should print')
11
+ })
12
+
13
+ test('log config location and option', () => {
14
+ const c = context()
15
+ logOptions(c, {
16
+ onSuitePass: ['music1.mp3'],
17
+ configs: [
18
+ 'rcfile1',
19
+ 'rcfile2'
20
+ ]
21
+ }, { onSuitePass: ['music1.mp3'] })
22
+ t.deepStrictEqual(c.log.messages, [
23
+ [`configs location:
24
+ rcfile1
25
+ rcfile2
26
+
27
+ options:
28
+ {
29
+ "onSuitePass": [
30
+ "music1.mp3"
31
+ ]
32
+ }
33
+ `]
34
+ ])
35
+ })
36
+
37
+ test('no config prints no config detected', () => {
38
+ const log = createLog()
39
+ log.enabled = true
40
+ let actual
41
+ log.writer = { info(msg) { actual = msg } } as any
42
+ logOptions({ log }, {}, undefined)
43
+ t.strictEqual(actual, 'no config detected')
44
+ })
45
+
46
+ function context() {
47
+ return {
48
+ log: {
49
+ debug(...args) {
50
+ this.messages.push(args)
51
+ },
52
+ messages: []
53
+ }
54
+ }
55
+ }
package/ts/log.ts ADDED
@@ -0,0 +1,29 @@
1
+ import { store } from './store'
2
+
3
+ export function createLog() {
4
+ return {
5
+ enabled: false,
6
+ writer: console,
7
+ debug(...args) {
8
+ if (store.devel) return
9
+ if (this.enabled) {
10
+ // istanbul ignore next
11
+ this.writer.info(...args)
12
+ }
13
+ }
14
+ }
15
+ }
16
+
17
+ export function logOptions({ log }, raw, options) {
18
+ if (!raw.configs) {
19
+ log.debug('no config detected')
20
+ }
21
+ else {
22
+ log.debug(`configs location:
23
+ ${raw.configs.map(c => ` ${c}`).join('\n')}
24
+
25
+ options:
26
+ ${JSON.stringify(options, undefined, 2)}
27
+ `)
28
+ }
29
+ }
@@ -0,0 +1,71 @@
1
+ import a from 'assertron'
2
+ import path from 'path'
3
+ import { processOptions } from './options'
4
+
5
+ describe('processOptions', () => {
6
+ test('no config returns options with empty array', () => {
7
+ a.satisfies(processOptions({}), {
8
+ onStart: [],
9
+ onSuitePass: [],
10
+ onSuiteFailure: []
11
+ })
12
+ })
13
+ test(`onStartThreshold is parsed as int`, () => {
14
+ a.satisfies(processOptions({ onStartThreshold: '4' }), {
15
+ onStartThreshold: 4
16
+ })
17
+ })
18
+ test('onStartThreshold is default to 10', () => {
19
+ a.satisfies(processOptions({}), {
20
+ onStartThreshold: 10
21
+ })
22
+ })
23
+ test('simple string is convert to entry in array', () => {
24
+ const cwd = process.cwd()
25
+ const config = path.join(cwd, '.jest-audio-reporterrc')
26
+ a.satisfies(processOptions({ onStart: 'audio/onSuitePass/昇格.mp3', config, configs: [config] }), {
27
+ onStart: [path.resolve(cwd, 'audio/onSuitePass/昇格.mp3')]
28
+ })
29
+ })
30
+ test(`support absolute path`, () => {
31
+ const cwd = process.cwd()
32
+ const dirConfig = path.join(__dirname, '.jest-audio-reporterrc')
33
+ const actual = path.resolve(cwd, 'audio/onSuitePass/昇格.mp3')
34
+ a.satisfies(processOptions({ onStart: actual, config: dirConfig, configs: [dirConfig] }), {
35
+ onStart: [actual]
36
+ })
37
+ })
38
+ test(`not exist file is trimmed`, () => {
39
+ const dirConfig = path.join(__dirname, '.jest-audio-reporterrc')
40
+ a.satisfies(processOptions({ onStart: 'not-exist.mp3', config: dirConfig, configs: [dirConfig] }), {
41
+ onStart: a => a.length === 0
42
+ })
43
+ })
44
+
45
+ test(`support multiple config`, () => {
46
+ const cwd = process.cwd()
47
+ const config = path.join(cwd, '.jest-audio-reporterrc')
48
+ const dirConfig = path.join(__dirname, '.jest-audio-reporterrc')
49
+ const actual = path.resolve(cwd, 'audio/onSuitePass/昇格.mp3')
50
+ a.satisfies(processOptions({ onStart: actual, config: dirConfig, configs: [config, dirConfig] }), {
51
+ onStart: [actual]
52
+ })
53
+
54
+ a.satisfies(processOptions({ onStart: actual, config, configs: [dirConfig, config] }), {
55
+ onStart: [actual]
56
+ })
57
+ })
58
+ test(`support array`, () => {
59
+ const cwd = process.cwd()
60
+ const config = path.join(cwd, '.jest-audio-reporterrc')
61
+ const failureFile = path.resolve(cwd, 'audio/onSuitePass/昇格.mp3')
62
+ const actual = processOptions({
63
+ onSuiteFailure: ['audio/onSuitePass/昇格.mp3'],
64
+ config,
65
+ configs: [config]
66
+ })
67
+ a.satisfies(actual, {
68
+ onSuiteFailure: [failureFile]
69
+ })
70
+ })
71
+ })
package/ts/options.ts ADDED
@@ -0,0 +1,67 @@
1
+ import fs from 'fs'
2
+ import path from 'path'
3
+
4
+ export interface Options {
5
+ /**
6
+ * Enable debug mode.
7
+ */
8
+ debug: boolean,
9
+ /**
10
+ * Master volume. 0 (silent) - 1 (normal).
11
+ */
12
+ volume: number,
13
+ /**
14
+ * Volume for onStart. 0 (silent) - 1 (normal).
15
+ * Value higher than Master volume is ignored.
16
+ */
17
+ onStartVolume: number,
18
+
19
+ /**
20
+ * Volume for onPass and onFailure. 0 (silent) - 1 (normal).
21
+ * Value higher than Master volume is ignored.
22
+ */
23
+ onCompleteVolume: number,
24
+ disable: boolean
25
+ }
26
+
27
+ export interface RuntimeOptions {
28
+ onStart: string[],
29
+ onStartThreshold: number,
30
+ onSuitePass: string[],
31
+ onSuiteFailure: string[]
32
+ }
33
+
34
+ export function processOptions(rawRCOptions) {
35
+ // reversing the config so the first one is the closest.
36
+ const dirs = rawRCOptions.configs ? rawRCOptions.configs.map(path.dirname) : []
37
+ const onStart = processRCFileEntry(rawRCOptions.onStart, dirs)
38
+ const onSuitePass = processRCFileEntry(rawRCOptions.onSuitePass, dirs)
39
+ const onSuiteFailure = processRCFileEntry(rawRCOptions.onSuiteFailure, dirs)
40
+
41
+ const onStartThreshold = rawRCOptions.onStartThreshold !== undefined ? parseInt(rawRCOptions.onStartThreshold, 10) : 10
42
+
43
+ return {
44
+ onStartThreshold,
45
+ onStart,
46
+ onSuitePass,
47
+ onSuiteFailure
48
+ }
49
+ }
50
+
51
+ function processRCFileEntry(files: string | string[] | undefined, dirs: string[]) {
52
+ if (!files) return []
53
+ const entries = typeof files === 'string' ? [files] : files
54
+ const validFiles: string[] = []
55
+ entries.forEach(e => {
56
+ if (path.isAbsolute(e)) {
57
+ validFiles.push(e)
58
+ }
59
+ else {
60
+ const file = dirs.map(dir => path.resolve(dir, e)).find(p => fs.existsSync(p))
61
+ if (file) {
62
+ validFiles.push(file)
63
+ }
64
+ }
65
+ })
66
+ return validFiles
67
+ }
package/ts/store.ts ADDED
@@ -0,0 +1,17 @@
1
+ export interface Store {
2
+ devel: boolean,
3
+ startAudio?: any,
4
+ completeAudio?: any,
5
+ doesLastRunPass: boolean,
6
+ reset(): void
7
+ }
8
+
9
+ export const store: Store = {
10
+ devel: false,
11
+ doesLastRunPass: false,
12
+ reset() {
13
+ store.completeAudio = undefined,
14
+ store.doesLastRunPass = false,
15
+ store.startAudio = undefined
16
+ }
17
+ }
@@ -1,24 +0,0 @@
1
- /// <reference types="jest" />
2
- /// <reference types="node" />
3
- import { Options, RuntimeOptions } from './options';
4
- export declare class AudioReporter {
5
- globalConfig: jest.GlobalConfig;
6
- log: {
7
- enabled: boolean;
8
- writer: Console;
9
- debug(...args: any[]): void;
10
- };
11
- player: any;
12
- disable: boolean;
13
- options: RuntimeOptions;
14
- volume: number | undefined;
15
- onStartVolume: number;
16
- onCompleteVolume: number | undefined;
17
- constructor(globalConfig: jest.GlobalConfig, jestOptions: Partial<Options>);
18
- onRunStart(results: jest.AggregatedResult, options: jest.ReporterOnStartOptions): void;
19
- onRunComplete(_contexts: any, results: jest.AggregatedResult): Promise<{}> | undefined;
20
- private playComplete;
21
- private getEffectiveOnStartVolume;
22
- private getEffectiveOnCompleteVolume;
23
- private getPlayOption;
24
- }
@@ -1,117 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const play_sound_1 = __importDefault(require("play-sound"));
7
- const log_1 = require("./log");
8
- const options_1 = require("./options");
9
- const store_1 = require("./store");
10
- const player = play_sound_1.default({});
11
- const rcOptions = options_1.processOptions(options_1.rawRCOptions);
12
- class AudioReporter {
13
- constructor(globalConfig, jestOptions) {
14
- this.globalConfig = globalConfig;
15
- this.log = log_1.createLog();
16
- this.player = player;
17
- if (jestOptions.debug) {
18
- this.log.enabled = true;
19
- }
20
- this.disable = !!jestOptions.disable;
21
- this.volume = jestOptions.volume;
22
- this.onStartVolume = jestOptions.onStartVolume || 0.5;
23
- this.onCompleteVolume = jestOptions.onCompleteVolume;
24
- log_1.logOptions({ log: this.log }, options_1.rawRCOptions, rcOptions);
25
- this.options = rcOptions;
26
- }
27
- onRunStart(results, options) {
28
- if (this.disable)
29
- return;
30
- if (store_1.store.completeAudio) {
31
- store_1.store.completeAudio.kill();
32
- store_1.store.completeAudio = undefined;
33
- }
34
- if (results.numTotalTestSuites === 0 ||
35
- options.estimatedTime > 0 &&
36
- options.estimatedTime <= this.options.onStartThreshold)
37
- return;
38
- const file = pickOne(this.options.onStart);
39
- const volume = this.getEffectiveOnStartVolume();
40
- store_1.store.startAudio = this.player.play(file, this.getPlayOption({ volume }));
41
- }
42
- onRunComplete(_contexts, results) {
43
- if (this.disable)
44
- return;
45
- if (store_1.store.startAudio) {
46
- store_1.store.startAudio.kill();
47
- store_1.store.startAudio = undefined;
48
- }
49
- if (results.numTotalTestSuites === 0)
50
- return;
51
- if (results.wasInterrupted)
52
- return;
53
- if (results.numFailedTestSuites === 0) {
54
- if (isWatch(this.globalConfig) && store_1.store.doesLastRunPass)
55
- return;
56
- store_1.store.doesLastRunPass = true;
57
- return this.playComplete(pickOne(this.options.onSuitePass));
58
- }
59
- else {
60
- store_1.store.doesLastRunPass = false;
61
- return this.playComplete(pickOne(this.options.onSuiteFailure));
62
- }
63
- }
64
- playComplete(file) {
65
- if (!file)
66
- return;
67
- const volume = this.getEffectiveOnCompleteVolume();
68
- if (isWatch(this.globalConfig)) {
69
- store_1.store.completeAudio = this.player.play(file, this.getPlayOption({ volume }));
70
- }
71
- else {
72
- return new Promise(a => {
73
- store_1.store.completeAudio = this.player.play(file, this.getPlayOption({ volume }), a);
74
- });
75
- }
76
- }
77
- getEffectiveOnStartVolume() {
78
- return Math.min(this.volume || 1, this.onStartVolume);
79
- }
80
- getEffectiveOnCompleteVolume() {
81
- return Math.min(this.volume || 1, this.onCompleteVolume || 1);
82
- }
83
- getPlayOption(option) {
84
- switch (this.player.player) {
85
- case 'afplay':
86
- return getAfPlayOption(option);
87
- case 'mplayer':
88
- return getMplayerOption(option);
89
- default:
90
- return {};
91
- }
92
- }
93
- }
94
- exports.AudioReporter = AudioReporter;
95
- function pickOne(arr) {
96
- if (arr.length === 0)
97
- return undefined;
98
- return arr[Math.floor(Math.random() * arr.length)];
99
- }
100
- function isWatch(globalConfig) {
101
- return globalConfig.watch || globalConfig.watchAll;
102
- }
103
- function getAfPlayOption({ volume }) {
104
- // https://ss64.com/osx/afplay.html
105
- // According to the link, the volume is logarithmic,
106
- // but I'm not sure what does it mean, as:
107
- // log(1) = 0
108
- // log(0.1) = -1
109
- // log(0) = -infinity
110
- // So for now, I treat [0, 1] as linear
111
- return { afplay: ['-v', 1 / (Math.pow(10, Math.log2(1 / volume)))] };
112
- }
113
- function getMplayerOption({ volume }) {
114
- // http://www.mplayerhq.hu/DOCS/man/en/mplayer.1.html search for "-volume"
115
- return { mplayer: ['-volume', volume * 100] };
116
- }
117
- //# sourceMappingURL=AudioReporter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"AudioReporter.js","sourceRoot":"","sources":["../src/AudioReporter.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts DELETED
@@ -1,2 +0,0 @@
1
- import { AudioReporter } from './AudioReporter';
2
- export = AudioReporter;
package/dist/index.js DELETED
@@ -1,12 +0,0 @@
1
- "use strict";
2
- const store_1 = require("./store");
3
- // istanbul ignore next
4
- process.on('exit', () => {
5
- if (store_1.store.startAudio)
6
- store_1.store.startAudio.kill();
7
- if (store_1.store.completeAudio)
8
- store_1.store.completeAudio.kill();
9
- });
10
- const AudioReporter_1 = require("./AudioReporter");
11
- module.exports = AudioReporter_1.AudioReporter;
12
- //# sourceMappingURL=index.js.map
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,mCAAgC;AAEhC,uBAAuB;AACvB,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;IACtB,IAAI,aAAK,CAAC,UAAU;QAAE,aAAK,CAAC,UAAU,CAAC,IAAI,EAAE,CAAA;IAC7C,IAAI,aAAK,CAAC,aAAa;QAAE,aAAK,CAAC,aAAa,CAAC,IAAI,EAAE,CAAA;AACrD,CAAC,CAAC,CAAA;AAEF,mDAA+C;AAE/C,iBAAS,6BAAa,CAAA"}
package/dist/log.d.ts DELETED
@@ -1,9 +0,0 @@
1
- /// <reference types="node" />
2
- export declare function createLog(): {
3
- enabled: boolean;
4
- writer: Console;
5
- debug(...args: any[]): void;
6
- };
7
- export declare function logOptions({ log }: {
8
- log: any;
9
- }, raw: any, options: any): void;
package/dist/log.js DELETED
@@ -1,33 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const store_1 = require("./store");
4
- function createLog() {
5
- return {
6
- enabled: false,
7
- writer: console,
8
- debug(...args) {
9
- if (store_1.store.devel)
10
- return;
11
- if (this.enabled) {
12
- // istanbul ignore next
13
- this.writer.info(...args);
14
- }
15
- }
16
- };
17
- }
18
- exports.createLog = createLog;
19
- function logOptions({ log }, raw, options) {
20
- if (!raw.configs) {
21
- log.debug('no config detected');
22
- }
23
- else {
24
- log.debug(`configs location:
25
- ${raw.configs.map(c => ` ${c}`).join('\n')}
26
-
27
- options:
28
- ${JSON.stringify(options, undefined, 2)}
29
- `);
30
- }
31
- }
32
- exports.logOptions = logOptions;
33
- //# sourceMappingURL=log.js.map
package/dist/log.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"log.js","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":";;AAAA,mCAAgC;AAEhC,SAAgB,SAAS;IACvB,OAAO;QACL,OAAO,EAAE,KAAK;QACd,MAAM,EAAE,OAAO;QACf,KAAK,CAAC,GAAG,IAAI;YACX,IAAI,aAAK,CAAC,KAAK;gBAAE,OAAM;YACvB,IAAI,IAAI,CAAC,OAAO,EAAE;gBAChB,uBAAuB;gBACvB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAA;aAC1B;QACH,CAAC;KACF,CAAA;AACH,CAAC;AAZD,8BAYC;AAED,SAAgB,UAAU,CAAC,EAAE,GAAG,EAAE,EAAE,GAAG,EAAE,OAAO;IAC9C,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE;QAChB,GAAG,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAA;KAChC;SACI;QACH,GAAG,CAAC,KAAK,CAAC;EACZ,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;;;EAGzC,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;CACtC,CAAC,CAAA;KACC;AACH,CAAC;AAZD,gCAYC"}
package/dist/options.d.ts DELETED
@@ -1,34 +0,0 @@
1
- export interface Options {
2
- /**
3
- * Enable debug mode.
4
- */
5
- debug: boolean;
6
- /**
7
- * Master volume. 0 (silent) - 1 (normal).
8
- */
9
- volume: number;
10
- /**
11
- * Volume for onStart. 0 (silent) - 1 (normal).
12
- * Value higher than Master volume is ignored.
13
- */
14
- onStartVolume: number;
15
- /**
16
- * Volume for onPass and onFailure. 0 (silent) - 1 (normal).
17
- * Value higher than Master volume is ignored.
18
- */
19
- onCompleteVolume: number;
20
- disable: boolean;
21
- }
22
- export interface RuntimeOptions {
23
- onStart: string[];
24
- onStartThreshold: number;
25
- onSuitePass: string[];
26
- onSuiteFailure: string[];
27
- }
28
- export declare const rawRCOptions: any;
29
- export declare function processOptions(rawRCOptions: any): {
30
- onStartThreshold: number;
31
- onStart: string[];
32
- onSuitePass: string[];
33
- onSuiteFailure: string[];
34
- };
package/dist/options.js DELETED
@@ -1,43 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const fs_1 = __importDefault(require("fs"));
7
- const path_1 = __importDefault(require("path"));
8
- const rc_1 = __importDefault(require("rc"));
9
- exports.rawRCOptions = rc_1.default('jest-audio-reporter');
10
- function processOptions(rawRCOptions) {
11
- // reversing the config so the first one is the closest.
12
- const dirs = rawRCOptions.configs ? rawRCOptions.configs.map(path_1.default.dirname) : [];
13
- const onStart = processRCFileEntry(rawRCOptions.onStart, dirs);
14
- const onSuitePass = processRCFileEntry(rawRCOptions.onSuitePass, dirs);
15
- const onSuiteFailure = processRCFileEntry(rawRCOptions.onSuiteFailure, dirs);
16
- const onStartThreshold = rawRCOptions.onStartThreshold !== undefined ? parseInt(rawRCOptions.onStartThreshold, 10) : 10;
17
- return {
18
- onStartThreshold,
19
- onStart,
20
- onSuitePass,
21
- onSuiteFailure
22
- };
23
- }
24
- exports.processOptions = processOptions;
25
- function processRCFileEntry(files, dirs) {
26
- if (!files)
27
- return [];
28
- const entries = typeof files === 'string' ? [files] : files;
29
- const validFiles = [];
30
- entries.forEach(e => {
31
- if (path_1.default.isAbsolute(e)) {
32
- validFiles.push(e);
33
- }
34
- else {
35
- const file = dirs.map(dir => path_1.default.resolve(dir, e)).find(p => fs_1.default.existsSync(p));
36
- if (file) {
37
- validFiles.push(file);
38
- }
39
- }
40
- });
41
- return validFiles;
42
- }
43
- //# sourceMappingURL=options.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":";;;;;AAAA,4CAAoB;AACpB,gDAAwB;AACxB,4CAAoB;AAgCP,QAAA,YAAY,GAAG,YAAE,CAAC,qBAAqB,CAAC,CAAA;AAErD,SAAgB,cAAc,CAAC,YAAY;IACzC,wDAAwD;IACxD,MAAM,IAAI,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,cAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAC/E,MAAM,OAAO,GAAG,kBAAkB,CAAC,YAAY,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;IAC9D,MAAM,WAAW,GAAG,kBAAkB,CAAC,YAAY,CAAC,WAAW,EAAE,IAAI,CAAC,CAAA;IACtE,MAAM,cAAc,GAAG,kBAAkB,CAAC,YAAY,CAAC,cAAc,EAAE,IAAI,CAAC,CAAA;IAE5E,MAAM,gBAAgB,GAAG,YAAY,CAAC,gBAAgB,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAEvH,OAAO;QACL,gBAAgB;QAChB,OAAO;QACP,WAAW;QACX,cAAc;KACf,CAAA;AACH,CAAC;AAfD,wCAeC;AAED,SAAS,kBAAkB,CAAC,KAAoC,EAAE,IAAc;IAC9E,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAA;IACrB,MAAM,OAAO,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;IAC3D,MAAM,UAAU,GAAa,EAAE,CAAA;IAC/B,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;QAClB,IAAI,cAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE;YACtB,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;SACnB;aACI;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,cAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,YAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAA;YAC9E,IAAI,IAAI,EAAE;gBACR,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;aACtB;SACF;IACH,CAAC,CAAC,CAAA;IACF,OAAO,UAAU,CAAA;AACnB,CAAC"}
package/dist/store.d.ts DELETED
@@ -1,8 +0,0 @@
1
- export interface Store {
2
- devel: boolean;
3
- startAudio?: any;
4
- completeAudio?: any;
5
- doesLastRunPass: boolean;
6
- reset(): void;
7
- }
8
- export declare const store: Store;
package/dist/store.js DELETED
@@ -1,12 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.store = {
4
- devel: false,
5
- doesLastRunPass: false,
6
- reset() {
7
- exports.store.completeAudio = undefined,
8
- exports.store.doesLastRunPass = false,
9
- exports.store.startAudio = undefined;
10
- }
11
- };
12
- //# sourceMappingURL=store.js.map
package/dist/store.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":";;AAQa,QAAA,KAAK,GAAU;IAC1B,KAAK,EAAE,KAAK;IACZ,eAAe,EAAE,KAAK;IACtB,KAAK;QACH,aAAK,CAAC,aAAa,GAAG,SAAS;YAC/B,aAAK,CAAC,eAAe,GAAG,KAAK;YAC7B,aAAK,CAAC,UAAU,GAAG,SAAS,CAAA;IAC9B,CAAC;CACF,CAAA"}