@@ -297,6 +297,31 @@ const files = {
297297 } ,
298298 ] ,
299299 8 : [ { filename : 'app/1.js' } , { filename : 'app/2.js' } , { filename : 'app/3.js' } ] ,
300+ 9 : [
301+ { filename : 'src/index.ts' } ,
302+ { filename : 'docs/readme.md' } ,
303+ ] ,
304+ 10 : [ { filename : 'lib/index.ts' } ] ,
305+ 11 : [
306+ { filename : 'app/feature.ts' } ,
307+ { filename : 'docs/readme.md' } ,
308+ ] ,
309+ 12 : [
310+ { filename : 'app/feature.ts' } ,
311+ { filename : 'app/helpers.ts' } ,
312+ { filename : 'docs/readme.md' } ,
313+ ] ,
314+ 13 : [
315+ { filename : 'src/index.ts' } ,
316+ { filename : 'docs/readme.md' } ,
317+ ] ,
318+ 14 : [
319+ { filename : 'lib/a.ts' } ,
320+ { filename : 'lib/b.ts' } ,
321+ { filename : 'misc/test.ts' } ,
322+ ] ,
323+ 15 : [ ] ,
324+ 16 : [ { filename : 'docs/readme.md' } ] ,
300325} ;
301326
302327describe ( 'basic' , ( ) => {
@@ -412,7 +437,7 @@ describe('complex', () => {
412437 } ,
413438 } ;
414439 const labels = await getMatchedLabels ( complex ) ;
415- expect ( labels ) . toEqual ( [ 'any-app' , 'NEQ1' , 'L' ] ) ;
440+ expect ( labels ) . toEqual ( [ 'all-app' , ' any-app', 'none-app' , 'all-any' , ' NEQ1', 'L' , 'mixed-1 '] ) ;
416441 } ) ;
417442
418443 it ( '2 should have complex labels' , async function ( ) {
@@ -432,7 +457,7 @@ describe('complex', () => {
432457 } ,
433458 } ;
434459 const labels = await getMatchedLabels ( complex ) ;
435- expect ( labels ) . toEqual ( [ 'any-app' , 'NEQ1' , 'M' ] ) ;
460+ expect ( labels ) . toEqual ( [ 'all-app' , ' any-app', 'none-app' , 'all-any' , ' NEQ1', 'M' , 'mixed-1 '] ) ;
436461 } ) ;
437462
438463 it ( '4 should have complex labels' , async function ( ) {
@@ -485,3 +510,215 @@ describe('complex', () => {
485510 expect ( labels ) . toEqual ( [ 'all-app' , 'any-app' , 'NEQ1' , 'M' , 'mixed-1' ] ) ;
486511 } ) ;
487512} ) ;
513+
514+ describe ( 'all matcher behavior' , ( ) => {
515+ const globsConfig : Config = {
516+ version : 'v1' ,
517+ labels : [
518+ {
519+ label : 'src-only' ,
520+ matcher : {
521+ files : {
522+ all : [ 'src/**' ] ,
523+ } ,
524+ } ,
525+ } ,
526+ ] ,
527+ } ;
528+
529+ beforeEach ( ( ) => {
530+ jest . spyOn ( github . context , 'repo' , 'get' ) . mockImplementation ( ( ) => {
531+ return {
532+ owner : 'owner-name' ,
533+ repo : 'repo-name' ,
534+ } ;
535+ } ) ;
536+ } ) ;
537+
538+ afterAll ( ( ) => {
539+ jest . restoreAllMocks ( ) ;
540+ } ) ;
541+
542+ it ( 'matches when each glob is satisfied by at least one file' , async function ( ) {
543+ github . context . payload = {
544+ pull_request : {
545+ number : 9 ,
546+ } ,
547+ } ;
548+
549+ const labels = await getMatchedLabels ( globsConfig ) ;
550+ expect ( labels ) . toEqual ( [ 'src-only' ] ) ;
551+ } ) ;
552+
553+ it ( 'does not match when glob does not match any files' , async function ( ) {
554+ github . context . payload = {
555+ pull_request : {
556+ number : 10 ,
557+ } ,
558+ } ;
559+
560+ const labels = await getMatchedLabels ( globsConfig ) ;
561+ expect ( labels ) . toEqual ( [ ] ) ;
562+ } ) ;
563+ } ) ;
564+
565+ describe ( 'count matcher scoping' , ( ) => {
566+ const scopedCountConfig : Config = {
567+ version : 'v1' ,
568+ labels : [
569+ {
570+ label : 'app-lte-1' ,
571+ matcher : {
572+ files : {
573+ any : [ 'app/**' ] ,
574+ count : { lte : 1 } ,
575+ } ,
576+ } ,
577+ } ,
578+ {
579+ label : 'app-eq-1' ,
580+ matcher : {
581+ files : {
582+ any : [ 'app/**' ] ,
583+ count : { eq : 1 } ,
584+ } ,
585+ } ,
586+ } ,
587+ {
588+ label : 'src-eq-1' ,
589+ matcher : {
590+ files : {
591+ all : [ 'src/**' ] ,
592+ count : { eq : 1 } ,
593+ } ,
594+ } ,
595+ } ,
596+ {
597+ label : 'lib-eq-2' ,
598+ matcher : {
599+ files : {
600+ any : [ 'lib/**' ] ,
601+ all : [ 'lib/**' ] ,
602+ count : { eq : 2 } ,
603+ } ,
604+ } ,
605+ } ,
606+ ] ,
607+ } ;
608+
609+ beforeEach ( ( ) => {
610+ jest . spyOn ( github . context , 'repo' , 'get' ) . mockImplementation ( ( ) => {
611+ return {
612+ owner : 'owner-name' ,
613+ repo : 'repo-name' ,
614+ } ;
615+ } ) ;
616+ } ) ;
617+
618+ afterAll ( ( ) => {
619+ jest . restoreAllMocks ( ) ;
620+ } ) ;
621+
622+ it ( 'counts only files matching the any globs' , async function ( ) {
623+ github . context . payload = {
624+ pull_request : {
625+ number : 11 ,
626+ } ,
627+ } ;
628+
629+ const labels = await getMatchedLabels ( scopedCountConfig ) ;
630+ expect ( labels ) . toEqual ( [ 'app-lte-1' , 'app-eq-1' ] ) ;
631+ } ) ;
632+
633+ it ( 'ignores unrelated files when evaluating counts' , async function ( ) {
634+ github . context . payload = {
635+ pull_request : {
636+ number : 12 ,
637+ } ,
638+ } ;
639+
640+ const labels = await getMatchedLabels ( scopedCountConfig ) ;
641+ expect ( labels ) . toEqual ( [ ] ) ;
642+ } ) ;
643+
644+ it ( 'uses files matching all globs for counts' , async function ( ) {
645+ github . context . payload = {
646+ pull_request : {
647+ number : 13 ,
648+ } ,
649+ } ;
650+
651+ const labels = await getMatchedLabels ( scopedCountConfig ) ;
652+ expect ( labels ) . toEqual ( [ 'src-eq-1' ] ) ;
653+ } ) ;
654+
655+ it ( 'reuses glob-matched files for count checks' , async function ( ) {
656+ github . context . payload = {
657+ pull_request : {
658+ number : 14 ,
659+ } ,
660+ } ;
661+
662+ const labels = await getMatchedLabels ( scopedCountConfig ) ;
663+ expect ( labels ) . toEqual ( [ 'lib-eq-2' ] ) ;
664+ } ) ;
665+ } ) ;
666+
667+ describe ( 'zero count handling' , ( ) => {
668+ const zeroCountConfig : Config = {
669+ version : 'v1' ,
670+ labels : [
671+ {
672+ label : 'no-files-eq' ,
673+ matcher : {
674+ files : {
675+ count : { eq : 0 } ,
676+ } ,
677+ } ,
678+ } ,
679+ {
680+ label : 'no-files-lte' ,
681+ matcher : {
682+ files : {
683+ count : { lte : 0 } ,
684+ } ,
685+ } ,
686+ } ,
687+ ] ,
688+ } ;
689+
690+ beforeEach ( ( ) => {
691+ jest . spyOn ( github . context , 'repo' , 'get' ) . mockImplementation ( ( ) => {
692+ return {
693+ owner : 'owner-name' ,
694+ repo : 'repo-name' ,
695+ } ;
696+ } ) ;
697+ } ) ;
698+
699+ afterAll ( ( ) => {
700+ jest . restoreAllMocks ( ) ;
701+ } ) ;
702+
703+ it ( 'applies labels when no files are present' , async function ( ) {
704+ github . context . payload = {
705+ pull_request : {
706+ number : 15 ,
707+ } ,
708+ } ;
709+
710+ const labels = await getMatchedLabels ( zeroCountConfig ) ;
711+ expect ( labels ) . toEqual ( [ 'no-files-eq' , 'no-files-lte' ] ) ;
712+ } ) ;
713+
714+ it ( 'does not apply labels when files exceed zero thresholds' , async function ( ) {
715+ github . context . payload = {
716+ pull_request : {
717+ number : 16 ,
718+ } ,
719+ } ;
720+
721+ const labels = await getMatchedLabels ( zeroCountConfig ) ;
722+ expect ( labels ) . toEqual ( [ ] ) ;
723+ } ) ;
724+ } ) ;
0 commit comments