@@ -334,6 +334,138 @@ public function testFirstRunCreatesFileSorted(): void
334334 self ::assertStringContainsString ('Error C ' , $ result );
335335 }
336336
337+ public function testOrphanedFilesAreDeleted (): void
338+ {
339+ $ folder = $ this ->prepareSampleFolder ();
340+ $ loaderPath = $ folder . '/baselines/loader.neon ' ;
341+
342+ // Create existing baseline files for two identifiers
343+ $ existingBaseline1 = <<<'NEON'
344+ parameters:
345+ ignoreErrors:
346+ -
347+ message: '#^Error A$#'
348+ count: 1
349+ path: ../app/a.php
350+
351+ NEON;
352+ $ existingBaseline2 = <<<'NEON'
353+ parameters:
354+ ignoreErrors:
355+ -
356+ message: '#^Error B$#'
357+ count: 1
358+ path: ../app/b.php
359+
360+ NEON;
361+ file_put_contents ($ folder . '/baselines/first.identifier.neon ' , $ existingBaseline1 );
362+ file_put_contents ($ folder . '/baselines/second.identifier.neon ' , $ existingBaseline2 );
363+
364+ // Now regenerate with only first.identifier (second.identifier should be deleted)
365+ $ inputErrors = [
366+ 'parameters ' => [
367+ 'ignoreErrors ' => [
368+ ['message ' => '#^Error A$# ' , 'count ' => 1 , 'path ' => '../app/a.php ' , 'identifier ' => 'first.identifier ' ],
369+ ],
370+ ],
371+ ];
372+ file_put_contents ($ loaderPath , Neon::encode ($ inputErrors ));
373+
374+ $ splitter = new BaselineSplitter ("\t" , true );
375+ $ result = $ splitter ->split ($ loaderPath );
376+
377+ $ firstIdentifierPath = $ folder . '/baselines/first.identifier.neon ' ;
378+ $ secondIdentifierPath = $ folder . '/baselines/second.identifier.neon ' ;
379+
380+ // first.identifier.neon should still exist
381+ self ::assertFileExists ($ firstIdentifierPath );
382+ self ::assertArrayHasKey ($ firstIdentifierPath , $ result );
383+ self ::assertSame (1 , $ result [$ firstIdentifierPath ]);
384+
385+ // second.identifier.neon should be deleted
386+ self ::assertFileDoesNotExist ($ secondIdentifierPath );
387+ self ::assertArrayHasKey ($ secondIdentifierPath , $ result );
388+ self ::assertSame (0 , $ result [$ secondIdentifierPath ]);
389+
390+ // loader should still exist
391+ self ::assertFileExists ($ loaderPath );
392+ self ::assertArrayHasKey ($ loaderPath , $ result );
393+ self ::assertNull ($ result [$ loaderPath ]);
394+ }
395+
396+ public function testLoaderFileIsNotDeleted (): void
397+ {
398+ $ folder = $ this ->prepareSampleFolder ();
399+ $ loaderPath = $ folder . '/baselines/loader.neon ' ;
400+ $ orphanPath = $ folder . '/baselines/orphan.neon ' ;
401+
402+ // Create an empty baseline (no errors)
403+ $ inputErrors = [
404+ 'parameters ' => [
405+ 'ignoreErrors ' => [],
406+ ],
407+ ];
408+ file_put_contents ($ loaderPath , Neon::encode ($ inputErrors ));
409+
410+ // Create an orphaned file that happens to exist
411+ file_put_contents ($ orphanPath , 'some content ' );
412+
413+ $ splitter = new BaselineSplitter ("\t" , true );
414+ $ result = $ splitter ->split ($ loaderPath );
415+
416+ // Loader should still exist
417+ self ::assertFileExists ($ loaderPath );
418+ self ::assertArrayHasKey ($ loaderPath , $ result );
419+ self ::assertNull ($ result [$ loaderPath ]);
420+
421+ // Orphaned file should be deleted
422+ self ::assertFileDoesNotExist ($ orphanPath );
423+ self ::assertArrayHasKey ($ orphanPath , $ result );
424+ self ::assertSame (0 , $ result [$ orphanPath ]);
425+ }
426+
427+ public function testOnlyFilesWithMatchingExtensionAreDeleted (): void
428+ {
429+ $ folder = $ this ->prepareSampleFolder ();
430+ $ loaderPath = $ folder . '/baselines/loader.neon ' ;
431+
432+ // Create a .neon baseline file and a .php file
433+ $ existingBaseline = <<<'NEON'
434+ parameters:
435+ ignoreErrors:
436+ -
437+ message: '#^Error A$#'
438+ count: 1
439+ path: ../app/a.php
440+
441+ NEON;
442+ file_put_contents ($ folder . '/baselines/old.identifier.neon ' , $ existingBaseline );
443+ file_put_contents ($ folder . '/baselines/some.file.php ' , '<?php // some php file ' );
444+
445+ // Regenerate with empty baseline
446+ $ inputErrors = [
447+ 'parameters ' => [
448+ 'ignoreErrors ' => [],
449+ ],
450+ ];
451+ file_put_contents ($ loaderPath , Neon::encode ($ inputErrors ));
452+
453+ $ splitter = new BaselineSplitter ("\t" , true );
454+ $ result = $ splitter ->split ($ loaderPath );
455+
456+ $ oldIdentifierPath = $ folder . '/baselines/old.identifier.neon ' ;
457+ $ phpFilePath = $ folder . '/baselines/some.file.php ' ;
458+
459+ // .neon file should be deleted
460+ self ::assertFileDoesNotExist ($ oldIdentifierPath );
461+ self ::assertArrayHasKey ($ oldIdentifierPath , $ result );
462+ self ::assertSame (0 , $ result [$ oldIdentifierPath ]);
463+
464+ // .php file should NOT be deleted (wrong extension)
465+ self ::assertFileExists ($ phpFilePath );
466+ self ::assertArrayNotHasKey ($ phpFilePath , $ result );
467+ }
468+
337469 /**
338470 * @return array{parameters: array{ignoreErrors: array{0: array{message?: string, rawMessage?: string, count: int, path: string, identifier?: string}}}}
339471 */
0 commit comments