@@ -5,12 +5,12 @@ import picomatch from "picomatch";
55import * as vscode from "vscode" ;
66import { coverageContext } from "./coverage" ;
77import { DisposableStore , MutableDisposable } from "./disposable" ;
8+ import { ExtensionConfig } from './extension-config' ;
89import { last } from "./iterable" ;
910import { ICreateOpts , ItemType , getContainingItemsForFile , testMetadata } from "./metadata" ;
1011import { IParsedNode , parseSource } from "./parsing" ;
1112import { RunHandler , TestRunner } from "./runner" ;
1213import { ISourceMapMaintainer , SourceMapStore } from "./source-map-store" ;
13- import { ExtensionConfig } from './extension-config' ;
1414
1515const diagnosticCollection = vscode . languages . createDiagnosticCollection ( "nodejs-testing-dupes" ) ;
1616
@@ -185,20 +185,31 @@ export class Controller {
185185 const add = (
186186 parent : vscode . TestItem ,
187187 node : IParsedNode ,
188+ id : string ,
188189 start : vscode . Location ,
189190 end : vscode . Location ,
190191 ) : vscode . TestItem => {
191- let item = parent . children . get ( node . name ) ;
192+ let item = parent . children . get ( id ) ;
192193 if ( ! item ) {
193- item = this . ctrl . createTestItem ( node . name , node . name , start . uri ) ;
194+ item = this . ctrl . createTestItem ( id , node . name , start . uri ) ;
194195 testMetadata . set ( item , { type : ItemType . Test } ) ;
195196 parent . children . add ( item ) ;
196197 }
197198 item . range = new vscode . Range ( start . range . start , end . range . end ) ;
198199
199200 const seen = new Map < string , vscode . TestItem > ( ) ;
201+ const level2Dupes = new Map < string , vscode . TestItem > ( ) ;
202+ for ( const [ , sibling ] of parent . children ) {
203+ if ( sibling . id == item . id || sibling . label !== node . name ) {
204+ continue ;
205+ }
206+
207+ for ( const [ , cousin ] of sibling . children ) {
208+ level2Dupes . set ( cousin . label , cousin ) ;
209+ }
210+ }
200211 for ( const child of node . children ) {
201- const existing = seen . get ( child . name ) ;
212+ const existing = seen . get ( child . name ) || level2Dupes . get ( child . name ) ;
202213 const start = sourceMap . originalPositionFor (
203214 child . location . start . line ,
204215 child . location . start . column ,
@@ -212,7 +223,7 @@ export class Controller {
212223 continue ;
213224 }
214225
215- seen . set ( child . name , add ( item , child , start , end ) ) ;
226+ seen . set ( child . name , add ( item , child , child . name , start , end ) ) ;
216227 }
217228
218229 for ( const [ id ] of item . children ) {
@@ -228,6 +239,7 @@ export class Controller {
228239 // source file. This is probably a good assumption. Likewise we assume that a single
229240 // a single describe/test is not split between different files.
230241 const newTestsInFile = new Map < string , vscode . TestItem > ( ) ;
242+ let nId : number = 0 ;
231243 for ( const node of tree ) {
232244 const start = sourceMap . originalPositionFor (
233245 node . location . start . line ,
@@ -236,7 +248,14 @@ export class Controller {
236248 const end = sourceMap . originalPositionFor ( node . location . end . line , node . location . end . column ) ;
237249 const file = last ( this . getContainingItemsForFile ( start . uri , { compiledFile : uri } ) ) ! . item ! ;
238250 diagnosticCollection . delete ( start . uri ) ;
239- newTestsInFile . set ( node . name , add ( file , node , start , end ) ) ;
251+ if ( newTestsInFile . has ( node . name ) && [ "describe" , "suite" ] . includes ( node . fn ) ) {
252+ const id = `${ node . name } #${ nId ++ } ` ;
253+ newTestsInFile . set ( id , add ( file , node , id , start , end ) ) ;
254+ }
255+ else {
256+ nId = 0 ;
257+ newTestsInFile . set ( node . name , add ( file , node , node . name , start , end ) ) ;
258+ }
240259 }
241260
242261 if ( previous ) {
0 commit comments