1+ <?php
2+
3+ declare (strict_types=1 );
4+
5+ if (PHP_VERSION_ID < 80500 ) {
6+ return ;
7+ }
8+
9+ use TypePHP \Internal \StreamWrapper ;
10+ use TypePHP \Tests \Fixtures \Pipes \NativePipeRunner ;
11+ use TypePHP \Tests \Fixtures \Pipes \PipePipelineService ;
12+
13+ describe ('PHP 8.5+ Pipe Operator (|>) and Multi-Step Pipelines ' , function () {
14+ describe ('Native Pipe Execution (PHP 8.5+) ' , function () {
15+ test ('executes multi-step piped transformation through first-class callables ' , function () {
16+ $ service = new PipePipelineService ();
17+ $ runner = new NativePipeRunner ();
18+
19+ $ result = $ runner ->runPipeline (10 , $ service );
20+
21+ expect ($ result )->toBe ('[TAG] RECORD_20 ' );
22+ });
23+
24+ test ('throws TypeError at the exact pipe step where parameter contract is violated ' , function () {
25+ $ service = new PipePipelineService ();
26+ $ runner = new NativePipeRunner ();
27+
28+ expect (fn () => $ runner ->runPipeline (-5 , $ service ))
29+ ->toThrow (TypeError::class, 'positive-int ' );
30+ });
31+
32+ test ('executes standalone method pipeline with native pipe operator ' , function () {
33+ $ runner = new NativePipeRunner ();
34+
35+ $ result = $ runner ->runStandalonePipeline (5 );
36+
37+ expect ($ result )->toBe ('piped_user_15 ' );
38+ });
39+
40+ test ('throws TypeError when standalone pipe step receives invalid integer ' , function () {
41+ $ runner = new NativePipeRunner ();
42+
43+ expect (fn () => $ runner ->runStandalonePipeline (-50 ))
44+ ->toThrow (TypeError::class, 'positive-int ' );
45+ });
46+ });
47+
48+ describe ('AST Transformation & Zero Line-Drift with Pipe Syntax ' , function () {
49+ test ('transforms code containing multi-line pipe operator chains with zero line-drift ' , function () {
50+ $ source = <<<'PHP'
51+ <?php
52+
53+ declare(strict_types=1);
54+
55+ /**
56+ * @param positive-int $id
57+ * @return non-empty-string
58+ */
59+ function formatId(int $id): string
60+ {
61+ return "ID_{$id}";
62+ }
63+
64+ $service = new \TypePHP\Tests\Fixtures\Pipes\PipePipelineService();
65+
66+ $targetLine = true;
67+ PHP;
68+
69+ $ transformed = StreamWrapper::transformSource ($ source , 'test_pipe_drift.php ' );
70+
71+ $ origLines = explode ("\n" , str_replace ("\r\n" , "\n" , $ source ));
72+ $ transLines = explode ("\n" , str_replace ("\r\n" , "\n" , $ transformed ));
73+
74+ expect (count ($ transLines ))->toBe (count ($ origLines ));
75+
76+ $ origTarget = array_search ('$targetLine = true; ' , array_map ('trim ' , $ origLines ), true );
77+ $ transTarget = array_search ('$targetLine = true; ' , array_map ('trim ' , $ transLines ), true );
78+
79+ expect ($ transTarget )->toBe ($ origTarget );
80+ });
81+ });
82+ });
0 commit comments