@@ -195,4 +195,140 @@ describe('matchGlob', () => {
195195 expect ( matchGlob ( '*.ts' , 'file.js' ) ) . toBe ( false ) ;
196196 } ) ;
197197 } ) ;
198+
199+ describe ( 'consecutive and adjacent wildcards' , ( ) => {
200+ it ( 'should handle ** same as *' , ( ) => {
201+ expect ( matchGlob ( 'index.**.ts' , 'index.routing.ts' ) ) . toBe ( true ) ;
202+ } ) ;
203+
204+ it ( 'should handle ** matching empty text segment' , ( ) => {
205+ expect ( matchGlob ( 'index.**.ts' , 'index..ts' ) ) . toBe ( true ) ;
206+ } ) ;
207+
208+ it ( 'should handle *? requiring at least one char' , ( ) => {
209+ expect ( matchGlob ( '*?.ts' , 'a.ts' ) ) . toBe ( true ) ;
210+ } ) ;
211+
212+ it ( 'should not match *? when no char precedes dot' , ( ) => {
213+ expect ( matchGlob ( '*?.ts' , '.ts' ) ) . toBe ( false ) ;
214+ } ) ;
215+
216+ it ( 'should handle ?* matching one or more chars' , ( ) => {
217+ expect ( matchGlob ( '?*.ts' , 'ab.ts' ) ) . toBe ( true ) ;
218+ } ) ;
219+
220+ it ( 'should handle ?* matching exactly one char' , ( ) => {
221+ expect ( matchGlob ( '?*.ts' , 'a.ts' ) ) . toBe ( true ) ;
222+ } ) ;
223+
224+ it ( 'should not match ?* against zero chars' , ( ) => {
225+ expect ( matchGlob ( '?*.ts' , '.ts' ) ) . toBe ( false ) ;
226+ } ) ;
227+ } ) ;
228+
229+ describe ( 'greedy star matching' , ( ) => {
230+ it ( 'should match with multiple possible split points' , ( ) => {
231+ expect ( matchGlob ( '*.*.ts' , 'a.b.ts' ) ) . toBe ( true ) ;
232+ } ) ;
233+
234+ it ( 'should handle greedy * with three dot segments' , ( ) => {
235+ expect ( matchGlob ( '*.*.ts' , 'a.b.c.ts' ) ) . toBe ( true ) ;
236+ } ) ;
237+
238+ it ( 'should handle * greedily consuming dots' , ( ) => {
239+ expect ( matchGlob ( '*.*' , 'index.routing.ts' ) ) . toBe ( true ) ;
240+ } ) ;
241+
242+ it ( 'should match when * must split across dots' , ( ) => {
243+ expect ( matchGlob ( 'index.*.*.ts' , 'index.routing.lazy.ts' ) ) . toBe ( true ) ;
244+ } ) ;
245+
246+ it ( 'should not match when insufficient segments for multiple *' , ( ) => {
247+ expect ( matchGlob ( 'index.*.*.ts' , 'index.routing.ts' ) ) . toBe ( false ) ;
248+ } ) ;
249+ } ) ;
250+
251+ describe ( 'single-character pattern edge cases' , ( ) => {
252+ it ( 'should match single ? against single char' , ( ) => {
253+ expect ( matchGlob ( '?' , 'a' ) ) . toBe ( true ) ;
254+ } ) ;
255+
256+ it ( 'should not match single ? against empty string' , ( ) => {
257+ expect ( matchGlob ( '?' , '' ) ) . toBe ( false ) ;
258+ } ) ;
259+
260+ it ( 'should not match single ? against two chars' , ( ) => {
261+ expect ( matchGlob ( '?' , 'ab' ) ) . toBe ( false ) ;
262+ } ) ;
263+
264+ it ( 'should match ?? against exactly two chars' , ( ) => {
265+ expect ( matchGlob ( '??' , 'ab' ) ) . toBe ( true ) ;
266+ } ) ;
267+
268+ it ( 'should not match ?? against one char' , ( ) => {
269+ expect ( matchGlob ( '??' , 'a' ) ) . toBe ( false ) ;
270+ } ) ;
271+
272+ it ( 'should not match ?? against three chars' , ( ) => {
273+ expect ( matchGlob ( '??' , 'abc' ) ) . toBe ( false ) ;
274+ } ) ;
275+ } ) ;
276+
277+ describe ( 'boundary and length edge cases' , ( ) => {
278+ it ( 'should not match when pattern is longer than text' , ( ) => {
279+ expect ( matchGlob ( 'index.routing.ts' , 'index.ts' ) ) . toBe ( false ) ;
280+ } ) ;
281+
282+ it ( 'should not match when text is longer than pattern' , ( ) => {
283+ expect ( matchGlob ( 'index.ts' , 'index.routing.ts' ) ) . toBe ( false ) ;
284+ } ) ;
285+
286+ it ( 'should match pattern with wildcard at both ends' , ( ) => {
287+ expect ( matchGlob ( '*index*' , 'my-index-file' ) ) . toBe ( true ) ;
288+ } ) ;
289+
290+ it ( 'should match long filename with simple glob' , ( ) => {
291+ expect (
292+ matchGlob ( 'index.*.ts' , 'index.very-long-feature-name.ts' ) ,
293+ ) . toBe ( true ) ;
294+ } ) ;
295+
296+ it ( 'should handle text that is a prefix of the pattern' , ( ) => {
297+ expect ( matchGlob ( 'index.routing.ts' , 'index.routing' ) ) . toBe ( false ) ;
298+ } ) ;
299+
300+ it ( 'should handle text that is a suffix of the pattern' , ( ) => {
301+ expect ( matchGlob ( 'routing.ts' , 'index.routing.ts' ) ) . toBe ( false ) ;
302+ } ) ;
303+ } ) ;
304+
305+ describe ( 'encapsulationPattern reuse scenarios' , ( ) => {
306+ it ( 'should match path-like patterns with *' , ( ) => {
307+ expect ( matchGlob ( 'public-*.ts' , 'public-api.ts' ) ) . toBe ( true ) ;
308+ } ) ;
309+
310+ it ( 'should match exposed file pattern' , ( ) => {
311+ expect ( matchGlob ( '*.component.ts' , 'user.component.ts' ) ) . toBe ( true ) ;
312+ } ) ;
313+
314+ it ( 'should not match private file against public pattern' , ( ) => {
315+ expect ( matchGlob ( '*.component.ts' , 'user.service.ts' ) ) . toBe ( false ) ;
316+ } ) ;
317+
318+ it ( 'should match with leading underscore convention' , ( ) => {
319+ expect ( matchGlob ( '_*.ts' , '_internal.ts' ) ) . toBe ( true ) ;
320+ } ) ;
321+
322+ it ( 'should not match non-underscore file against underscore pattern' , ( ) => {
323+ expect ( matchGlob ( '_*.ts' , 'internal.ts' ) ) . toBe ( false ) ;
324+ } ) ;
325+
326+ it ( 'should match feature module barrel with question mark' , ( ) => {
327+ expect ( matchGlob ( 'index.?.ts' , 'index.a.ts' ) ) . toBe ( true ) ;
328+ } ) ;
329+
330+ it ( 'should not match multi-char segment against single ?' , ( ) => {
331+ expect ( matchGlob ( 'index.?.ts' , 'index.routing.ts' ) ) . toBe ( false ) ;
332+ } ) ;
333+ } ) ;
198334} ) ;
0 commit comments