@@ -5,45 +5,36 @@ import {
55 opPlayer ,
66 sleep ,
77 getPlayerPinCount ,
8- getAllPlayerPins ,
98 clearPlayerPins ,
109 closeDatabase
1110} from './helpers'
1211
13- describe ( 'Pin Cache Behavior' , ( ) => {
12+ describe ( 'Pin Rate Limiting Behavior' , ( ) => {
1413 let playerBot : TestBot
1514
16- beforeAll ( async ( ) => {
17- playerBot = await createBot ( 'PinCachePlayer' )
18- await sleep ( 2000 )
19- await opPlayer ( 'PinCachePlayer' )
20- await sleep ( 500 )
21- await clearPlayerPins ( )
22- } )
23-
2415 afterAll ( async ( ) => {
2516 await playerBot ?. disconnect ( )
2617 await disconnectRcon ( )
2718 await closeDatabase ( )
2819 } )
2920
30- beforeEach ( async ( ) => {
31- await clearPlayerPins ( )
21+ test ( 'rate limit prevents rapid pin generation' , async ( ) => {
22+ playerBot = await createBot ( 'RateLimitTest' )
23+ await sleep ( 2000 )
24+ await opPlayer ( 'RateLimitTest' )
3225 await sleep ( 500 )
33- } )
3426
35- test ( 'same pin is returned within 5-minute cache window' , async ( ) => {
36- // First /bmpin call
27+ // First /bmpin call - should succeed
3728 playerBot . clearSystemMessages ( )
3829 await playerBot . sendChat ( '/bmpin' )
3930
40- // Wait for the expiry message first
31+ // Wait for the expiry message (indicates success)
4132 const firstResponse = await playerBot . waitForSystemMessage ( 'expires' , 10000 )
4233 console . log ( `First call - Received: ${ firstResponse . message } ` )
4334
4435 await sleep ( 500 )
4536
46- // Get all system messages and find the 6-digit pin
37+ // Get the first pin
4738 const firstMessages = playerBot . getSystemMessages ( )
4839 let actualFirstPin : string | undefined
4940 for ( const msg of firstMessages ) {
@@ -54,84 +45,83 @@ describe('Pin Cache Behavior', () => {
5445 }
5546 }
5647 console . log ( `First call - Actual pin: ${ actualFirstPin ?? 'not found' } ` )
48+ expect ( actualFirstPin ) . toBeDefined ( )
5749
5850 await sleep ( 1000 )
5951
60- // Second /bmpin call ( should return cached pin)
52+ // Second /bmpin call immediately - should be rate limited
6153 playerBot . clearSystemMessages ( )
6254 await playerBot . sendChat ( '/bmpin' )
6355
64- const secondResponse = await playerBot . waitForSystemMessage ( 'expires' , 10000 )
65- console . log ( `Second call - Received: ${ secondResponse . message } ` )
56+ // Should receive rate limit message
57+ const rateLimitResponse = await playerBot . waitForSystemMessage ( 'wait' , 10000 )
58+ console . log ( `Second call - Rate limit message: ${ rateLimitResponse . message } ` )
6659
67- await sleep ( 500 )
60+ expect ( rateLimitResponse . message ) . toContain ( 'wait' )
61+ expect ( rateLimitResponse . message ) . toContain ( 'seconds' )
6862
69- // Get all system messages and find the 6-digit pin
70- const secondMessages = playerBot . getSystemMessages ( )
71- let actualSecondPin : string | undefined
72- for ( const msg of secondMessages ) {
73- const match = msg . message . match ( / ^ \d { 6 } $ / )
74- if ( match != null ) {
75- actualSecondPin = match [ 0 ]
76- break
77- }
78- }
79- console . log ( `Second call - Actual pin: ${ actualSecondPin ?? 'not found' } ` )
80-
81- // The pins should be the same (cached)
82- if ( actualFirstPin != null && actualSecondPin != null ) {
83- expect ( actualFirstPin ) . toBe ( actualSecondPin )
84- console . log ( `Pins match as expected (cache working): ${ actualFirstPin } ` )
85- }
63+ await playerBot . disconnect ( )
8664 } , 30000 )
8765
8866 test ( 'pin is stored in database on first request' , async ( ) => {
89- const initialCount = await getPlayerPinCount ( 'PinCachePlayer' )
67+ // Use a unique player for this test (max 16 chars)
68+ playerBot = await createBot ( 'PinDbTest' )
69+ await sleep ( 2000 )
70+ await opPlayer ( 'PinDbTest' )
71+ await sleep ( 500 )
72+ await clearPlayerPins ( )
73+ await sleep ( 500 )
74+
75+ const initialCount = await getPlayerPinCount ( 'PinDbTest' )
9076 console . log ( `Initial pin count: ${ initialCount } ` )
9177
9278 playerBot . clearSystemMessages ( )
9379 await playerBot . sendChat ( '/bmpin' )
9480 await playerBot . waitForSystemMessage ( 'expires' , 10000 )
9581 await sleep ( 1000 )
9682
97- const newCount = await getPlayerPinCount ( 'PinCachePlayer ' )
98- // Pin count should increase by at least 1 (could be more if previous test created one )
99- expect ( newCount ) . toBeGreaterThanOrEqual ( initialCount )
83+ const newCount = await getPlayerPinCount ( 'PinDbTest ' )
84+ // Pin count should be exactly 1 (old pins deleted before new one created)
85+ expect ( newCount ) . toBe ( 1 )
10086 console . log ( `Pin count after /bmpin: ${ newCount } ` )
101- } , 20000 )
10287
103- test ( 'only one pin is stored for multiple cached requests' , async ( ) => {
104- // Clear and wait for cache to be empty
88+ await playerBot . disconnect ( )
89+ } , 30000 )
90+
91+ test ( 'new pin generation deletes old pins for same player' , async ( ) => {
92+ // Use a unique player for this test (max 16 chars)
93+ playerBot = await createBot ( 'PinDelTest' )
94+ await sleep ( 2000 )
95+ await opPlayer ( 'PinDelTest' )
96+ await sleep ( 500 )
10597 await clearPlayerPins ( )
10698 await sleep ( 500 )
10799
108- const initialCount = await getPlayerPinCount ( 'PinCachePlayer' )
109- console . log ( `Initial pin count after clear: ${ initialCount } ` )
110-
111100 // First call creates a pin
112101 playerBot . clearSystemMessages ( )
113102 await playerBot . sendChat ( '/bmpin' )
114103 await playerBot . waitForSystemMessage ( 'expires' , 10000 )
115104 await sleep ( 500 )
116105
117- const afterFirstCall = await getPlayerPinCount ( 'PinCachePlayer ' )
106+ const afterFirstCall = await getPlayerPinCount ( 'PinDelTest ' )
118107 console . log ( `Pin count after first call: ${ afterFirstCall } ` )
108+ expect ( afterFirstCall ) . toBe ( 1 )
119109
120- // Make two more /bmpin calls (should use cache)
121- for ( let i = 0 ; i < 2 ; i ++ ) {
122- playerBot . clearSystemMessages ( )
123- await playerBot . sendChat ( '/bmpin' )
124- await playerBot . waitForSystemMessage ( 'expires' , 10000 )
125- await sleep ( 500 )
126- }
110+ // Wait for rate limit to expire (30 seconds)
111+ console . log ( 'Waiting 31 seconds for rate limit to expire...' )
112+ await sleep ( 31000 )
127113
128- await sleep ( 1000 )
114+ // Second call should delete old pin and create new one
115+ playerBot . clearSystemMessages ( )
116+ await playerBot . sendChat ( '/bmpin' )
117+ await playerBot . waitForSystemMessage ( 'expires' , 10000 )
118+ await sleep ( 500 )
129119
130- // Should still have the same count (cached, not generating new ones)
131- const finalCount = await getPlayerPinCount ( 'PinCachePlayer' )
132- console . log ( `Final pin count: ${ finalCount } ` )
120+ // Should still have only 1 pin (old one was deleted)
121+ const finalCount = await getPlayerPinCount ( 'PinDelTest' )
122+ console . log ( `Pin count after second call: ${ finalCount } ` )
123+ expect ( finalCount ) . toBe ( 1 )
133124
134- // Final count should equal the count after first call (no new pins generated)
135- expect ( finalCount ) . toBe ( afterFirstCall )
136- } , 30000 )
125+ await playerBot . disconnect ( )
126+ } , 70000 )
137127} )
0 commit comments