bfj 9.0.2 → 9.1.0
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/HISTORY.md +7 -0
- package/README.md +48 -0
- package/package.json +1 -1
- package/src/events.js +1 -0
- package/src/match.js +38 -5
- package/src/walk.js +33 -5
- package/test/integration.js +29 -0
- package/test/unit/match.js +72 -2
- package/test/unit/walk.js +133 -2
package/HISTORY.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# History
|
|
2
2
|
|
|
3
|
+
## 9.1.0
|
|
4
|
+
|
|
5
|
+
### New features
|
|
6
|
+
|
|
7
|
+
* match: implement `recursive` option (acdd744c2eeedad3b5b3df6bc9cf4c48272b6677)
|
|
8
|
+
* walk: implement `stringChunkSize` option and `stringChunk` event (ea8bafcdcbc9a45d177c3407d6e7e88e1e22072a)
|
|
9
|
+
|
|
3
10
|
## 9.0.2
|
|
4
11
|
|
|
5
12
|
### Bug fixes
|
package/README.md
CHANGED
|
@@ -24,6 +24,8 @@ Big-Friendly JSON. Asynchronous streaming functions for large JSON data sets.
|
|
|
24
24
|
* [Options for parsing functions](#options-for-parsing-functions)
|
|
25
25
|
* [Options for serialisation functions](#options-for-serialisation-functions)
|
|
26
26
|
* [Is it possible to pause parsing or serialisation from calling code?](#is-it-possible-to-pause-parsing-or-serialisation-from-calling-code)
|
|
27
|
+
* [Can it break long strings into chunks?](#can-it-break-long-strings-into-chunks)
|
|
28
|
+
* [Can it recursively parse JSON nested inside a JSON string?](#can-it-recursively-parse-json-nested-inside-a-json-string)
|
|
27
29
|
* [Can it handle newline-delimited JSON (NDJSON)?](#can-it-handle-newline-delimited-json-ndjson)
|
|
28
30
|
* [Is there a change log?](#is-there-a-change-log)
|
|
29
31
|
* [How do I set up the dev environment?](#how-do-i-set-up-the-dev-environment)
|
|
@@ -475,6 +477,16 @@ of an object,
|
|
|
475
477
|
the value
|
|
476
478
|
as its argument.
|
|
477
479
|
|
|
480
|
+
* `bfj.events.stringChunk`
|
|
481
|
+
indicates that
|
|
482
|
+
a string chunk
|
|
483
|
+
has been encountered
|
|
484
|
+
if the `stringChunkSize` [option](#options-for-parsing-functions) was set.
|
|
485
|
+
The listener
|
|
486
|
+
will be passed
|
|
487
|
+
the chunk
|
|
488
|
+
as its argument.
|
|
489
|
+
|
|
478
490
|
* `bfj.events.number`
|
|
479
491
|
indicates that
|
|
480
492
|
a number
|
|
@@ -687,6 +699,19 @@ of an object,
|
|
|
687
699
|
discrete chunks of JSON.
|
|
688
700
|
See [NDJSON](#can-it-handle-newline-delimited-json-ndjson) for more information.
|
|
689
701
|
|
|
702
|
+
* `options.stringChunkSize`:
|
|
703
|
+
For `bfj.walk` only,
|
|
704
|
+
set this to the character count
|
|
705
|
+
at which you wish to chunk strings.
|
|
706
|
+
Each chunk will be emitted as a `bfj.events.stringChunk` event,
|
|
707
|
+
followed by the regular `bfj.events.string` event
|
|
708
|
+
after all chunks are emitted.
|
|
709
|
+
|
|
710
|
+
* `options.recursive`:
|
|
711
|
+
For `bfj.match` only,
|
|
712
|
+
set this to `true`
|
|
713
|
+
if you wish to match against recursively JSON-parsed strings.
|
|
714
|
+
|
|
690
715
|
* `options.numbers`:
|
|
691
716
|
For `bfj.match` only,
|
|
692
717
|
set this to `true`
|
|
@@ -821,6 +846,29 @@ const resume = emitter.pause();
|
|
|
821
846
|
resume();
|
|
822
847
|
```
|
|
823
848
|
|
|
849
|
+
## Can it break long strings into chunks?
|
|
850
|
+
|
|
851
|
+
Yes.
|
|
852
|
+
If you pass the `stringChunkSize` [option](#options-for-parsing-functions)
|
|
853
|
+
to `bfj.walk`,
|
|
854
|
+
it will emit a `bfj.events.stringChunk` event
|
|
855
|
+
for each chunk of the string.
|
|
856
|
+
The regular `bfj.events.string` event
|
|
857
|
+
will still be emitted
|
|
858
|
+
after all the chunks.
|
|
859
|
+
|
|
860
|
+
## Can it recursively parse JSON nested inside a JSON string?
|
|
861
|
+
|
|
862
|
+
Yes.
|
|
863
|
+
If you pass the `recursive` [option](#options-for-parsing-functions)
|
|
864
|
+
to `bfj.match`,
|
|
865
|
+
it will recursively parse any string values
|
|
866
|
+
that satisfy the `selector` argument.
|
|
867
|
+
Note the same selector is applied
|
|
868
|
+
to every level of recursion,
|
|
869
|
+
so this works best in combination
|
|
870
|
+
with selectors that are predicate functions.
|
|
871
|
+
|
|
824
872
|
## Can it handle [newline-delimited JSON (NDJSON)](http://ndjson.org/)?
|
|
825
873
|
|
|
826
874
|
Yes.
|
package/package.json
CHANGED
package/src/events.js
CHANGED
package/src/match.js
CHANGED
|
@@ -5,6 +5,7 @@ const DataStream = require('./datastream')
|
|
|
5
5
|
const events = require('./events')
|
|
6
6
|
const Hoopy = require('hoopy')
|
|
7
7
|
const jsonpath = require('jsonpath')
|
|
8
|
+
const { PassThrough } = require('node:stream')
|
|
8
9
|
const walk = require('./walk')
|
|
9
10
|
|
|
10
11
|
const DEFAULT_BUFFER_LENGTH = 256
|
|
@@ -39,6 +40,10 @@ module.exports = match
|
|
|
39
40
|
* @option ndjson: Set this to true to parse newline-delimited JSON,
|
|
40
41
|
* default is `false`.
|
|
41
42
|
*
|
|
43
|
+
* @option recursive: Set this to true to recursively parse
|
|
44
|
+
* matched string values,
|
|
45
|
+
* default is `false`.
|
|
46
|
+
*
|
|
42
47
|
* @option yieldRate: The number of data items to process per timeslice,
|
|
43
48
|
* default is 1024.
|
|
44
49
|
*
|
|
@@ -51,18 +56,17 @@ function match (stream, selector, options = {}) {
|
|
|
51
56
|
const keys = []
|
|
52
57
|
const scopes = []
|
|
53
58
|
const properties = []
|
|
54
|
-
const emitter = walk(stream, options)
|
|
55
59
|
const matches = new Hoopy(options.bufferLength || DEFAULT_BUFFER_LENGTH)
|
|
56
60
|
let streamOptions
|
|
57
61
|
const { highWaterMark } = options
|
|
58
62
|
if (highWaterMark) {
|
|
59
63
|
streamOptions = { highWaterMark }
|
|
60
64
|
}
|
|
61
|
-
const results = new DataStream(read, streamOptions)
|
|
65
|
+
const results = options.results || new DataStream(read, streamOptions)
|
|
62
66
|
|
|
63
|
-
let selectorFunction, selectorPath, selectorString, resume
|
|
67
|
+
let chunkStream, selectorFunction, selectorPath, selectorString, resume
|
|
64
68
|
let coerceNumbers = false
|
|
65
|
-
let awaitPush =
|
|
69
|
+
let awaitPush = ! options.results
|
|
66
70
|
let isEnded = false
|
|
67
71
|
let length = 0
|
|
68
72
|
let index = 0
|
|
@@ -70,6 +74,9 @@ function match (stream, selector, options = {}) {
|
|
|
70
74
|
const minDepth = options.minDepth || 0
|
|
71
75
|
check.assert.greaterOrEqual(minDepth, 0)
|
|
72
76
|
|
|
77
|
+
const recursive = options.recursive || false
|
|
78
|
+
check.assert.boolean(recursive)
|
|
79
|
+
|
|
73
80
|
if (check.function(selector)) {
|
|
74
81
|
selectorFunction = selector
|
|
75
82
|
selector = null
|
|
@@ -98,6 +105,11 @@ function match (stream, selector, options = {}) {
|
|
|
98
105
|
coerceNumbers = !! options.numbers
|
|
99
106
|
}
|
|
100
107
|
|
|
108
|
+
const emitter = walk(stream, {
|
|
109
|
+
...options,
|
|
110
|
+
streamChunkSize: recursive ? matches.length : null,
|
|
111
|
+
})
|
|
112
|
+
|
|
101
113
|
emitter.on(events.array, array)
|
|
102
114
|
emitter.on(events.object, object)
|
|
103
115
|
emitter.on(events.property, property)
|
|
@@ -110,6 +122,10 @@ function match (stream, selector, options = {}) {
|
|
|
110
122
|
emitter.on(events.error, error)
|
|
111
123
|
emitter.on(events.dataError, dataError)
|
|
112
124
|
|
|
125
|
+
if (recursive) {
|
|
126
|
+
emitter.on(events.stringChunk, stringChunk)
|
|
127
|
+
}
|
|
128
|
+
|
|
113
129
|
return results
|
|
114
130
|
|
|
115
131
|
function read () {
|
|
@@ -190,12 +206,16 @@ function match (stream, selector, options = {}) {
|
|
|
190
206
|
}
|
|
191
207
|
|
|
192
208
|
function value (v) {
|
|
193
|
-
|
|
209
|
+
if (chunkStream) {
|
|
210
|
+
chunkStream = null
|
|
211
|
+
}
|
|
194
212
|
|
|
195
213
|
if (scopes.length < minDepth) {
|
|
196
214
|
return
|
|
197
215
|
}
|
|
198
216
|
|
|
217
|
+
let key
|
|
218
|
+
|
|
199
219
|
if (scopes.length > 0) {
|
|
200
220
|
const scope = scopes[scopes.length - 1]
|
|
201
221
|
|
|
@@ -269,6 +289,19 @@ function match (stream, selector, options = {}) {
|
|
|
269
289
|
after()
|
|
270
290
|
}
|
|
271
291
|
|
|
292
|
+
function stringChunk (chunk) {
|
|
293
|
+
if (!chunkStream) {
|
|
294
|
+
chunkStream = new PassThrough(streamOptions)
|
|
295
|
+
match(
|
|
296
|
+
chunkStream,
|
|
297
|
+
selectorFunction || selectorPath || selectorString || selector,
|
|
298
|
+
{ ...options, results },
|
|
299
|
+
)
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
chunkStream.write(chunk)
|
|
303
|
+
}
|
|
304
|
+
|
|
272
305
|
function end () {
|
|
273
306
|
isEnded = true
|
|
274
307
|
endResults()
|
package/src/walk.js
CHANGED
|
@@ -34,17 +34,23 @@ module.exports = initialise
|
|
|
34
34
|
* emitting events as it encounters tokens. The event emitter is decorated
|
|
35
35
|
* with a `pause` method that can be called to pause processing.
|
|
36
36
|
*
|
|
37
|
-
* @param stream:
|
|
37
|
+
* @param stream: Readable instance representing the incoming JSON.
|
|
38
38
|
*
|
|
39
|
-
* @option
|
|
39
|
+
* @option bufferLength: The length of the walk buffer, default is 256.
|
|
40
40
|
*
|
|
41
|
-
* @option
|
|
42
|
-
* default is 1024.
|
|
41
|
+
* @option ndjson: Set this to true to parse newline-delimited JSON.
|
|
43
42
|
*
|
|
44
|
-
* @option
|
|
43
|
+
* @option stringChunkSize: The size at which to chunk long strings, emitting
|
|
44
|
+
* `string-chunk` events for each chunk followed by a
|
|
45
|
+
* regular `string` event when the complete string has
|
|
46
|
+
* been walked. Default is disabled.
|
|
47
|
+
*
|
|
48
|
+
* @option yieldRate: The number of data items to process per timeslice,
|
|
49
|
+
* default is 1024.
|
|
45
50
|
**/
|
|
46
51
|
function initialise (stream, options = {}) {
|
|
47
52
|
check.assert.instanceStrict(stream, require('stream').Readable, 'Invalid stream argument')
|
|
53
|
+
check.assert.maybe.greater(options.stringChunkSize, 0, 'Invalid stringChunkSize option')
|
|
48
54
|
|
|
49
55
|
const currentPosition = {
|
|
50
56
|
line: 1,
|
|
@@ -62,6 +68,7 @@ function initialise (stream, options = {}) {
|
|
|
62
68
|
const shouldHandleNdjson = !! options.ndjson
|
|
63
69
|
const yieldRate = options.yieldRate || 1024
|
|
64
70
|
const bufferLength = options.bufferLength || DEFAULT_BUFFER_LENGTH
|
|
71
|
+
const stringChunkSize = options.stringChunkSize || Number.POSITIVE_INFINITY
|
|
65
72
|
|
|
66
73
|
let index = 0
|
|
67
74
|
let isStreamEnded = false
|
|
@@ -71,6 +78,8 @@ function initialise (stream, options = {}) {
|
|
|
71
78
|
let isWalkingString = false
|
|
72
79
|
let hasEndedLine = true
|
|
73
80
|
let count = 0
|
|
81
|
+
let stringChunkCount = 0
|
|
82
|
+
let stringChunkStart = 0
|
|
74
83
|
let resumeFn
|
|
75
84
|
let pause
|
|
76
85
|
let cachedCharacter
|
|
@@ -433,6 +442,9 @@ function initialise (stream, options = {}) {
|
|
|
433
442
|
|
|
434
443
|
if (isEscaping) {
|
|
435
444
|
str.push(await escape(char))
|
|
445
|
+
if (++stringChunkCount >= stringChunkSize) {
|
|
446
|
+
await walkStringChunk(event, str)
|
|
447
|
+
}
|
|
436
448
|
return walkStringContinue(event, str, false)
|
|
437
449
|
}
|
|
438
450
|
|
|
@@ -442,13 +454,29 @@ function initialise (stream, options = {}) {
|
|
|
442
454
|
|
|
443
455
|
if (char !== '"') {
|
|
444
456
|
str.push(char)
|
|
457
|
+
if (++stringChunkCount >= stringChunkSize) {
|
|
458
|
+
await walkStringChunk(event, str)
|
|
459
|
+
}
|
|
445
460
|
return walkStringContinue(event, str, isEscaping)
|
|
446
461
|
}
|
|
447
462
|
|
|
448
463
|
isWalkingString = false
|
|
464
|
+
|
|
465
|
+
await walkStringChunk(event, str)
|
|
466
|
+
stringChunkStart = 0
|
|
467
|
+
|
|
449
468
|
return emit(event, str.join(''))
|
|
450
469
|
}
|
|
451
470
|
|
|
471
|
+
function walkStringChunk (event, str) {
|
|
472
|
+
if (event === events.string) {
|
|
473
|
+
const chunk = str.slice(stringChunkStart).join('')
|
|
474
|
+
stringChunkStart = str.length
|
|
475
|
+
stringChunkCount = 0
|
|
476
|
+
return emit(events.stringChunk, chunk)
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
452
480
|
async function escape (char) {
|
|
453
481
|
if (escapes[char]) {
|
|
454
482
|
return escapes[char]
|
package/test/integration.js
CHANGED
|
@@ -303,6 +303,35 @@ suite('integration:', () => {
|
|
|
303
303
|
})
|
|
304
304
|
})
|
|
305
305
|
|
|
306
|
+
suite('match recursive:', () => {
|
|
307
|
+
let file, results, errors
|
|
308
|
+
|
|
309
|
+
setup(done => {
|
|
310
|
+
file = path.join(__dirname, 'data.json')
|
|
311
|
+
fs.writeFileSync(file, JSON.stringify({
|
|
312
|
+
foo: 'bar',
|
|
313
|
+
wibble: {
|
|
314
|
+
foo: 'baz',
|
|
315
|
+
wibble: JSON.stringify({ foo: 'qux' }),
|
|
316
|
+
},
|
|
317
|
+
}))
|
|
318
|
+
results = []
|
|
319
|
+
errors = []
|
|
320
|
+
const datastream = bfj.match(fs.createReadStream(file), (k) => k === 'foo', { recursive: true })
|
|
321
|
+
datastream.on('data', item => results.push(item))
|
|
322
|
+
datastream.on('error', error => errors.push(error))
|
|
323
|
+
datastream.on('end', done)
|
|
324
|
+
})
|
|
325
|
+
|
|
326
|
+
test('the correct properties were matched', () => {
|
|
327
|
+
assert.deepEqual([ 'bar', 'baz', 'qux' ], results)
|
|
328
|
+
})
|
|
329
|
+
|
|
330
|
+
test('no errors occurred', () => {
|
|
331
|
+
assert.deepEqual(errors, [])
|
|
332
|
+
})
|
|
333
|
+
})
|
|
334
|
+
|
|
306
335
|
suite('parse request:', () => {
|
|
307
336
|
let error, result
|
|
308
337
|
|
package/test/unit/match.js
CHANGED
|
@@ -122,8 +122,11 @@ suite('match:', () => {
|
|
|
122
122
|
assert.lengthOf(log.args.walk[0], 2)
|
|
123
123
|
assert.strictEqual(log.args.walk[0][0], stream)
|
|
124
124
|
assert.lengthOf(Object.keys(log.args.walk[0][0]), 0)
|
|
125
|
-
assert.
|
|
126
|
-
|
|
125
|
+
assert.deepEqual(log.args.walk[0][1], {
|
|
126
|
+
...options,
|
|
127
|
+
streamChunkSize: null,
|
|
128
|
+
})
|
|
129
|
+
assert.lengthOf(Object.keys(log.args.walk[0][1]), 3)
|
|
127
130
|
})
|
|
128
131
|
|
|
129
132
|
test('EventEmitter.on was called eleven times', () => {
|
|
@@ -1253,5 +1256,72 @@ suite('match:', () => {
|
|
|
1253
1256
|
})
|
|
1254
1257
|
})
|
|
1255
1258
|
})
|
|
1259
|
+
|
|
1260
|
+
suite('match recursive:', () => {
|
|
1261
|
+
let stream, predicate, options, result
|
|
1262
|
+
|
|
1263
|
+
setup(() => {
|
|
1264
|
+
stream = {}
|
|
1265
|
+
predicate = spooks.fn({ name: 'predicate', log, results: [ true ] })
|
|
1266
|
+
options = { recursive: true }
|
|
1267
|
+
result = match(stream, predicate, options)
|
|
1268
|
+
})
|
|
1269
|
+
|
|
1270
|
+
test('DataStream was called once', () => {
|
|
1271
|
+
assert.strictEqual(log.counts.DataStream, 1)
|
|
1272
|
+
})
|
|
1273
|
+
|
|
1274
|
+
test('walk was called once', () => {
|
|
1275
|
+
assert.strictEqual(log.counts.walk, 1)
|
|
1276
|
+
})
|
|
1277
|
+
|
|
1278
|
+
test('EventEmitter.on was called twelve times', () => {
|
|
1279
|
+
assert.strictEqual(log.counts.on, 12)
|
|
1280
|
+
})
|
|
1281
|
+
|
|
1282
|
+
test('EventEmitter.on was called correctly twelfth time', () => {
|
|
1283
|
+
assert.lengthOf(log.args.on[11], 2)
|
|
1284
|
+
assert.strictEqual(log.args.on[11][0], 'str-chunk')
|
|
1285
|
+
assert.isFunction(log.args.on[11][1])
|
|
1286
|
+
assert.strictEqual(log.these.on[11], results.walk[0])
|
|
1287
|
+
})
|
|
1288
|
+
|
|
1289
|
+
suite('array with string chunks:', () => {
|
|
1290
|
+
setup(() => {
|
|
1291
|
+
log.args.on[0][1]()
|
|
1292
|
+
log.args.on[11][1]('{"foo":"')
|
|
1293
|
+
log.args.on[11][1]('bar",')
|
|
1294
|
+
log.args.on[11][1]('"baz"')
|
|
1295
|
+
log.args.on[11][1](':"qux"')
|
|
1296
|
+
log.args.on[5][1]('{"foo":"bar","baz":"qux"}')
|
|
1297
|
+
log.args.on[3][1]()
|
|
1298
|
+
log.args.DataStream[0][0]()
|
|
1299
|
+
})
|
|
1300
|
+
|
|
1301
|
+
test('predicate was called twice', () => {
|
|
1302
|
+
assert.strictEqual(log.counts.predicate, 2)
|
|
1303
|
+
})
|
|
1304
|
+
|
|
1305
|
+
test('predicate was called correctly first time', () => {
|
|
1306
|
+
assert.strictEqual(log.args.predicate[0][0], 0)
|
|
1307
|
+
assert.strictEqual(log.args.predicate[0][1], '{"foo":"bar","baz":"qux"}')
|
|
1308
|
+
assert.strictEqual(log.args.predicate[0][2], 1)
|
|
1309
|
+
})
|
|
1310
|
+
|
|
1311
|
+
test('predicate was called correctly second time', () => {
|
|
1312
|
+
assert.isUndefined(log.args.predicate[1][0])
|
|
1313
|
+
assert.deepEqual(log.args.predicate[1][1], ['{"foo":"bar","baz":"qux"}'])
|
|
1314
|
+
assert.strictEqual(log.args.predicate[1][2], 0)
|
|
1315
|
+
})
|
|
1316
|
+
|
|
1317
|
+
test('results.push was not called', () => {
|
|
1318
|
+
assert.strictEqual(log.counts.push, 0)
|
|
1319
|
+
})
|
|
1320
|
+
|
|
1321
|
+
test('results.emit was not called', () => {
|
|
1322
|
+
assert.strictEqual(log.counts.emit, 0)
|
|
1323
|
+
})
|
|
1324
|
+
})
|
|
1325
|
+
})
|
|
1256
1326
|
})
|
|
1257
1327
|
})
|
package/test/unit/walk.js
CHANGED
|
@@ -103,6 +103,10 @@ suite('walk:', () => {
|
|
|
103
103
|
assert.strictEqual(log.counts.string, 0)
|
|
104
104
|
})
|
|
105
105
|
|
|
106
|
+
test('stringChunk event did not occur', () => {
|
|
107
|
+
assert.strictEqual(log.counts.stringChunk, 0)
|
|
108
|
+
})
|
|
109
|
+
|
|
106
110
|
test('number event did not occur', () => {
|
|
107
111
|
assert.strictEqual(log.counts.number, 0)
|
|
108
112
|
})
|
|
@@ -190,6 +194,10 @@ suite('walk:', () => {
|
|
|
190
194
|
assert.strictEqual(log.counts.string, 0)
|
|
191
195
|
})
|
|
192
196
|
|
|
197
|
+
test('stringChunk event did not occur', () => {
|
|
198
|
+
assert.strictEqual(log.counts.stringChunk, 0)
|
|
199
|
+
})
|
|
200
|
+
|
|
193
201
|
test('number event did not occur', () => {
|
|
194
202
|
assert.strictEqual(log.counts.number, 0)
|
|
195
203
|
})
|
|
@@ -273,6 +281,10 @@ suite('walk:', () => {
|
|
|
273
281
|
assert.strictEqual(log.counts.string, 0)
|
|
274
282
|
})
|
|
275
283
|
|
|
284
|
+
test('stringChunk event did not occur', () => {
|
|
285
|
+
assert.strictEqual(log.counts.stringChunk, 0)
|
|
286
|
+
})
|
|
287
|
+
|
|
276
288
|
test('number event did not occur', () => {
|
|
277
289
|
assert.strictEqual(log.counts.number, 0)
|
|
278
290
|
})
|
|
@@ -349,6 +361,109 @@ suite('walk:', () => {
|
|
|
349
361
|
assert.strictEqual(log.counts.property, 0)
|
|
350
362
|
})
|
|
351
363
|
|
|
364
|
+
test('stringChunk event occured once', () => {
|
|
365
|
+
assert.strictEqual(log.counts.stringChunk, 1)
|
|
366
|
+
})
|
|
367
|
+
|
|
368
|
+
test('number event did not occur', () => {
|
|
369
|
+
assert.strictEqual(log.counts.number, 0)
|
|
370
|
+
})
|
|
371
|
+
|
|
372
|
+
test('literal event did not occur', () => {
|
|
373
|
+
assert.strictEqual(log.counts.literal, 0)
|
|
374
|
+
})
|
|
375
|
+
|
|
376
|
+
test('endArray event did not occur', () => {
|
|
377
|
+
assert.strictEqual(log.counts.endArray, 0)
|
|
378
|
+
})
|
|
379
|
+
|
|
380
|
+
test('endObject event did not occur', () => {
|
|
381
|
+
assert.strictEqual(log.counts.endObject, 0)
|
|
382
|
+
})
|
|
383
|
+
|
|
384
|
+
test('error event did not occur', () => {
|
|
385
|
+
assert.strictEqual(log.counts.error, 0)
|
|
386
|
+
})
|
|
387
|
+
|
|
388
|
+
test('dataError event did not occur', () => {
|
|
389
|
+
assert.strictEqual(log.counts.dataError, 0)
|
|
390
|
+
})
|
|
391
|
+
|
|
392
|
+
test('endLine event did not occur', () => {
|
|
393
|
+
assert.strictEqual(log.counts.endLine, 0)
|
|
394
|
+
})
|
|
395
|
+
|
|
396
|
+
test('endPrefix event did not occur', () => {
|
|
397
|
+
assert.strictEqual(log.counts.endPrefix, 0)
|
|
398
|
+
})
|
|
399
|
+
})
|
|
400
|
+
|
|
401
|
+
suite('string (with chunk size):', () => {
|
|
402
|
+
let stream, emitter
|
|
403
|
+
|
|
404
|
+
setup(done => {
|
|
405
|
+
stream = new Readable()
|
|
406
|
+
stream._read = () => {}
|
|
407
|
+
|
|
408
|
+
emitter = walk(stream, { stringChunkSize: 8 })
|
|
409
|
+
|
|
410
|
+
stream.push('"\\"the quick brown fox\r\n\\tjumps\\u00a0over the lazy\\u1680dog\\""')
|
|
411
|
+
stream.push(null)
|
|
412
|
+
|
|
413
|
+
Object.entries(events).forEach(([ key, value ]) => {
|
|
414
|
+
emitter.on(value, spooks.fn({
|
|
415
|
+
name: key,
|
|
416
|
+
log: log
|
|
417
|
+
}))
|
|
418
|
+
})
|
|
419
|
+
|
|
420
|
+
emitter.on(events.end, done)
|
|
421
|
+
})
|
|
422
|
+
|
|
423
|
+
test('stringChunk event occurred seven times', () => {
|
|
424
|
+
assert.strictEqual(log.counts.stringChunk, 6)
|
|
425
|
+
})
|
|
426
|
+
|
|
427
|
+
test('stringChunk event was dispatched correctly', () => {
|
|
428
|
+
assert.lengthOf(log.args.stringChunk[0], 1)
|
|
429
|
+
assert.strictEqual(log.args.stringChunk[0][0], '"the qui')
|
|
430
|
+
assert.lengthOf(log.args.stringChunk[1], 1)
|
|
431
|
+
assert.strictEqual(log.args.stringChunk[1][0], 'ck brown')
|
|
432
|
+
assert.lengthOf(log.args.stringChunk[2], 1)
|
|
433
|
+
assert.strictEqual(log.args.stringChunk[2][0], ' fox\r\n\tj')
|
|
434
|
+
assert.lengthOf(log.args.stringChunk[3], 1)
|
|
435
|
+
assert.strictEqual(log.args.stringChunk[3][0], 'umps\u00a0ove')
|
|
436
|
+
assert.lengthOf(log.args.stringChunk[4], 1)
|
|
437
|
+
assert.strictEqual(log.args.stringChunk[4][0], 'r the la')
|
|
438
|
+
assert.lengthOf(log.args.stringChunk[5], 1)
|
|
439
|
+
assert.strictEqual(log.args.stringChunk[5][0], 'zy\u1680dog"')
|
|
440
|
+
})
|
|
441
|
+
|
|
442
|
+
test('string event occurred once', () => {
|
|
443
|
+
assert.strictEqual(log.counts.string, 1)
|
|
444
|
+
})
|
|
445
|
+
|
|
446
|
+
test('string event was dispatched correctly', () => {
|
|
447
|
+
assert.lengthOf(log.args.string[0], 1)
|
|
448
|
+
assert.strictEqual(log.args.string[0][0], '"the quick brown fox\r\n\tjumps\u00a0over the lazy\u1680dog"')
|
|
449
|
+
})
|
|
450
|
+
|
|
451
|
+
test('end event occurred once', () => {
|
|
452
|
+
assert.strictEqual(log.counts.end, 1)
|
|
453
|
+
})
|
|
454
|
+
|
|
455
|
+
test('array event did not occur', () => {
|
|
456
|
+
assert.strictEqual(log.counts.array, 0)
|
|
457
|
+
})
|
|
458
|
+
|
|
459
|
+
test('object event did not occur', () => {
|
|
460
|
+
assert.strictEqual(log.counts.object, 0)
|
|
461
|
+
})
|
|
462
|
+
|
|
463
|
+
test('property event did not occur', () => {
|
|
464
|
+
assert.strictEqual(log.counts.property, 0)
|
|
465
|
+
})
|
|
466
|
+
|
|
352
467
|
test('number event did not occur', () => {
|
|
353
468
|
assert.strictEqual(log.counts.number, 0)
|
|
354
469
|
})
|
|
@@ -433,6 +548,10 @@ suite('walk:', () => {
|
|
|
433
548
|
assert.strictEqual(log.counts.string, 0)
|
|
434
549
|
})
|
|
435
550
|
|
|
551
|
+
test('stringChunk event did not occur', () => {
|
|
552
|
+
assert.strictEqual(log.counts.stringChunk, 0)
|
|
553
|
+
})
|
|
554
|
+
|
|
436
555
|
test('literal event did not occur', () => {
|
|
437
556
|
assert.strictEqual(log.counts.literal, 0)
|
|
438
557
|
})
|
|
@@ -513,6 +632,10 @@ suite('walk:', () => {
|
|
|
513
632
|
assert.strictEqual(log.counts.string, 0)
|
|
514
633
|
})
|
|
515
634
|
|
|
635
|
+
test('stringChunk event did not occur', () => {
|
|
636
|
+
assert.strictEqual(log.counts.stringChunk, 0)
|
|
637
|
+
})
|
|
638
|
+
|
|
516
639
|
test('number event did not occur', () => {
|
|
517
640
|
assert.strictEqual(log.counts.number, 0)
|
|
518
641
|
})
|
|
@@ -592,6 +715,10 @@ suite('walk:', () => {
|
|
|
592
715
|
assert.strictEqual(log.counts.string, 0)
|
|
593
716
|
})
|
|
594
717
|
|
|
718
|
+
test('stringChunk event did not occur', () => {
|
|
719
|
+
assert.strictEqual(log.counts.stringChunk, 0)
|
|
720
|
+
})
|
|
721
|
+
|
|
595
722
|
test('number event did not occur', () => {
|
|
596
723
|
assert.strictEqual(log.counts.number, 0)
|
|
597
724
|
})
|
|
@@ -671,6 +798,10 @@ suite('walk:', () => {
|
|
|
671
798
|
assert.strictEqual(log.counts.string, 0)
|
|
672
799
|
})
|
|
673
800
|
|
|
801
|
+
test('stringChunk event did not occur', () => {
|
|
802
|
+
assert.strictEqual(log.counts.stringChunk, 0)
|
|
803
|
+
})
|
|
804
|
+
|
|
674
805
|
test('number event did not occur', () => {
|
|
675
806
|
assert.strictEqual(log.counts.number, 0)
|
|
676
807
|
})
|
|
@@ -2892,8 +3023,8 @@ suite('walk:', () => {
|
|
|
2892
3023
|
assert.strictEqual(log.counts.endObject, 1)
|
|
2893
3024
|
})
|
|
2894
3025
|
|
|
2895
|
-
test('error event occurred
|
|
2896
|
-
assert.strictEqual(log.counts.error,
|
|
3026
|
+
test('error event occurred thirteen times', () => {
|
|
3027
|
+
assert.strictEqual(log.counts.error, 13)
|
|
2897
3028
|
})
|
|
2898
3029
|
|
|
2899
3030
|
test('end event occurred once', () => {
|