packages/deriver/tests/Unit/Reporter/JsonReporterTest.php
1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Reporter;
6
7use Deriver\Deriver\Candidate;
8use Deriver\Deriver\Candidate\Alternative;
9use Deriver\Deriver\Candidate\CandidateCollection;
10use Deriver\Deriver\Candidate\ResultRef;
11use Deriver\Deriver\Candidate\Snapshot;
12use Deriver\Deriver\Evaluator\Evidence\EvidenceKind;
13use Deriver\Deriver\Evaluator\Evidence\Node;
14use Deriver\Deriver\Evaluator\Term;
15use Deriver\Exception\ReportingException;
16use Deriver\Reporter\JsonReporter;
17use PHPUnit\Framework\Attributes\CoversNothing;
18use PHPUnit\Framework\TestCase;
19
20#[CoversNothing]
21final class JsonReporterTest extends TestCase
22{
23 public function testReportIncludesConcreteValuesAndOrderedEvidence(): void
24 {
25 $input = new Node(EvidenceKind::Operation);
26 $node = new Node(EvidenceKind::Observation, ['value' => $input]);
27 $evidence = [new Alternative($node, $node, new Snapshot('s', [], [], new \Deriver\Deriver\Evaluator\TargetProfile(), 'environment'))];
28 $candidates = new CandidateCollection([new Candidate(Term::constant(1.0), $evidence)], new ResultRef('r'));
29 $text = (new JsonReporter())->report($candidates);
30 self::assertStringContainsString('"result": 1.0', $text);
31 self::assertStringContainsString('"interrupted": false', $text);
32 self::assertStringContainsString($node->id, $text);
33 self::assertStringContainsString($input->id, $text);
34 self::assertStringNotContainsString('sourceModes', $text);
35 }
36
37 public function testReportIncludesResidualStructure(): void
38 {
39 $node = new Node(EvidenceKind::Observation);
40 $evidence = [new Alternative($node, $node, new Snapshot('s', [], [], new \Deriver\Deriver\Evaluator\TargetProfile(), 'environment'))];
41 $candidates = new CandidateCollection([new Candidate(Term::parameter('id', 'int'), $evidence)], new ResultRef('r'), interrupted: true);
42 $text = (new JsonReporter())->report($candidates);
43 self::assertStringContainsString('"type": "partials"', $text);
44 self::assertStringContainsString('"literal": "id"', $text);
45 self::assertStringContainsString('"interrupted": true', $text);
46 }
47
48 public function testReportFailsWithoutSilentlyReplacingBinaryStrings(): void
49 {
50 $node = new Node(EvidenceKind::Observation);
51 $evidence = [new Alternative($node, $node, new Snapshot('s', [], [], new \Deriver\Deriver\Evaluator\TargetProfile(), 'environment'))];
52 $candidates = new CandidateCollection([new Candidate(Term::constant("\xff"), $evidence)], new ResultRef('r'));
53 $this->expectException(ReportingException::class);
54 $this->expectExceptionMessage('Cannot encode report as JSON');
55 (new JsonReporter())->report($candidates);
56 }
57
58 public function testReportProducesAnEmptyArrayForNoCandidates(): void
59 {
60 self::assertSame("{\n \"interrupted\": false,\n \"candidates\": []\n}\n", (new JsonReporter())->report(new CandidateCollection([], new ResultRef('r'))));
61 }
62}
63