Skip to content

Commit df109b9

Browse files
committed
de-duplicate test code
1 parent f7e8570 commit df109b9

1 file changed

Lines changed: 112 additions & 196 deletions

File tree

tests/Unit/Parser/ParserTest.php

Lines changed: 112 additions & 196 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,91 @@
88
use Kestrel\JsoncParser\Parser\JsonVisitor;
99
use Kestrel\JsoncParser\Parser\ParseErrorCode;
1010

11+
/**
12+
* A reusable visitor that records events to an array.
13+
* Configure which events to record via constructor parameters.
14+
*/
15+
class EventRecordingVisitor implements JsonVisitor
16+
{
17+
/** @var array<array<mixed>> */
18+
public array $events = [];
19+
20+
public function __construct(
21+
private bool $recordObject = true,
22+
private bool $recordArray = true,
23+
private bool $recordLiteral = true,
24+
private bool $recordSeparator = true,
25+
private bool $recordComment = true,
26+
private bool $recordError = true,
27+
) {
28+
}
29+
30+
public function onObjectBegin(int $offset, int $length, int $startLine, int $startCharacter, \Closure $pathSupplier): bool|null
31+
{
32+
if ($this->recordObject) {
33+
$this->events[] = ['onObjectBegin', $offset, $pathSupplier()];
34+
}
35+
return null;
36+
}
37+
38+
public function onObjectProperty(string $property, int $offset, int $length, int $startLine, int $startCharacter, \Closure $pathSupplier): void
39+
{
40+
if ($this->recordObject) {
41+
$this->events[] = ['onObjectProperty', $property, $pathSupplier()];
42+
}
43+
}
44+
45+
public function onObjectEnd(int $offset, int $length, int $startLine, int $startCharacter): void
46+
{
47+
if ($this->recordObject) {
48+
$this->events[] = ['onObjectEnd', $offset];
49+
}
50+
}
51+
52+
public function onArrayBegin(int $offset, int $length, int $startLine, int $startCharacter, \Closure $pathSupplier): bool|null
53+
{
54+
if ($this->recordArray) {
55+
$this->events[] = ['onArrayBegin', $offset, $pathSupplier()];
56+
}
57+
return null;
58+
}
59+
60+
public function onArrayEnd(int $offset, int $length, int $startLine, int $startCharacter): void
61+
{
62+
if ($this->recordArray) {
63+
$this->events[] = ['onArrayEnd', $offset];
64+
}
65+
}
66+
67+
public function onLiteralValue(mixed $value, int $offset, int $length, int $startLine, int $startCharacter, \Closure $pathSupplier): void
68+
{
69+
if ($this->recordLiteral) {
70+
$this->events[] = ['onLiteralValue', $value, $pathSupplier()];
71+
}
72+
}
73+
74+
public function onSeparator(string $character, int $offset, int $length, int $startLine, int $startCharacter): void
75+
{
76+
if ($this->recordSeparator) {
77+
$this->events[] = ['onSeparator', $character];
78+
}
79+
}
80+
81+
public function onComment(int $offset, int $length, int $startLine, int $startCharacter): void
82+
{
83+
if ($this->recordComment) {
84+
$this->events[] = ['onComment', $offset];
85+
}
86+
}
87+
88+
public function onError(ParseErrorCode $error, int $offset, int $length, int $startLine, int $startCharacter): void
89+
{
90+
if ($this->recordError) {
91+
$this->events[] = ['onError', $error];
92+
}
93+
}
94+
}
95+
1196
describe('parse: literals', function () {
1297
test('parses boolean literals', function () {
1398
assertValidParse('true', true);
@@ -292,122 +377,31 @@
292377

293378
describe('visit: object', function () {
294379
test('visits empty object', function () {
295-
/** @var array<array<mixed>> $events */
296-
$events = [];
297-
298-
$visitor = new class ($events) implements JsonVisitor {
299-
/**
300-
* @param array<array<mixed>> $events
301-
* @phpstan-ignore property.onlyWritten (property is accessed via reference binding)
302-
*/
303-
public function __construct(private array &$events)
304-
{
305-
}
306-
307-
public function onObjectBegin(int $offset, int $length, int $startLine, int $startCharacter, \Closure $pathSupplier): bool|null
308-
{
309-
$this->events[] = ['onObjectBegin', $offset, $pathSupplier()];
310-
return null;
311-
}
312-
public function onObjectProperty(string $property, int $offset, int $length, int $startLine, int $startCharacter, \Closure $pathSupplier): void
313-
{
314-
$this->events[] = ['onObjectProperty', $property, $pathSupplier()];
315-
}
316-
public function onObjectEnd(int $offset, int $length, int $startLine, int $startCharacter): void
317-
{
318-
$this->events[] = ['onObjectEnd', $offset];
319-
}
320-
public function onArrayBegin(int $offset, int $length, int $startLine, int $startCharacter, \Closure $pathSupplier): bool|null
321-
{
322-
$this->events[] = ['onArrayBegin', $offset, $pathSupplier()];
323-
return null;
324-
}
325-
public function onArrayEnd(int $offset, int $length, int $startLine, int $startCharacter): void
326-
{
327-
$this->events[] = ['onArrayEnd', $offset];
328-
}
329-
public function onLiteralValue(mixed $value, int $offset, int $length, int $startLine, int $startCharacter, \Closure $pathSupplier): void
330-
{
331-
$this->events[] = ['onLiteralValue', $value, $pathSupplier()];
332-
}
333-
public function onSeparator(string $character, int $offset, int $length, int $startLine, int $startCharacter): void
334-
{
335-
$this->events[] = ['onSeparator', $character];
336-
}
337-
public function onComment(int $offset, int $length, int $startLine, int $startCharacter): void
338-
{
339-
$this->events[] = ['onComment', $offset];
340-
}
341-
public function onError(ParseErrorCode $error, int $offset, int $length, int $startLine, int $startCharacter): void
342-
{
343-
$this->events[] = ['onError', $error];
344-
}
345-
};
380+
$visitor = new EventRecordingVisitor(
381+
recordArray: false,
382+
recordLiteral: false,
383+
recordComment: false,
384+
recordError: false,
385+
);
346386

347387
JsoncParser::visit('{ }', $visitor);
348388

349-
expect($events)->toBe([
389+
expect($visitor->events)->toBe([
350390
['onObjectBegin', 0, []],
351391
['onObjectEnd', 2],
352392
]);
353393
});
354394

355395
test('visits simple object', function () {
356-
/** @var array<array<mixed>> $events */
357-
$events = [];
358-
359-
$visitor = new class ($events) implements JsonVisitor {
360-
/**
361-
* @param array<array<mixed>> $events
362-
* @phpstan-ignore property.onlyWritten (property is accessed via reference binding)
363-
*/
364-
public function __construct(private array &$events)
365-
{
366-
}
367-
368-
public function onObjectBegin(int $offset, int $length, int $startLine, int $startCharacter, \Closure $pathSupplier): bool|null
369-
{
370-
$this->events[] = ['onObjectBegin', $offset, $pathSupplier()];
371-
return null;
372-
}
373-
public function onObjectProperty(string $property, int $offset, int $length, int $startLine, int $startCharacter, \Closure $pathSupplier): void
374-
{
375-
$this->events[] = ['onObjectProperty', $property, $pathSupplier()];
376-
}
377-
public function onObjectEnd(int $offset, int $length, int $startLine, int $startCharacter): void
378-
{
379-
$this->events[] = ['onObjectEnd', $offset];
380-
}
381-
public function onArrayBegin(int $offset, int $length, int $startLine, int $startCharacter, \Closure $pathSupplier): bool|null
382-
{
383-
$this->events[] = ['onArrayBegin', $offset, $pathSupplier()];
384-
return null;
385-
}
386-
public function onArrayEnd(int $offset, int $length, int $startLine, int $startCharacter): void
387-
{
388-
$this->events[] = ['onArrayEnd', $offset];
389-
}
390-
public function onLiteralValue(mixed $value, int $offset, int $length, int $startLine, int $startCharacter, \Closure $pathSupplier): void
391-
{
392-
$this->events[] = ['onLiteralValue', $value, $pathSupplier()];
393-
}
394-
public function onSeparator(string $character, int $offset, int $length, int $startLine, int $startCharacter): void
395-
{
396-
$this->events[] = ['onSeparator', $character];
397-
}
398-
public function onComment(int $offset, int $length, int $startLine, int $startCharacter): void
399-
{
400-
$this->events[] = ['onComment', $offset];
401-
}
402-
public function onError(ParseErrorCode $error, int $offset, int $length, int $startLine, int $startCharacter): void
403-
{
404-
$this->events[] = ['onError', $error];
405-
}
406-
};
396+
$visitor = new EventRecordingVisitor(
397+
recordArray: false,
398+
recordComment: false,
399+
recordError: false,
400+
);
407401

408402
JsoncParser::visit('{ "foo": "bar" }', $visitor);
409403

410-
expect($events)->toBe([
404+
expect($visitor->events)->toBe([
411405
['onObjectBegin', 0, []],
412406
['onObjectProperty', 'foo', []],
413407
['onSeparator', ':'],
@@ -419,110 +413,32 @@ public function onError(ParseErrorCode $error, int $offset, int $length, int $st
419413

420414
describe('visit: array', function () {
421415
test('visits empty array', function () {
422-
/** @var array<array<mixed>> $events */
423-
$events = [];
424-
425-
$visitor = new class ($events) implements JsonVisitor {
426-
/**
427-
* @param array<array<mixed>> $events
428-
* @phpstan-ignore property.onlyWritten (property is accessed via reference binding)
429-
*/
430-
public function __construct(private array &$events)
431-
{
432-
}
433-
434-
public function onObjectBegin(int $offset, int $length, int $startLine, int $startCharacter, \Closure $pathSupplier): bool|null
435-
{
436-
return null;
437-
}
438-
public function onObjectProperty(string $property, int $offset, int $length, int $startLine, int $startCharacter, \Closure $pathSupplier): void
439-
{
440-
}
441-
public function onObjectEnd(int $offset, int $length, int $startLine, int $startCharacter): void
442-
{
443-
}
444-
public function onArrayBegin(int $offset, int $length, int $startLine, int $startCharacter, \Closure $pathSupplier): bool|null
445-
{
446-
$this->events[] = ['onArrayBegin', $offset, $pathSupplier()];
447-
return null;
448-
}
449-
public function onArrayEnd(int $offset, int $length, int $startLine, int $startCharacter): void
450-
{
451-
$this->events[] = ['onArrayEnd', $offset];
452-
}
453-
public function onLiteralValue(mixed $value, int $offset, int $length, int $startLine, int $startCharacter, \Closure $pathSupplier): void
454-
{
455-
$this->events[] = ['onLiteralValue', $value, $pathSupplier()];
456-
}
457-
public function onSeparator(string $character, int $offset, int $length, int $startLine, int $startCharacter): void
458-
{
459-
}
460-
public function onComment(int $offset, int $length, int $startLine, int $startCharacter): void
461-
{
462-
}
463-
public function onError(ParseErrorCode $error, int $offset, int $length, int $startLine, int $startCharacter): void
464-
{
465-
}
466-
};
416+
$visitor = new EventRecordingVisitor(
417+
recordObject: false,
418+
recordSeparator: false,
419+
recordComment: false,
420+
recordError: false,
421+
);
467422

468423
JsoncParser::visit('[]', $visitor);
469424

470-
expect($events)->toBe([
425+
expect($visitor->events)->toBe([
471426
['onArrayBegin', 0, []],
472427
['onArrayEnd', 1],
473428
]);
474429
});
475430

476431
test('visits array with values', function () {
477-
/** @var array<array<mixed>> $events */
478-
$events = [];
479-
480-
$visitor = new class ($events) implements JsonVisitor {
481-
/**
482-
* @param array<array<mixed>> $events
483-
* @phpstan-ignore property.onlyWritten (property is accessed via reference binding)
484-
*/
485-
public function __construct(private array &$events)
486-
{
487-
}
488-
489-
public function onObjectBegin(int $offset, int $length, int $startLine, int $startCharacter, \Closure $pathSupplier): bool|null
490-
{
491-
return null;
492-
}
493-
public function onObjectProperty(string $property, int $offset, int $length, int $startLine, int $startCharacter, \Closure $pathSupplier): void
494-
{
495-
}
496-
public function onObjectEnd(int $offset, int $length, int $startLine, int $startCharacter): void
497-
{
498-
}
499-
public function onArrayBegin(int $offset, int $length, int $startLine, int $startCharacter, \Closure $pathSupplier): bool|null
500-
{
501-
$this->events[] = ['onArrayBegin', $offset, $pathSupplier()];
502-
return null;
503-
}
504-
public function onArrayEnd(int $offset, int $length, int $startLine, int $startCharacter): void
505-
{
506-
$this->events[] = ['onArrayEnd', $offset];
507-
}
508-
public function onLiteralValue(mixed $value, int $offset, int $length, int $startLine, int $startCharacter, \Closure $pathSupplier): void
509-
{
510-
$this->events[] = ['onLiteralValue', $value, $pathSupplier()];
511-
}
512-
public function onSeparator(string $character, int $offset, int $length, int $startLine, int $startCharacter): void
513-
{
514-
}
515-
public function onComment(int $offset, int $length, int $startLine, int $startCharacter): void
516-
{
517-
}
518-
public function onError(ParseErrorCode $error, int $offset, int $length, int $startLine, int $startCharacter): void
519-
{
520-
}
521-
};
432+
$visitor = new EventRecordingVisitor(
433+
recordObject: false,
434+
recordSeparator: false,
435+
recordComment: false,
436+
recordError: false,
437+
);
522438

523439
JsoncParser::visit('[ true, null ]', $visitor);
524440

525-
expect($events)->toBe([
441+
expect($visitor->events)->toBe([
526442
['onArrayBegin', 0, []],
527443
['onLiteralValue', true, [0]],
528444
['onLiteralValue', null, [1]],

0 commit comments

Comments
 (0)