1+ import { describe , it , expect } from 'vitest' ;
2+ import { getTotalRequestsForUsersExceedingQuota , getUniqueUsersExceedingQuota , CopilotUsageData , COPILOT_PLANS } from '@/lib/utils' ;
3+
4+ describe ( 'Exceeding Users Cost Calculation' , ( ) => {
5+ // Test data with users who exceed the 300 Business plan limit
6+ const mockData : CopilotUsageData [ ] = [
7+ // User A: 350 total requests (exceeds 300 limit)
8+ {
9+ timestamp : new Date ( '2025-01-01T10:00:00Z' ) ,
10+ user : 'userA@example.com' ,
11+ model : 'gpt-4o' ,
12+ requestsUsed : 150 ,
13+ exceedsQuota : false ,
14+ totalMonthlyQuota : '300'
15+ } ,
16+ {
17+ timestamp : new Date ( '2025-01-02T10:00:00Z' ) ,
18+ user : 'userA@example.com' ,
19+ model : 'gpt-4o' ,
20+ requestsUsed : 200 ,
21+ exceedsQuota : true , // Only this specific request exceeds quota
22+ totalMonthlyQuota : '300'
23+ } ,
24+ // User B: 250 total requests (does NOT exceed 300 limit)
25+ {
26+ timestamp : new Date ( '2025-01-01T11:00:00Z' ) ,
27+ user : 'userB@example.com' ,
28+ model : 'gpt-4o' ,
29+ requestsUsed : 100 ,
30+ exceedsQuota : false ,
31+ totalMonthlyQuota : '300'
32+ } ,
33+ {
34+ timestamp : new Date ( '2025-01-02T11:00:00Z' ) ,
35+ user : 'userB@example.com' ,
36+ model : 'gpt-4o' ,
37+ requestsUsed : 150 ,
38+ exceedsQuota : false ,
39+ totalMonthlyQuota : '300'
40+ } ,
41+ // User C: 450 total requests (exceeds 300 limit)
42+ {
43+ timestamp : new Date ( '2025-01-01T12:00:00Z' ) ,
44+ user : 'userC@example.com' ,
45+ model : 'claude-sonnet-3.5' ,
46+ requestsUsed : 300 ,
47+ exceedsQuota : false ,
48+ totalMonthlyQuota : '300'
49+ } ,
50+ {
51+ timestamp : new Date ( '2025-01-02T12:00:00Z' ) ,
52+ user : 'userC@example.com' ,
53+ model : 'claude-sonnet-3.5' ,
54+ requestsUsed : 150 ,
55+ exceedsQuota : true , // Only this specific request exceeds quota
56+ totalMonthlyQuota : '300'
57+ }
58+ ] ;
59+
60+ it ( 'should correctly count users exceeding quota' , ( ) => {
61+ // Only userA (350) and userC (450) exceed the 300 limit
62+ const exceedingUsersCount = getUniqueUsersExceedingQuota ( mockData , COPILOT_PLANS . BUSINESS ) ;
63+ expect ( exceedingUsersCount ) . toBe ( 2 ) ;
64+ } ) ;
65+
66+ it ( 'should correctly calculate total requests for users exceeding quota' , ( ) => {
67+ // Should return ALL requests for users who exceed the quota:
68+ // userA: 150 + 200 = 350 requests
69+ // userC: 300 + 150 = 450 requests
70+ // Total: 350 + 450 = 800 requests
71+ const totalRequests = getTotalRequestsForUsersExceedingQuota ( mockData , COPILOT_PLANS . BUSINESS ) ;
72+ expect ( totalRequests ) . toBe ( 800 ) ;
73+ } ) ;
74+
75+ it ( 'should NOT include requests from users who do not exceed quota' , ( ) => {
76+ // userB has 250 total requests (under 300 limit)
77+ // Their requests should NOT be included
78+ const totalRequests = getTotalRequestsForUsersExceedingQuota ( mockData , COPILOT_PLANS . BUSINESS ) ;
79+
80+ // Verify userB's requests are not included
81+ const userBTotal = 100 + 150 ; // 250 requests
82+ expect ( totalRequests ) . not . toEqual ( userBTotal ) ;
83+ expect ( totalRequests ) . toBeGreaterThan ( userBTotal ) ;
84+ } ) ;
85+
86+ it ( 'should handle different plan limits correctly' , ( ) => {
87+ // With Individual plan (50 limit), all users should exceed
88+ const individualPlanExceedingRequests = getTotalRequestsForUsersExceedingQuota ( mockData , COPILOT_PLANS . INDIVIDUAL ) ;
89+ const totalAllRequests = mockData . reduce ( ( sum , item ) => sum + item . requestsUsed , 0 ) ;
90+ expect ( individualPlanExceedingRequests ) . toBe ( totalAllRequests ) ; // All 1050 requests
91+
92+ // With Enterprise plan (1000 limit), no users should exceed
93+ const enterprisePlanExceedingRequests = getTotalRequestsForUsersExceedingQuota ( mockData , COPILOT_PLANS . ENTERPRISE ) ;
94+ expect ( enterprisePlanExceedingRequests ) . toBe ( 0 ) ;
95+ } ) ;
96+
97+ it ( 'should be consistent between count and total functions' , ( ) => {
98+ const exceedingUsersCount = getUniqueUsersExceedingQuota ( mockData , COPILOT_PLANS . BUSINESS ) ;
99+ const totalRequests = getTotalRequestsForUsersExceedingQuota ( mockData , COPILOT_PLANS . BUSINESS ) ;
100+
101+ // If there are exceeding users, there should be requests
102+ if ( exceedingUsersCount > 0 ) {
103+ expect ( totalRequests ) . toBeGreaterThan ( 0 ) ;
104+ } else {
105+ expect ( totalRequests ) . toBe ( 0 ) ;
106+ }
107+ } ) ;
108+
109+ it ( 'should demonstrate the difference between old logic and new logic' , ( ) => {
110+ // Old logic (incorrect): only count requests with exceedsQuota=true
111+ const oldLogicTotal = mockData
112+ . filter ( item => item . exceedsQuota )
113+ . reduce ( ( sum , item ) => sum + item . requestsUsed , 0 ) ;
114+
115+ // This would be: 200 (userA) + 150 (userC) = 350
116+ expect ( oldLogicTotal ) . toBe ( 350 ) ;
117+
118+ // New logic (correct): count ALL requests for users who exceed the plan limit
119+ const newLogicTotal = getTotalRequestsForUsersExceedingQuota ( mockData , COPILOT_PLANS . BUSINESS ) ;
120+
121+ // This should be: 350 (userA) + 450 (userC) = 800
122+ expect ( newLogicTotal ) . toBe ( 800 ) ;
123+
124+ // The new logic should give a higher (more accurate) total
125+ expect ( newLogicTotal ) . toBeGreaterThan ( oldLogicTotal ) ;
126+ } ) ;
127+
128+ it ( 'should handle edge cases correctly' , ( ) => {
129+ // Empty data
130+ expect ( getTotalRequestsForUsersExceedingQuota ( [ ] , COPILOT_PLANS . BUSINESS ) ) . toBe ( 0 ) ;
131+
132+ // Single user at exactly the limit
133+ const exactLimitData : CopilotUsageData [ ] = [ {
134+ timestamp : new Date ( '2025-01-01T10:00:00Z' ) ,
135+ user : 'exactUser@example.com' ,
136+ model : 'gpt-4o' ,
137+ requestsUsed : 300 , // Exactly at the 300 limit
138+ exceedsQuota : false ,
139+ totalMonthlyQuota : '300'
140+ } ] ;
141+
142+ // User with exactly 300 requests should NOT exceed the limit
143+ expect ( getTotalRequestsForUsersExceedingQuota ( exactLimitData , COPILOT_PLANS . BUSINESS ) ) . toBe ( 0 ) ;
144+ expect ( getUniqueUsersExceedingQuota ( exactLimitData , COPILOT_PLANS . BUSINESS ) ) . toBe ( 0 ) ;
145+ } ) ;
146+ } ) ;
0 commit comments