@@ -492,14 +492,27 @@ class TestCase {
492492
493493// Validators
494494const queueSizeStore = { } ;
495+ const extractedValues = { } ;
495496
496497function extractQueueSize ( responses ) {
497498 const allText = responses . map ( r => r . text ) . join ( ' ' ) ;
499+ // Match "X tracks" pattern first (more specific)
500+ const tracksMatch = allText . match ( / ( \d + ) \s * t r a c k / i) ;
501+ if ( tracksMatch ) return parseInt ( tracksMatch [ 1 ] , 10 ) ;
502+ // Fall back to first number
498503 const match = allText . match ( / \b ( \d + ) \b / ) ;
499504 if ( ! match ) return null ;
500505 return parseInt ( match [ 1 ] , 10 ) ;
501506}
502507
508+ function extractTrackCountFromResponse ( responses ) {
509+ const allText = responses . map ( r => r . text ) . join ( ' ' ) ;
510+ // Match patterns like "(150 tracks)" or "150 tracks"
511+ const match = allText . match ( / \( ( \d + ) \s * t r a c k s ? \) / i) || allText . match ( / ( \d + ) \s * t r a c k s ? / i) ;
512+ if ( ! match ) return null ;
513+ return parseInt ( match [ 1 ] , 10 ) ;
514+ }
515+
503516const validators = {
504517 containsText : ( text ) => ( responses ) => {
505518 const allText = responses . map ( r => r . text ) . join ( ' ' ) ;
@@ -568,6 +581,69 @@ const validators = {
568581 }
569582 if ( size >= baseline + minIncrease ) return true ;
570583 return `Expected queue size to increase by ${ minIncrease } from ${ baseline } , got ${ size } ` ;
584+ } ,
585+
586+ // Verify queue size increased by EXACTLY N (not double, not less)
587+ queueSizeIncreaseExactly : ( key , exactIncrease ) => ( responses ) => {
588+ const size = extractQueueSize ( responses ) ;
589+ if ( size === null ) return 'Could not parse queue size from response' ;
590+ const baseline = queueSizeStore [ key ] ;
591+ if ( baseline === undefined || baseline === null ) {
592+ return `No baseline queue size recorded for "${ key } "` ;
593+ }
594+ const actualIncrease = size - baseline ;
595+
596+ // Exact match - no output
597+ if ( actualIncrease === exactIncrease ) return true ;
598+
599+ // Within tolerance (90-100%) - warning but pass
600+ const tolerance = Math . floor ( exactIncrease * 0.9 ) ;
601+ if ( actualIncrease >= tolerance && actualIncrease < exactIncrease ) {
602+ console . log ( ` ⚠️ WARNING: Queue increased by ${ actualIncrease } (expected ${ exactIncrease } , baseline: ${ baseline } → ${ size } )` ) ;
603+ return true ;
604+ }
605+
606+ // Outside tolerance - fail
607+ return `❌ FAIL: Queue increased by ${ actualIncrease } (expected exactly ${ exactIncrease } , baseline: ${ baseline } → ${ size } )` ;
608+ } ,
609+
610+ // Extract and store track count from search results (e.g., "(50 tracks)")
611+ extractAndStoreTrackCount : ( key ) => ( responses ) => {
612+ const count = extractTrackCountFromResponse ( responses ) ;
613+ if ( count === null ) return 'Could not extract track count from response' ;
614+ extractedValues [ key ] = count ;
615+ return true ;
616+ } ,
617+
618+ // Verify queue increased by stored track count (with tolerance for duplicates/blacklist)
619+ queueSizeIncreasedByStoredCount : ( baselineKey , countKey , tolerancePercent = 10 ) => ( responses ) => {
620+ const size = extractQueueSize ( responses ) ;
621+ if ( size === null ) return 'Could not parse queue size from response' ;
622+ const baseline = queueSizeStore [ baselineKey ] ;
623+ const expectedCount = extractedValues [ countKey ] ;
624+ if ( baseline === undefined ) return `No baseline recorded for "${ baselineKey } "` ;
625+ if ( expectedCount === undefined ) return `No track count recorded for "${ countKey } "` ;
626+
627+ const actualIncrease = size - baseline ;
628+ const minExpected = Math . floor ( expectedCount * ( 1 - tolerancePercent / 100 ) ) ;
629+ const maxExpected = expectedCount ; // Should not exceed expected (no doubling!)
630+
631+ // Exact match - no output
632+ if ( actualIncrease === expectedCount ) return true ;
633+
634+ // Within tolerance but not exact - warning but pass
635+ if ( actualIncrease >= minExpected && actualIncrease < expectedCount ) {
636+ console . log ( ` ⚠️ WARNING: Queue increased by ${ actualIncrease } (expected ${ expectedCount } , baseline: ${ baseline } → ${ size } , tolerance: ${ minExpected } -${ maxExpected } )` ) ;
637+ return true ;
638+ }
639+
640+ // Exceeded expected (possible doubling bug) - fail
641+ if ( actualIncrease > maxExpected ) {
642+ return `❌ FAIL: Queue increased by ${ actualIncrease } but expected max ${ maxExpected } - possible DUPLICATE QUEUEING BUG! (baseline: ${ baseline } → ${ size } )` ;
643+ }
644+
645+ // Below minimum (too many filtered) - fail
646+ return `❌ FAIL: Queue increased by ${ actualIncrease } , expected ${ minExpected } -${ maxExpected } (based on ${ expectedCount } tracks, baseline: ${ baseline } → ${ size } )` ;
571647 }
572648} ;
573649
@@ -730,6 +806,17 @@ const testSuiteArray = [
730806 // PHASE 4: BUILD UP THE QUEUE (add tracks for later tests)
731807 // ═══════════════════════════════════════════════════════════════════
732808
809+ // Get baseline queue size before adding tracks
810+ new TestCase (
811+ 'Queue Size - Initial Baseline' ,
812+ 'size' ,
813+ validators . and (
814+ validators . responseCount ( 1 , 2 ) ,
815+ validators . recordQueueSize ( 'initialBaseline' )
816+ ) ,
817+ 4
818+ ) ,
819+
733820 new TestCase (
734821 'Add Track #1 - Foo Fighters' ,
735822 'add Foo Fighters - Best Of You' ,
@@ -744,6 +831,18 @@ const testSuiteArray = [
744831 7
745832 ) ,
746833
834+ // Verify exactly 1 track was added
835+ new TestCase (
836+ 'Queue Size - After Track #1 (+1)' ,
837+ 'size' ,
838+ validators . and (
839+ validators . responseCount ( 1 , 2 ) ,
840+ validators . queueSizeIncreaseExactly ( 'initialBaseline' , 1 ) ,
841+ validators . recordQueueSize ( 'afterTrack1' )
842+ ) ,
843+ 4
844+ ) ,
845+
747846 new TestCase (
748847 'Add Track - Duplicate Detection' ,
749848 'add Foo Fighters - Best Of You' ,
@@ -768,6 +867,18 @@ const testSuiteArray = [
768867 7
769868 ) ,
770869
870+ // Verify exactly 1 more track added (total +2 from initial)
871+ new TestCase (
872+ 'Queue Size - After Track #2 (+1)' ,
873+ 'size' ,
874+ validators . and (
875+ validators . responseCount ( 1 , 2 ) ,
876+ validators . queueSizeIncreaseExactly ( 'afterTrack1' , 1 ) ,
877+ validators . recordQueueSize ( 'afterTrack2' )
878+ ) ,
879+ 4
880+ ) ,
881+
771882 new TestCase (
772883 'Add Track #3 - Queen' ,
773884 'add Queen - Bohemian Rhapsody' ,
@@ -796,6 +907,21 @@ const testSuiteArray = [
796907 7
797908 ) ,
798909
910+ // Search album first to get track count
911+ new TestCase (
912+ 'Search Album - Abbey Road (get track count)' ,
913+ 'searchalbum abbey road' ,
914+ validators . and (
915+ validators . responseCount ( 1 , 2 ) ,
916+ validators . or (
917+ validators . containsText ( 'Beatles' ) ,
918+ validators . containsText ( 'Abbey Road' )
919+ ) ,
920+ validators . extractAndStoreTrackCount ( 'abbeyRoadTracks' )
921+ ) ,
922+ 5
923+ ) ,
924+
799925 new TestCase (
800926 'Queue Size - Baseline Before Album' ,
801927 'size' ,
@@ -820,17 +946,30 @@ const testSuiteArray = [
820946 10
821947 ) ,
822948
949+ // Verify album tracks were added (not doubled!)
823950 new TestCase (
824- 'Queue Size - After Album' ,
951+ 'Queue Size - After Album (verify no doubling) ' ,
825952 'size' ,
826953 validators . and (
827954 validators . responseCount ( 1 , 2 ) ,
828- validators . queueSizeIncreaseFrom ( 'beforeAlbum' , 1 ) ,
955+ validators . queueSizeIncreasedByStoredCount ( 'beforeAlbum' , 'abbeyRoadTracks' , 20 ) ,
829956 validators . recordQueueSize ( 'beforePlaylist' )
830957 ) ,
831958 4
832959 ) ,
833960
961+ // Search playlist first to get track count
962+ new TestCase (
963+ 'Search Playlist - Rock Classics (get track count)' ,
964+ 'searchplaylist rock classics' ,
965+ validators . and (
966+ validators . responseCount ( 1 , 2 ) ,
967+ validators . matchesRegex ( / p l a y l i s t | t r a c k s | \d + / i) ,
968+ validators . extractAndStoreTrackCount ( 'rockClassicsTracks' )
969+ ) ,
970+ 5
971+ ) ,
972+
834973 new TestCase (
835974 'Add Playlist - Rock Classics' ,
836975 'addplaylist rock classics' ,
@@ -845,12 +984,13 @@ const testSuiteArray = [
845984 12
846985 ) ,
847986
987+ // Verify playlist tracks added (not doubled!)
848988 new TestCase (
849- 'Queue Size - After Playlist' ,
989+ 'Queue Size - After Playlist (verify no doubling) ' ,
850990 'size' ,
851991 validators . and (
852992 validators . responseCount ( 1 , 2 ) ,
853- validators . queueSizeIncreaseFrom ( 'beforePlaylist' , 1 )
993+ validators . queueSizeIncreasedByStoredCount ( 'beforePlaylist' , 'rockClassicsTracks' , 20 )
854994 ) ,
855995 4
856996 ) ,
0 commit comments