11import {
22 Configuration ,
3+ type OutputWriter ,
34 type Path ,
45 PathReplacer ,
56 PHPUnitXML ,
67 PRESET_PROGRESS ,
78 Printer ,
89 ProcessBuilder ,
910 semverLt ,
11+ TeamcityEvent ,
1012 TestRunner ,
1113} from '@vscode-phpunit/phpunit' ;
1214import { detectPhpUnitStubs , phpUnitProject } from '@vscode-phpunit/phpunit/testing' ;
@@ -20,16 +22,22 @@ const writers = [
2022 writerName : 'OutputChannelWriter' ,
2123 createWriter : ( ) => {
2224 const spy = vi . fn ( ) ;
23- const outputChannel = { append : spy , appendLine : vi . fn ( ) } ;
25+ const outputChannel = { append : spy , appendLine : ( ) => { } } ;
2426 return { writer : new OutputChannelWriter ( outputChannel ) , spy } ;
2527 } ,
2628 } ,
2729 {
2830 writerName : 'TestRunWriter' ,
2931 createWriter : ( ) => {
32+ const testRun = { appendOutput : vi . fn ( ) } as unknown as TestRun ;
33+ const writer = new TestRunWriter ( testRun , new Map ( ) ) ;
3034 const spy = vi . fn ( ) ;
31- const testRun = { appendOutput : spy } as unknown as TestRun ;
32- return { writer : new TestRunWriter ( testRun ) , spy } ;
35+ const originalAppend = writer . append . bind ( writer ) ;
36+ writer . append = ( text : string , ...args : unknown [ ] ) => {
37+ spy ( text ) ;
38+ originalAppend ( text , ...( args as [ ] ) ) ;
39+ } ;
40+ return { writer, spy } ;
3341 } ,
3442 } ,
3543] ;
@@ -187,3 +195,96 @@ describe.each(writers)('PrinterObserver with $writerName', ({ createWriter }) =>
187195 } ) ;
188196 } ) ;
189197} ) ;
198+
199+ describe ( 'PrinterObserver passes location and testId to writer' , ( ) => {
200+ let appendSpy : ReturnType < typeof vi . fn > ;
201+ let observer : PrinterObserver ;
202+
203+ beforeEach ( ( ) => {
204+ appendSpy = vi . fn ( ) ;
205+ const writer : OutputWriter = {
206+ append : appendSpy as OutputWriter [ 'append' ] ,
207+ appendLine : ( ) => { } ,
208+ } ;
209+ observer = new PrinterObserver ( writer , new Printer ( new PHPUnitXML ( ) , PRESET_PROGRESS ) ) ;
210+ } ) ;
211+
212+ function startTest ( name : string , id : string ) {
213+ observer . testStarted ( {
214+ event : TeamcityEvent . testStarted ,
215+ name,
216+ locationHint : '' ,
217+ flowId : 1 ,
218+ id,
219+ file : '/app/tests/MyTest.php' ,
220+ } ) ;
221+ appendSpy . mockClear ( ) ;
222+ }
223+
224+ it ( 'testFinished passes file line 1 as location' , ( ) => {
225+ startTest ( 'test_passed' , 'App\\Tests\\MyTest::test_passed' ) ;
226+
227+ observer . testFinished ( {
228+ event : TeamcityEvent . testFinished ,
229+ name : 'test_passed' ,
230+ locationHint : '' ,
231+ flowId : 1 ,
232+ id : 'App\\Tests\\MyTest::test_passed' ,
233+ file : '/app/tests/MyTest.php' ,
234+ duration : 5 ,
235+ } ) ;
236+
237+ expect ( appendSpy ) . toHaveBeenCalledWith (
238+ expect . any ( String ) ,
239+ { file : '/app/tests/MyTest.php' , line : 1 } ,
240+ 'App\\Tests\\MyTest::test_passed' ,
241+ ) ;
242+ } ) ;
243+
244+ it ( 'testFailed passes detail location when available' , ( ) => {
245+ startTest ( 'test_fail' , 'App\\Tests\\MyTest::test_fail' ) ;
246+
247+ observer . testFailed ( {
248+ event : TeamcityEvent . testFailed ,
249+ name : 'test_fail' ,
250+ locationHint : '' ,
251+ flowId : 1 ,
252+ id : 'App\\Tests\\MyTest::test_fail' ,
253+ file : '/app/tests/MyTest.php' ,
254+ message : 'Failed asserting that false is true.' ,
255+ details : [
256+ { file : 'vendor/phpunit/phpunit/src/Framework/Assert.php' , line : 198 } ,
257+ { file : '/app/tests/MyTest.php' , line : 27 } ,
258+ ] ,
259+ duration : 0 ,
260+ } ) ;
261+
262+ expect ( appendSpy ) . toHaveBeenCalledWith (
263+ expect . any ( String ) ,
264+ { file : '/app/tests/MyTest.php' , line : 27 } ,
265+ 'App\\Tests\\MyTest::test_fail' ,
266+ ) ;
267+ } ) ;
268+
269+ it ( 'testIgnored passes file line 1 as location' , ( ) => {
270+ startTest ( 'test_skipped' , 'App\\Tests\\MyTest::test_skipped' ) ;
271+
272+ observer . testIgnored ( {
273+ event : TeamcityEvent . testIgnored ,
274+ name : 'test_skipped' ,
275+ locationHint : '' ,
276+ flowId : 1 ,
277+ id : 'App\\Tests\\MyTest::test_skipped' ,
278+ file : '/app/tests/MyTest.php' ,
279+ message : 'The MySQLi extension is not available.' ,
280+ details : [ ] ,
281+ duration : 0 ,
282+ } ) ;
283+
284+ expect ( appendSpy ) . toHaveBeenCalledWith (
285+ expect . any ( String ) ,
286+ { file : '/app/tests/MyTest.php' , line : 1 } ,
287+ 'App\\Tests\\MyTest::test_skipped' ,
288+ ) ;
289+ } ) ;
290+ } ) ;
0 commit comments