22// Licensed under the MIT license.
33
44import { Location , MarkdownString , TestItem , TestMessage } from 'vscode' ;
5- import { INVOCATION_PREFIX } from '../../constants' ;
65import { dataCache , ITestItemData } from '../../controller/testItemDataCache' ;
76import { createTestItem , updateOrCreateTestItem } from '../../controller/utils' ;
87import { IJavaTestItem , IRunTestContext , TestKind , TestLevel } from '../../types' ;
98import { RunnerResultAnalyzer } from '../baseRunner/RunnerResultAnalyzer' ;
109import { findTestLocation , setTestState , TestResultState } from '../utils' ;
10+ import { JUnitTestPart } from '../../constants' ;
1111
1212
1313export class JUnitRunnerResultAnalyzer extends RunnerResultAnalyzer {
@@ -192,20 +192,13 @@ export class JUnitRunnerResultAnalyzer extends RunnerResultAnalyzer {
192192 }
193193
194194 protected getTestIdForJunit5Method ( message : string ) : string {
195- const classId : string = 'class:' ;
196- const nestedClassId : string = 'nested-class:' ;
197- const methodId : string = 'method:' ;
198- const testFactoryId : string = 'test-factory:' ;
199- // Property id is for jqwik
200- const propertyId : string = 'property:' ;
201- const testTemplateId : string = 'test-template:' ;
202-
203195 // We're expecting something like:
204196 // [engine:junit5]/[class:com.example.MyTest]/[method:myTest]/[test-template:myTest(String\, int)]
205197 const parts : string [ ] = message . split ( '/' ) ;
206198
207199 let className : string = '' ;
208200 let methodName : string = '' ;
201+ let InvocationSuffix : string = '' ;
209202
210203 if ( ! parts || parts . length === 0 ) {
211204 // The pattern doesn't match what we're expecting, so we'll go ahead and defer to the non JUnit5 method.
@@ -216,38 +209,44 @@ export class JUnitRunnerResultAnalyzer extends RunnerResultAnalyzer {
216209 // Remove the leading and trailing brackets.
217210 part = part . trim ( ) . replace ( / \[ / g, '' ) . replace ( / \] / g, '' ) ;
218211
219- if ( part . startsWith ( classId ) ) {
220- className = part . substring ( classId . length ) ;
221- } else if ( part . startsWith ( methodId ) ) {
222- const rawMethodName : string = part . substring ( methodId . length ) ;
212+ if ( part . startsWith ( JUnitTestPart . CLASS ) ) {
213+ className = part . substring ( JUnitTestPart . CLASS . length ) ;
214+ } else if ( part . startsWith ( JUnitTestPart . METHOD ) ) {
215+ const rawMethodName : string = part . substring ( JUnitTestPart . METHOD . length ) ;
223216 // If the method name exists then we want to include the '#' qualifier.
224217 methodName = `#${ this . getJUnit5MethodName ( rawMethodName ) } ` ;
225- } else if ( part . startsWith ( testFactoryId ) ) {
226- const rawMethodName : string = part . substring ( testFactoryId . length ) ;
218+ } else if ( part . startsWith ( JUnitTestPart . TEST_FACTORY ) ) {
219+ const rawMethodName : string = part . substring ( JUnitTestPart . TEST_FACTORY . length ) ;
227220 // If the method name exists then we want to include the '#' qualifier.
228221 methodName = `#${ this . getJUnit5MethodName ( rawMethodName ) } ` ;
229- } else if ( part . startsWith ( nestedClassId ) ) {
230- const nestedClassName : string = part . substring ( nestedClassId . length ) ;
222+ } else if ( part . startsWith ( JUnitTestPart . NESTED_CLASS ) ) {
223+ const nestedClassName : string = part . substring ( JUnitTestPart . NESTED_CLASS . length ) ;
231224 className = `${ className } $${ nestedClassName } ` ;
232- } else if ( part . startsWith ( testTemplateId ) ) {
233- const rawMethodName : string = part . substring ( testTemplateId . length )
225+ } else if ( part . startsWith ( JUnitTestPart . TEST_TEMPLATE ) ) {
226+ const rawMethodName : string = part . substring ( JUnitTestPart . TEST_TEMPLATE . length )
234227 . replace ( / \\ , / g, ',' )
235228 . replace ( / / g, '' ) ;
236229 // If the method name exists then we want to include the '#' qualifier.
237230 methodName = `#${ this . getJUnit5MethodName ( rawMethodName ) } ` ;
238- } else if ( part . startsWith ( propertyId ) ) {
239- const rawMethodName : string = part . substring ( propertyId . length )
231+ } else if ( part . startsWith ( JUnitTestPart . PROPERTY ) ) {
232+ const rawMethodName : string = part . substring ( JUnitTestPart . PROPERTY . length )
240233 . replace ( / \\ , / g, ',' )
241234 . replace ( / / g, '' ) ;
242235 // If the method name exists then we want to include the '#' qualifier.
243236 methodName = `#${ this . getJUnit5MethodName ( rawMethodName ) } ` ;
237+ } else if ( part . startsWith ( JUnitTestPart . TEST_TEMPLATE_INVOCATION ) ) {
238+ InvocationSuffix += `[${ part . substring ( JUnitTestPart . TEST_TEMPLATE_INVOCATION . length ) } ]` ;
239+ } else if ( part . startsWith ( JUnitTestPart . DYNAMIC_CONTAINER ) ) {
240+ InvocationSuffix += `[${ part . substring ( JUnitTestPart . DYNAMIC_CONTAINER . length ) } ]` ;
241+ } else if ( part . startsWith ( JUnitTestPart . DYNAMIC_TEST ) ) {
242+ InvocationSuffix += `[${ part . substring ( JUnitTestPart . DYNAMIC_TEST . length ) } ]` ;
244243 }
245244 } ) ;
246245
247246 if ( className ) {
248- return `${ this . projectName } @${ className } ${ methodName } ` ;
247+ return `${ this . projectName } @${ className } ${ methodName } ${ InvocationSuffix } ` ;
249248 } else {
250- return `${ this . projectName } @${ message } ` ;
249+ return `${ this . projectName } @${ message } ${ InvocationSuffix } ` ;
251250 }
252251 }
253252
@@ -354,8 +353,8 @@ export class JUnitRunnerResultAnalyzer extends RunnerResultAnalyzer {
354353 const parent : TestItem | undefined = parentInfo ?. testItem ;
355354 if ( parent ) {
356355 const parentData : ITestItemData | undefined = dataCache . get ( parent ) ;
357- if ( parentData ?. testLevel === TestLevel . Method ) {
358- testItem = this . enlistDynamicMethodToTestMapping ( testItem , parent , parentData , displayName , uniqueId ) ;
356+ if ( parentData ?. testLevel === TestLevel . Method || parentData ?. testLevel === TestLevel . Invocation ) {
357+ testItem = this . enlistDynamicMethodToTestMapping ( testId , parent , parentData , displayName , uniqueId ) ;
359358 }
360359 }
361360 } else {
@@ -376,7 +375,7 @@ export class JUnitRunnerResultAnalyzer extends RunnerResultAnalyzer {
376375 jdtHandler : '' ,
377376 fullName : testId . substr ( testId . indexOf ( '@' ) + 1 ) ,
378377 label : this . getTestMethodName ( displayName ) ,
379- id : ` ${ INVOCATION_PREFIX } ${ testId } ` ,
378+ id : testId ,
380379 projectName : this . projectName ,
381380 testKind : this . testContext . kind ,
382381 testLevel : TestLevel . Invocation ,
@@ -412,25 +411,23 @@ export class JUnitRunnerResultAnalyzer extends RunnerResultAnalyzer {
412411 }
413412
414413 // Leaving this public so that it can be mocked when testing.
415- public enlistDynamicMethodToTestMapping ( testItem : TestItem | undefined , parent : TestItem , parentData : ITestItemData , displayName : string , uniqueId : string | undefined ) : TestItem {
416- testItem = updateOrCreateTestItem ( parent , {
414+ public enlistDynamicMethodToTestMapping ( testId : string , parent : TestItem , parentData : ITestItemData , displayName : string , uniqueId : string | undefined ) : TestItem {
415+ return updateOrCreateTestItem ( parent , {
417416 children : [ ] ,
418417 uri : parent . uri ?. toString ( ) ,
419418 range : parent . range ,
420419 jdtHandler : parentData . jdtHandler ,
421420 fullName : parentData . fullName ,
422421 label : this . getTestMethodName ( displayName ) ,
423422 // prefer uniqueId, as it does not change when re-running only a single invocation:
424- id : uniqueId ? `${ INVOCATION_PREFIX } ${ uniqueId } `
425- : `${ INVOCATION_PREFIX } ${ parent . id } [#${ parent . children . size + 1 } ]` ,
423+ id : uniqueId ? uniqueId : testId ,
426424 projectName : parentData . projectName ,
427425 testKind : parentData . testKind ,
428426 testLevel : TestLevel . Invocation ,
429427 uniqueId,
430428 // We will just create a string padded with the character "a" to provide easy sorting.
431429 sortText : '' . padStart ( parent . children . size + 1 , 'a' )
432430 } ) ;
433- return testItem ;
434431 }
435432
436433 private async tryAppendMessage ( item : TestItem , testMessage : TestMessage , testState : TestResultState ) : Promise < void > {
@@ -440,15 +437,12 @@ export class JUnitRunnerResultAnalyzer extends RunnerResultAnalyzer {
440437 testMessage . location = new Location ( item . uri , item . range ) ;
441438 } else {
442439 let id : string = item . id ;
443- if ( id . startsWith ( INVOCATION_PREFIX ) ) {
444- id = id . substring ( INVOCATION_PREFIX . length ) ;
445- if ( this . testContext . kind === TestKind . JUnit ) {
446- // change test[0] -> test
447- // to fix: https://github.com/microsoft/vscode-java-test/issues/1296
448- const indexOfParameterizedTest : number = id . lastIndexOf ( '[' ) ;
449- if ( indexOfParameterizedTest > - 1 ) {
450- id = id . substring ( 0 , id . lastIndexOf ( '[' ) ) ;
451- }
440+ if ( this . testContext . kind === TestKind . JUnit ) {
441+ // change test[0] -> test
442+ // to fix: https://github.com/microsoft/vscode-java-test/issues/1296
443+ const indexOfParameterizedTest : number = id . lastIndexOf ( '[' ) ;
444+ if ( indexOfParameterizedTest > - 1 ) {
445+ id = id . substring ( 0 , id . lastIndexOf ( '[' ) ) ;
452446 }
453447 }
454448 const location : Location | undefined = await findTestLocation ( id ) ;
0 commit comments