Skip to content

Commit 025ebfc

Browse files
committed
Query tests added
1 parent 16734bb commit 025ebfc

File tree

6 files changed

+285
-38
lines changed

6 files changed

+285
-38
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Remorhaz\JSON\Patch\Query\Exception;
5+
6+
use Remorhaz\JSON\Data\Value\NodeValueInterface;
7+
use RuntimeException;
8+
use Throwable;
9+
10+
final class OperationNotLoadedException extends RuntimeException implements ExceptionInterface
11+
{
12+
13+
private $index;
14+
15+
private $patch;
16+
17+
public function __construct(int $index, NodeValueInterface $patch, Throwable $previous = null)
18+
{
19+
$this->index = $index;
20+
$this->patch = $patch;
21+
parent::__construct("Failed to load operation #{$this->index} from patch", 0, $previous);
22+
}
23+
24+
public function getIndex(): int
25+
{
26+
return $this->index;
27+
}
28+
29+
public function getPatch(): NodeValueInterface
30+
{
31+
return $this->patch;
32+
}
33+
}

src/Query/Exception/PatchNotLoadedException.php

Lines changed: 0 additions & 25 deletions
This file was deleted.

src/Query/LazyQuery.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,14 +55,14 @@ private function getLoadedQuery(): QueryInterface
5555
private function loadQuery(): QueryInterface
5656
{
5757
$operations = [];
58-
try {
59-
foreach ($this->createOperationDataIterator($this->patch) as $index => $operationData) {
58+
foreach ($this->createOperationDataIterator($this->patch) as $index => $operationData) {
59+
try {
6060
$operations[] = $this
6161
->operationFactory
6262
->fromJson($operationData, $index);
63+
} catch (Throwable $e) {
64+
throw new Exception\OperationNotLoadedException($index, $this->patch, $e);
6365
}
64-
} catch (Throwable $e) {
65-
throw new Exception\PatchNotLoadedException($this->patch, $e);
6666
}
6767

6868
return new Query($this->encoder, $this->decoder, ...$operations);

tests/Query/Exception/PatchNotLoadedExceptionTest.php renamed to tests/Query/Exception/OperationNotLoadedExceptionTest.php

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,40 +6,52 @@
66
use Exception;
77
use PHPUnit\Framework\TestCase;
88
use Remorhaz\JSON\Data\Value\NodeValueInterface;
9-
use Remorhaz\JSON\Patch\Query\Exception\PatchNotLoadedException;
9+
use Remorhaz\JSON\Patch\Query\Exception\OperationNotLoadedException;
1010

1111
/**
12-
* @covers \Remorhaz\JSON\Patch\Query\Exception\PatchNotLoadedException
12+
* @covers \Remorhaz\JSON\Patch\Query\Exception\OperationNotLoadedException
1313
*/
14-
class PatchNotLoadedExceptionTest extends TestCase
14+
class OperationNotLoadedExceptionTest extends TestCase
1515
{
1616

1717
public function testGetMessage_Constructed_ReturnsMatchingValue(): void
1818
{
19-
$exception = new PatchNotLoadedException(
19+
$exception = new OperationNotLoadedException(
20+
1,
2021
$this->createMock(NodeValueInterface::class)
2122
);
22-
self::assertSame('Failed to load patch', $exception->getMessage());
23+
self::assertSame('Failed to load operation #1 from patch', $exception->getMessage());
24+
}
25+
26+
public function testGetIndex_ConstructedWithIndex_ReturnsSameValue(): void
27+
{
28+
$exception = new OperationNotLoadedException(
29+
1,
30+
$this->createMock(NodeValueInterface::class)
31+
);
32+
self::assertSame(1, $exception->getIndex());
2333
}
2434

2535
public function testGetPatch_ConstructedWithPatch_ReturnsSameInstance(): void
2636
{
2737
$patch = $this->createMock(NodeValueInterface::class);
28-
$exception = new PatchNotLoadedException($patch);
38+
$exception = new OperationNotLoadedException(1, $patch);
2939
self::assertSame($patch, $exception->getPatch());
3040
}
3141

3242
public function testGetCode_Always_ReturnsZero(): void
3343
{
34-
$exception = new PatchNotLoadedException(
44+
$exception = new OperationNotLoadedException(
45+
1,
3546
$this->createMock(NodeValueInterface::class)
3647
);
3748
self::assertSame(0, $exception->getCode());
3849
}
3950

4051
public function testGetPrevious_ConstructedWithoutPrevious_ReturnsNull(): void
4152
{
42-
$exception = new PatchNotLoadedException(
53+
$exception = new OperationNotLoadedException(
54+
1,
4355
$this->createMock(NodeValueInterface::class)
4456
);
4557
self::assertNull($exception->getPrevious());
@@ -48,7 +60,8 @@ public function testGetPrevious_ConstructedWithoutPrevious_ReturnsNull(): void
4860
public function testGetPrevious_ConstructedWithPrevious_ReturnsSameInstance(): void
4961
{
5062
$previous = new Exception;
51-
$exception = new PatchNotLoadedException(
63+
$exception = new OperationNotLoadedException(
64+
1,
5265
$this->createMock(NodeValueInterface::class),
5366
$previous
5467
);

tests/Query/LazyQueryTest.php

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Remorhaz\JSON\Patch\Test\Query;
5+
6+
use Exception;
7+
use PHPUnit\Framework\TestCase;
8+
use Remorhaz\JSON\Data\Export\ValueDecoderInterface;
9+
use Remorhaz\JSON\Data\Export\ValueEncoderInterface;
10+
use Remorhaz\JSON\Data\Path\Path;
11+
use Remorhaz\JSON\Data\Value\DecodedJson\NodeArrayValue;
12+
use Remorhaz\JSON\Data\Value\DecodedJson\NodeValueFactory;
13+
use Remorhaz\JSON\Data\Value\NodeValueInterface;
14+
use Remorhaz\JSON\Patch\Exception\ExceptionInterface as PatchExceptionInterface;
15+
use Remorhaz\JSON\Patch\Operation\OperationFactoryInterface;
16+
use Remorhaz\JSON\Patch\Operation\OperationInterface;
17+
use Remorhaz\JSON\Patch\Query\Exception\InvalidPatchException;
18+
use Remorhaz\JSON\Patch\Query\Exception\OperationNotLoadedException;
19+
use Remorhaz\JSON\Patch\Query\LazyQuery;
20+
use Remorhaz\JSON\Pointer\Processor\ProcessorInterface as PointerProcessorInterface;
21+
22+
/**
23+
* Class LazyQueryTest
24+
*
25+
* @package Remorhaz\JSON\Patch\Query
26+
* @covers \Remorhaz\JSON\Patch\Query\LazyQuery
27+
*/
28+
class LazyQueryTest extends TestCase
29+
{
30+
31+
/**
32+
* @throws PatchExceptionInterface
33+
*/
34+
public function testInvoke_ConstructedWithNonArrayPatch_ThrowsException(): void
35+
{
36+
$query = new LazyQuery(
37+
$this->createMock(OperationFactoryInterface::class),
38+
$this->createMock(ValueEncoderInterface::class),
39+
$this->createMock(ValueDecoderInterface::class),
40+
$this->createMock(NodeValueInterface::class)
41+
);
42+
$input = $this->createMock(NodeValueInterface::class);
43+
$pointerProcessor = $this->createMock(PointerProcessorInterface::class);
44+
45+
$this->expectException(InvalidPatchException::class);
46+
$query($input, $pointerProcessor);
47+
}
48+
49+
/**
50+
* @throws PatchExceptionInterface
51+
*/
52+
public function testInvoke_OperationFactoryThrowsException_ThrowsException(): void
53+
{
54+
$operationFactory = $this->createMock(OperationFactoryInterface::class);
55+
$patch = new NodeArrayValue(
56+
[
57+
(object) [],
58+
],
59+
new Path,
60+
NodeValueFactory::create()
61+
);
62+
$query = new LazyQuery(
63+
$operationFactory,
64+
$this->createMock(ValueEncoderInterface::class),
65+
$this->createMock(ValueDecoderInterface::class),
66+
$patch
67+
);
68+
$input = $this->createMock(NodeValueInterface::class);
69+
$pointerProcessor = $this->createMock(PointerProcessorInterface::class);
70+
71+
$operationFactory
72+
->method('fromJson')
73+
->willThrowException(new Exception);
74+
$this->expectException(OperationNotLoadedException::class);
75+
$query($input, $pointerProcessor);
76+
}
77+
78+
/**
79+
* @throws PatchExceptionInterface
80+
*/
81+
public function testInvoke_OperationFactoryReturnsTwoOperations_SameOperationsAppliedInSameOrder(): void
82+
{
83+
$operationFactory = $this->createMock(OperationFactoryInterface::class);
84+
$patch = new NodeArrayValue(
85+
[
86+
(object) [],
87+
(object) [],
88+
],
89+
new Path,
90+
NodeValueFactory::create()
91+
);
92+
$query = new LazyQuery(
93+
$operationFactory,
94+
$this->createMock(ValueEncoderInterface::class),
95+
$this->createMock(ValueDecoderInterface::class),
96+
$patch
97+
);
98+
$input = $this->createMock(NodeValueInterface::class);
99+
$pointerProcessor = $this->createMock(PointerProcessorInterface::class);
100+
101+
$firstOperation = $this->createMock(OperationInterface::class);
102+
$secondOperation = $this->createMock(OperationInterface::class);
103+
$operationFactory
104+
->expects(self::exactly(2))
105+
->method('fromJson')
106+
->willReturnOnConsecutiveCalls($firstOperation, $secondOperation);
107+
108+
$firstOutput = $this->createMock(NodeValueInterface::class);
109+
$firstOperation
110+
->method('apply')
111+
->with(self::identicalTo($input), self::identicalTo($pointerProcessor))
112+
->willReturn($firstOutput);
113+
114+
$secondOutput = $this->createMock(NodeValueInterface::class);
115+
$secondOperation
116+
->method('apply')
117+
->with(self::identicalTo($firstOutput), self::identicalTo($pointerProcessor))
118+
->willReturn($secondOutput);
119+
$actualValue = $query($input, $pointerProcessor);
120+
self::assertSame($secondOutput, $actualValue->get());
121+
}
122+
}

tests/Query/QueryFactoryTest.php

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Remorhaz\JSON\Patch\Test\Query;
5+
6+
use PHPUnit\Framework\TestCase;
7+
use Remorhaz\JSON\Data\Export\ValueDecoderInterface;
8+
use Remorhaz\JSON\Data\Export\ValueEncoderInterface;
9+
use Remorhaz\JSON\Data\Value\EncodedJson\NodeValueFactory;
10+
use Remorhaz\JSON\Data\Value\NodeValueInterface;
11+
use Remorhaz\JSON\Patch\Exception\ExceptionInterface as PatchExceptionInterface;
12+
use Remorhaz\JSON\Patch\Operation\OperationFactoryInterface;
13+
use Remorhaz\JSON\Patch\Query\LazyQuery;
14+
use Remorhaz\JSON\Patch\Query\QueryFactory;
15+
use Remorhaz\JSON\Pointer\Processor\ProcessorInterface as PointerProcessorInterface;
16+
17+
/**
18+
* @covers \Remorhaz\JSON\Patch\Query\QueryFactory
19+
*/
20+
class QueryFactoryTest extends TestCase
21+
{
22+
23+
public function testCreate_Always_ReturnsQueryFactoryInstance(): void
24+
{
25+
self::assertInstanceOf(QueryFactory::class, QueryFactory::create());
26+
}
27+
28+
public function testCreateQuery_Constructed_ReturnsLazyQueryInstaqnce(): void
29+
{
30+
$factory = QueryFactory::create();
31+
$patch = $this->createMock(NodeValueInterface::class);
32+
self::assertInstanceOf(LazyQuery::class, $factory->createQuery($patch));
33+
}
34+
35+
/**
36+
* @throws PatchExceptionInterface
37+
*/
38+
public function testCreateQuery_ConstructedWithOperationFactory_ResultUsesSameInstanceOnInvoke(): void
39+
{
40+
$operationFactory = $this->createMock(OperationFactoryInterface::class);
41+
$factory = new QueryFactory(
42+
$operationFactory,
43+
$this->createMock(ValueEncoderInterface::class),
44+
$this->createMock(ValueDecoderInterface::class),
45+
);
46+
47+
$patch = NodeValueFactory::create()->createValue('[{"op":"remove","path":"/0"}]');
48+
$query = $factory->createQuery($patch);
49+
$input = $this->createMock(NodeValueInterface::class);
50+
$pointerProcessor = $this->createMock(PointerProcessorInterface::class);
51+
$operationFactory
52+
->expects(self::atLeastOnce())
53+
->method('fromJson');
54+
$query($input, $pointerProcessor);
55+
}
56+
57+
/**
58+
* @throws PatchExceptionInterface
59+
*/
60+
public function testCreateQuery_ConstructedWithEncoder_ResultOfInvocationUsesSameInstanceOnEncode(): void
61+
{
62+
$encoder = $this->createMock(ValueEncoderInterface::class);
63+
$factory = new QueryFactory(
64+
$this->createMock(OperationFactoryInterface::class),
65+
$encoder,
66+
$this->createMock(ValueDecoderInterface::class)
67+
);
68+
69+
$patch = NodeValueFactory::create()->createValue('[{"op":"remove","path":"/0"}]');
70+
$query = $factory->createQuery($patch);
71+
$result = $query(
72+
$this->createMock(NodeValueInterface::class),
73+
$this->createMock(PointerProcessorInterface::class)
74+
);
75+
$encoder
76+
->expects(self::once())
77+
->method('exportValue');
78+
$result->encode();
79+
}
80+
81+
/**
82+
* @throws PatchExceptionInterface
83+
*/
84+
public function testCreateQuery_ConstructedWithDecoder_ResultOfInvocationUsesSameInstanceOnDecode(): void
85+
{
86+
$decoder = $this->createMock(ValueDecoderInterface::class);
87+
$factory = new QueryFactory(
88+
$this->createMock(OperationFactoryInterface::class),
89+
$this->createMock(ValueEncoderInterface::class),
90+
$decoder
91+
);
92+
93+
$patch = NodeValueFactory::create()->createValue('[{"op":"remove","path":"/0"}]');
94+
$query = $factory->createQuery($patch);
95+
$result = $query(
96+
$this->createMock(NodeValueInterface::class),
97+
$this->createMock(PointerProcessorInterface::class)
98+
);
99+
$decoder
100+
->expects(self::once())
101+
->method('exportValue');
102+
$result->decode();
103+
}
104+
}

0 commit comments

Comments
 (0)