Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
29 / 29
n/a
0 / 0
CRAP
n/a
0 / 0
1<?php
2
3// ╔════════════════════════════════════════════════════════════╗
4// ║ MIT Licence (#Expat) - https://opensource.org/licenses/MIT ║
5// ║ Copyright 2026 Frederic Poeydomenge <dyno@phexium.com>     ║
6// ╚════════════════════════════════════════════════════════════╝
7
8declare(strict_types=1);
9
10pest()->group('unit');
11
12use Phexium\Domain\Id\TimestampId;
13use Phexium\Domain\Specification\BinaryXnorSpecification;
14use Tests\Phexium\Fake\Domain\Specification\IdSpecification as FakeIdSpecification;
15use Tests\Phexium\Fake\Domain\Specification\NameSpecification as FakeNameSpecification;
16
17describe('Truth table', function (): void {
18    it('combines two specifications with XNOR operator in SQL', function (): void {
19        $nameSpec = new FakeNameSpecification('Foo');
20        $idSpec = new FakeIdSpecification(new TimestampId(123));
21        $xnorSpec = new BinaryXnorSpecification($nameSpec, $idSpec);
22
23        $result = $xnorSpec->toSql();
24
25        expect($result)->toBeArray();
26        expect($result)->toHaveKey('sql');
27        expect($result)->toHaveKey('params');
28        expect($result['sql'])->toBe('((name = :name_0) AND (id = :id_1)) OR (NOT (name = :name_0) AND NOT (id = :id_1))');
29        expect($result['params'])->toBe(['name_0' => 'Foo', 'id_1' => 123]);
30    });
31
32    it('returns callable that applies XNOR logic', function (): void {
33        $nameSpec = new FakeNameSpecification('Foo');
34        $idSpec = new FakeIdSpecification(new TimestampId(123));
35        $xnorSpec = new BinaryXnorSpecification($nameSpec, $idSpec);
36
37        $filter = $xnorSpec->toInMemoryFilter();
38
39        expect($filter)->toBeCallable();
40
41        $matchingBothRow = ['id' => 123, 'name' => 'Foo'];
42        expect($filter($matchingBothRow))->toBeTrue();
43
44        $matchingIdOnly = ['id' => 123, 'name' => 'Bar'];
45        expect($filter($matchingIdOnly))->toBeFalse();
46
47        $matchingNameOnly = ['id' => 456, 'name' => 'Foo'];
48        expect($filter($matchingNameOnly))->toBeFalse();
49
50        $matchingNone = ['id' => 456, 'name' => 'Bar'];
51        expect($filter($matchingNone))->toBeTrue();
52    });
53});