@@ -57,20 +57,23 @@ public function testProcessFile(): void
5757 );
5858 }
5959
60- public function testProcessFileWithInvalidFile (): void
60+ public function testProcessFileWithEmptyFile (): void
6161 {
6262 $ parser = $ this ->createMock (ParserInterface::class);
63- $ parser ->method ('extractKeys ' )->willReturn (null );
64- $ parser ->method ('getFileName ' )->willReturn ('invalid .xlf ' );
63+ $ parser ->method ('extractKeys ' )->willReturn ([] );
64+ $ parser ->method ('getFileName ' )->willReturn ('empty .xlf ' );
6565
6666 $ logger = $ this ->createMock (LoggerInterface::class);
67- $ logger ->expects ($ this ->once ())
68- ->method ('error ' )
69- ->with ($ this ->stringContains ('The source file invalid.xlf is not valid. ' ));
70-
7167 $ validator = new MismatchValidator ($ logger );
7268 $ result = $ validator ->processFile ($ parser );
7369
70+ // Empty files should now be tracked with an empty array
71+ $ reflection = new ReflectionClass ($ validator );
72+ $ keyArrayProperty = $ reflection ->getProperty ('keyArray ' );
73+ $ keyArray = $ keyArrayProperty ->getValue ($ validator );
74+
75+ $ this ->assertArrayHasKey ('empty.xlf ' , $ keyArray );
76+ $ this ->assertSame ([], $ keyArray ['empty.xlf ' ]);
7477 $ this ->assertEmpty ($ result );
7578 }
7679
@@ -316,4 +319,109 @@ public function testGetShortName(): void
316319
317320 $ this ->assertSame ('MismatchValidator ' , $ validator ->getShortName ());
318321 }
322+
323+ public function testPostProcessDetectsEmptyFileWithMissingKeys (): void
324+ {
325+ $ parser1 = $ this ->createMock (ParserInterface::class);
326+ $ parser1 ->method ('extractKeys ' )->willReturn (['key1 ' , 'key2 ' ]);
327+ $ parser1 ->method ('getFileName ' )->willReturn ('source.xlf ' );
328+
329+ $ parser2 = $ this ->createMock (ParserInterface::class);
330+ $ parser2 ->method ('extractKeys ' )->willReturn ([]);
331+ $ parser2 ->method ('getFileName ' )->willReturn ('empty.xlf ' );
332+
333+ $ logger = $ this ->createMock (LoggerInterface::class);
334+ $ validator = new MismatchValidator ($ logger );
335+
336+ $ validator ->processFile ($ parser1 );
337+ $ validator ->processFile ($ parser2 );
338+
339+ $ validator ->postProcess ();
340+
341+ // Accessing protected property for testing purposes
342+ $ reflection = new ReflectionClass ($ validator );
343+ $ issuesProperty = $ reflection ->getProperty ('issues ' );
344+ $ issues = $ issuesProperty ->getValue ($ validator );
345+
346+ // Should detect both keys as missing in the empty file
347+ $ this ->assertCount (2 , $ issues );
348+
349+ $ issueArrays = array_map (fn ($ issue ) => $ issue ->toArray (), $ issues );
350+
351+ // Check that both key1 and key2 are reported as mismatches
352+ $ keys = array_map (fn ($ issue ) => $ issue ['issues ' ]['key ' ], $ issueArrays );
353+ $ this ->assertContains ('key1 ' , $ keys );
354+ $ this ->assertContains ('key2 ' , $ keys );
355+
356+ // Verify that the empty file is included in the details
357+ foreach ($ issueArrays as $ issueArray ) {
358+ $ files = $ issueArray ['issues ' ]['files ' ];
359+ $ this ->assertCount (2 , $ files );
360+
361+ $ fileNames = array_map (fn ($ file ) => $ file ['file ' ], $ files );
362+ $ this ->assertContains ('source.xlf ' , $ fileNames );
363+ $ this ->assertContains ('empty.xlf ' , $ fileNames );
364+
365+ // Empty file should have null value for all keys
366+ foreach ($ files as $ file ) {
367+ if ('empty.xlf ' === $ file ['file ' ]) {
368+ $ this ->assertNull ($ file ['value ' ]);
369+ }
370+ }
371+ }
372+ }
373+
374+ public function testPostProcessWithMixedScenario (): void
375+ {
376+ // Source file with 6 keys
377+ $ parser1 = $ this ->createMock (ParserInterface::class);
378+ $ parser1 ->method ('extractKeys ' )->willReturn (['key1 ' , 'key2 ' , 'key3 ' , 'key4 ' , 'key5 ' , 'key6 ' ]);
379+ $ parser1 ->method ('getFileName ' )->willReturn ('source.xlf ' );
380+
381+ // Partial translation file with 3 keys
382+ $ parser2 = $ this ->createMock (ParserInterface::class);
383+ $ parser2 ->method ('extractKeys ' )->willReturn (['key1 ' , 'key2 ' , 'key3 ' ]);
384+ $ parser2 ->method ('getFileName ' )->willReturn ('partial.xlf ' );
385+
386+ // Empty translation file
387+ $ parser3 = $ this ->createMock (ParserInterface::class);
388+ $ parser3 ->method ('extractKeys ' )->willReturn ([]);
389+ $ parser3 ->method ('getFileName ' )->willReturn ('empty.xlf ' );
390+
391+ $ logger = $ this ->createMock (LoggerInterface::class);
392+ $ validator = new MismatchValidator ($ logger );
393+
394+ $ validator ->processFile ($ parser1 );
395+ $ validator ->processFile ($ parser2 );
396+ $ validator ->processFile ($ parser3 );
397+
398+ $ validator ->postProcess ();
399+
400+ // Accessing protected property for testing purposes
401+ $ reflection = new ReflectionClass ($ validator );
402+ $ issuesProperty = $ reflection ->getProperty ('issues ' );
403+ $ issues = $ issuesProperty ->getValue ($ validator );
404+
405+ // Should detect all 6 keys as mismatches since:
406+ // - key1, key2, key3 are missing from empty.xlf
407+ // - key4, key5, key6 are missing from both partial.xlf and empty.xlf
408+ $ this ->assertCount (6 , $ issues );
409+
410+ $ issueArrays = array_map (fn ($ issue ) => $ issue ->toArray (), $ issues );
411+ $ keys = array_map (fn ($ issue ) => $ issue ['issues ' ]['key ' ], $ issueArrays );
412+
413+ // All keys should be reported as missing somewhere
414+ $ this ->assertContains ('key1 ' , $ keys );
415+ $ this ->assertContains ('key2 ' , $ keys );
416+ $ this ->assertContains ('key3 ' , $ keys );
417+ $ this ->assertContains ('key4 ' , $ keys );
418+ $ this ->assertContains ('key5 ' , $ keys );
419+ $ this ->assertContains ('key6 ' , $ keys );
420+
421+ // Verify that all three files are tracked in each issue
422+ foreach ($ issueArrays as $ issueArray ) {
423+ $ files = $ issueArray ['issues ' ]['files ' ];
424+ $ this ->assertCount (3 , $ files );
425+ }
426+ }
319427}
0 commit comments