@codeguide/core 0.0.28 → 0.0.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/__tests__/services/codespace/codespace-v2.test.ts +53 -0
  2. package/__tests__/services/usage/usage-service.test.ts +458 -104
  3. package/codeguide.ts +3 -0
  4. package/dist/codeguide.d.ts +2 -1
  5. package/dist/codeguide.js +1 -0
  6. package/dist/index.d.ts +4 -3
  7. package/dist/services/base/base-service.d.ts +21 -0
  8. package/dist/services/base/base-service.js +114 -0
  9. package/dist/services/codespace/codespace-service.d.ts +64 -1
  10. package/dist/services/codespace/codespace-service.js +272 -0
  11. package/dist/services/codespace/codespace-types.d.ts +213 -12
  12. package/dist/services/codespace/index.d.ts +1 -1
  13. package/dist/services/index.d.ts +2 -0
  14. package/dist/services/index.js +4 -1
  15. package/dist/services/projects/project-types.d.ts +66 -32
  16. package/dist/services/starter-kits/index.d.ts +2 -0
  17. package/dist/services/starter-kits/index.js +20 -0
  18. package/dist/services/starter-kits/starter-kits-service.d.ts +13 -0
  19. package/dist/services/starter-kits/starter-kits-service.js +27 -0
  20. package/dist/services/starter-kits/starter-kits-types.d.ts +34 -0
  21. package/dist/services/starter-kits/starter-kits-types.js +2 -0
  22. package/dist/services/subscriptions/subscription-service.d.ts +11 -1
  23. package/dist/services/subscriptions/subscription-service.js +14 -0
  24. package/dist/services/tasks/task-service.d.ts +2 -1
  25. package/dist/services/tasks/task-service.js +8 -0
  26. package/dist/services/tasks/task-types.d.ts +26 -7
  27. package/dist/services/usage/usage-service.d.ts +5 -2
  28. package/dist/services/usage/usage-service.js +58 -9
  29. package/dist/services/usage/usage-types.d.ts +157 -34
  30. package/dist/types.d.ts +18 -2
  31. package/docs/.vitepress/README.md +51 -0
  32. package/docs/.vitepress/config.ts +139 -0
  33. package/docs/.vitepress/theme/custom.css +80 -0
  34. package/docs/.vitepress/theme/index.ts +13 -0
  35. package/docs/.vitepress/tsconfig.json +19 -0
  36. package/docs/QUICKSTART.md +77 -0
  37. package/docs/README.md +134 -0
  38. package/docs/README_SETUP.md +46 -0
  39. package/docs/authentication.md +351 -0
  40. package/docs/codeguide-client.md +350 -0
  41. package/docs/codespace-models.md +1004 -0
  42. package/docs/codespace-service.md +444 -0
  43. package/docs/index.md +135 -0
  44. package/docs/package.json +14 -0
  45. package/docs/projects-service.md +688 -0
  46. package/docs/security-keys-service.md +773 -0
  47. package/docs/starter-kits-service.md +249 -0
  48. package/docs/task-service.md +955 -0
  49. package/docs/testsprite_tests/TC001_Homepage_Load_and_Hero_Section_Display.py +70 -0
  50. package/docs/testsprite_tests/TC002_Sidebar_Navigation_ExpandCollapse_Functionality.py +73 -0
  51. package/docs/testsprite_tests/TC003_Full_Text_Local_Search_with_Keyboard_Shortcut.py +90 -0
  52. package/docs/testsprite_tests/TC004_Dark_Mode_Toggle_and_Persistence.py +73 -0
  53. package/docs/testsprite_tests/TC005_Mobile_Responsiveness_and_Touch_Navigation.py +113 -0
  54. package/docs/testsprite_tests/TC006_GitHub_Integration_Edit_this_page_Links.py +73 -0
  55. package/docs/testsprite_tests/TC007_Syntax_Highlighting_and_Code_Copy_Functionality.py +73 -0
  56. package/docs/testsprite_tests/TC008_Auto_Generated_Table_of_Contents_Accuracy.py +73 -0
  57. package/docs/testsprite_tests/TC009_SEO_and_Content_Discoverability_Verification.py +73 -0
  58. package/docs/testsprite_tests/TC010_Accessibility_Compliance_WCAG_AA.py +73 -0
  59. package/docs/testsprite_tests/TC011_Local_Development_Workflow_Build_and_Hot_Reload.py +74 -0
  60. package/docs/testsprite_tests/TC012_Performance_Metrics_Compliance.py +73 -0
  61. package/docs/testsprite_tests/standard_prd.json +122 -0
  62. package/docs/testsprite_tests/testsprite-mcp-test-report.html +2508 -0
  63. package/docs/testsprite_tests/testsprite-mcp-test-report.md +273 -0
  64. package/docs/testsprite_tests/testsprite_frontend_test_plan.json +390 -0
  65. package/docs/usage-service.md +291 -1
  66. package/index.ts +11 -3
  67. package/package.json +17 -2
  68. package/plans/CODESPACE_LOGS_STREAMING_GUIDE.md +320 -0
  69. package/plans/CODESPACE_TASK_LOGS_API_COMPLETE_GUIDE.md +821 -0
  70. package/services/base/base-service.ts +130 -0
  71. package/services/codespace/codespace-service.ts +359 -0
  72. package/services/codespace/codespace-types.ts +295 -13
  73. package/services/codespace/index.ts +21 -1
  74. package/services/index.ts +2 -0
  75. package/services/projects/README.md +107 -34
  76. package/services/projects/project-types.ts +69 -32
  77. package/services/starter-kits/index.ts +2 -0
  78. package/services/starter-kits/starter-kits-service.ts +33 -0
  79. package/services/starter-kits/starter-kits-types.ts +38 -0
  80. package/services/subscriptions/subscription-service.ts +23 -5
  81. package/services/tasks/task-service.ts +10 -0
  82. package/services/tasks/task-types.ts +29 -7
  83. package/services/usage/usage-service.ts +59 -10
  84. package/services/usage/usage-types.ts +186 -36
  85. package/types.ts +22 -2
@@ -6,12 +6,19 @@ import {
6
6
  TrackUsageRequest,
7
7
  TrackUsageResponse,
8
8
  CreditBalanceResponse,
9
+ CreditBalanceData,
9
10
  CreditCheckResponse,
10
11
  UsageSummaryResponse,
11
12
  AuthorizationResponse,
12
13
  CalculateUsageResponse,
13
14
  TrackCodespaceUsageResponse,
14
15
  CodespaceTaskUsageResponse,
16
+ DashboardAnalyticsRequest,
17
+ DashboardAnalyticsResponse,
18
+ UsageDetailsRequest,
19
+ UsageDetailsResponse,
20
+ ServiceBreakdownRequest,
21
+ ServiceBreakdownResponse,
15
22
  } from '../../../services/usage/usage-types'
16
23
 
17
24
  describe('UsageService', () => {
@@ -20,12 +27,12 @@ describe('UsageService', () => {
20
27
  let config: APIServiceConfig
21
28
 
22
29
  beforeEach(() => {
23
- mockAxios = new MockAdapter(axios)
24
30
  config = {
25
31
  baseUrl: 'https://api.codeguide.app',
26
32
  databaseApiKey: 'sk_test123',
27
33
  }
28
34
  usageService = new UsageService(config)
35
+ mockAxios = new MockAdapter((usageService as any).client)
29
36
  })
30
37
 
31
38
  afterEach(() => {
@@ -49,7 +56,7 @@ describe('UsageService', () => {
49
56
  message: 'Usage tracked successfully',
50
57
  }
51
58
 
52
- mockAxios.onPost('/v1/usage/track', request).reply(200, response)
59
+ mockAxios.onPost('/usage/track', request).reply(200, response)
53
60
 
54
61
  const result = await usageService.trackUsage(request)
55
62
 
@@ -63,7 +70,7 @@ describe('UsageService', () => {
63
70
  output_tokens: 50,
64
71
  }
65
72
 
66
- mockAxios.onPost('/v1/usage/track', request).reply(400, {
73
+ mockAxios.onPost('/usage/track', request).reply(400, {
67
74
  detail: 'Invalid request',
68
75
  })
69
76
 
@@ -73,7 +80,7 @@ describe('UsageService', () => {
73
80
 
74
81
  describe('getCreditBalance', () => {
75
82
  it('should get credit balance successfully', async () => {
76
- const response: CreditBalanceResponse = {
83
+ const creditBalanceData: CreditBalanceData = {
77
84
  user_id: 'user123',
78
85
  total_consumed: 10.5,
79
86
  total_allotted: 100,
@@ -87,7 +94,11 @@ describe('UsageService', () => {
87
94
  },
88
95
  }
89
96
 
90
- mockAxios.onGet('/v1/usage/credit-balance').reply(200, response)
97
+ const response: CreditBalanceResponse = {
98
+ data: creditBalanceData,
99
+ }
100
+
101
+ mockAxios.onGet('/usage/credit-balance').reply(200, response)
91
102
 
92
103
  const result = await usageService.getCreditBalance()
93
104
 
@@ -113,7 +124,7 @@ describe('UsageService', () => {
113
124
 
114
125
  mockAxios
115
126
  .onGet(
116
- '/v1/usage/credit-check?model_key=gpt-4&input_tokens=100&output_tokens=50&call_seconds=2'
127
+ '/usage/credit-check?model_key=gpt-4&input_tokens=100&output_tokens=50&call_seconds=2'
117
128
  )
118
129
  .reply(200, response)
119
130
 
@@ -135,9 +146,7 @@ describe('UsageService', () => {
135
146
  model_key: 'gpt-4',
136
147
  }
137
148
 
138
- mockAxios
139
- .onGet('/v1/usage/credit-check?model_key=gpt-4&input_tokens=100')
140
- .reply(200, response)
149
+ mockAxios.onGet('/usage/credit-check?model_key=gpt-4&input_tokens=100').reply(200, response)
141
150
 
142
151
  const result = await usageService.checkCredits(params)
143
152
 
@@ -145,73 +154,6 @@ describe('UsageService', () => {
145
154
  })
146
155
  })
147
156
 
148
- describe('getUsageSummary', () => {
149
- it('should get usage summary with date range', async () => {
150
- const params = {
151
- start_date: '2024-01-01',
152
- end_date: '2024-01-31',
153
- }
154
-
155
- const response: UsageSummaryResponse = {
156
- user_id: 'user123',
157
- period: {
158
- start_date: '2024-01-01',
159
- end_date: '2024-01-31',
160
- },
161
- usage_summary: {
162
- total_credits_used: 15.5,
163
- total_calls: 42,
164
- model_breakdown: {
165
- 'gpt-4': { calls: 20, credits: 12.0 },
166
- 'gpt-3.5': { calls: 22, credits: 3.5 },
167
- },
168
- daily_usage: [
169
- { date: '2024-01-01', credits_used: 1.5, calls: 5 },
170
- { date: '2024-01-02', credits_used: 2.0, calls: 8 },
171
- ],
172
- },
173
- subscription: {
174
- plan: 'pro',
175
- status: 'active',
176
- },
177
- }
178
-
179
- mockAxios
180
- .onGet('/v1/usage/summary?start_date=2024-01-01&end_date=2024-01-31')
181
- .reply(200, response)
182
-
183
- const result = await usageService.getUsageSummary(params)
184
-
185
- expect(result).toEqual(response)
186
- })
187
-
188
- it('should get usage summary without date range', async () => {
189
- const response: UsageSummaryResponse = {
190
- user_id: 'user123',
191
- period: {
192
- start_date: '2024-01-01',
193
- end_date: '2024-01-31',
194
- },
195
- usage_summary: {
196
- total_credits_used: 15.5,
197
- total_calls: 42,
198
- model_breakdown: {},
199
- daily_usage: [],
200
- },
201
- subscription: {
202
- plan: 'pro',
203
- status: 'active',
204
- },
205
- }
206
-
207
- mockAxios.onGet('/v1/usage/summary').reply(200, response)
208
-
209
- const result = await usageService.getUsageSummary()
210
-
211
- expect(result).toEqual(response)
212
- })
213
- })
214
-
215
157
  describe('getAuthorization', () => {
216
158
  it('should get authorization info successfully', async () => {
217
159
  const response: AuthorizationResponse = {
@@ -291,7 +233,7 @@ describe('UsageService', () => {
291
233
  message: 'Authorization status retrieved successfully',
292
234
  }
293
235
 
294
- mockAxios.onGet('/v1/usage/authorization').reply(200, response)
236
+ mockAxios.onGet('/usage/authorization').reply(200, response)
295
237
 
296
238
  const result = await usageService.getAuthorization()
297
239
 
@@ -375,7 +317,7 @@ describe('UsageService', () => {
375
317
  message: 'Authorization status retrieved successfully',
376
318
  }
377
319
 
378
- mockAxios.onGet('/v1/usage/authorization').reply(200, response)
320
+ mockAxios.onGet('/usage/authorization').reply(200, response)
379
321
 
380
322
  const result = await usageService.getAuthorization()
381
323
 
@@ -397,7 +339,7 @@ describe('UsageService', () => {
397
339
  credits_expire_at: '2024-12-31',
398
340
  }
399
341
 
400
- mockAxios.onGet('/v1/usage/free-user-status').reply(200, response)
342
+ mockAxios.onGet('/usage/free-user-status').reply(200, response)
401
343
 
402
344
  const result = await usageService.getFreeUserStatus()
403
345
 
@@ -428,7 +370,7 @@ describe('UsageService', () => {
428
370
 
429
371
  mockAxios
430
372
  .onGet(
431
- '/v1/usage/calculate?model_key=gpt-4&input_tokens=100&output_tokens=50&call_seconds=2&cost_amount=0.05'
373
+ '/usage/calculate?model_key=gpt-4&input_tokens=100&output_tokens=50&call_seconds=2&cost_amount=0.05'
432
374
  )
433
375
  .reply(200, response)
434
376
 
@@ -461,7 +403,7 @@ describe('UsageService', () => {
461
403
  created_at: '2024-01-01T00:00:00Z',
462
404
  }
463
405
 
464
- mockAxios.onPost('/v1/usage/codespace/track', request).reply(200, response)
406
+ mockAxios.onPost('/usage/codespace/track', request).reply(200, response)
465
407
 
466
408
  const result = await usageService.trackCodespaceUsage(request)
467
409
 
@@ -472,29 +414,15 @@ describe('UsageService', () => {
472
414
  describe('getCodespaceTaskUsage', () => {
473
415
  it('should get codespace task usage successfully', async () => {
474
416
  const response: CodespaceTaskUsageResponse = {
475
- codespace_task_id: 'task123',
476
- total_usage: {
477
- total_input_tokens: 200,
478
- total_output_tokens: 100,
479
- total_call_seconds: 4,
480
- total_cost: 0.1,
417
+ status: 'success',
418
+ data: {
419
+ total_records: 2,
420
+ total_credits_consumed: 49.428799,
421
+ latest_usage: '2025-11-24T07:50:58.150274+00:00',
481
422
  },
482
- usage_records: [
483
- {
484
- id: 'usage123',
485
- codespace_task_id: 'task123',
486
- user_id: 'user123',
487
- model_key: 'gpt-4',
488
- input_tokens: 100,
489
- output_tokens: 50,
490
- call_seconds: 2,
491
- cost_amount: 0.05,
492
- created_at: '2024-01-01T00:00:00Z',
493
- },
494
- ],
495
423
  }
496
424
 
497
- mockAxios.onGet('/v1/usage/codespace/task/task123').reply(200, response)
425
+ mockAxios.onGet('/usage/codespace/task/task123').reply(200, response)
498
426
 
499
427
  const result = await usageService.getCodespaceTaskUsage('task123')
500
428
 
@@ -504,7 +432,7 @@ describe('UsageService', () => {
504
432
 
505
433
  describe('healthCheck', () => {
506
434
  it('should return true when API is healthy', async () => {
507
- mockAxios.onGet('/v1/usage/health').reply(200, {
435
+ mockAxios.onGet('/usage/health').reply(200, {
508
436
  status: 'healthy',
509
437
  timestamp: '2024-01-01T00:00:00Z',
510
438
  version: '1.0.0',
@@ -516,7 +444,7 @@ describe('UsageService', () => {
516
444
  })
517
445
 
518
446
  it('should return false when API is not healthy', async () => {
519
- mockAxios.onGet('/v1/usage/health').reply(200, {
447
+ mockAxios.onGet('/usage/health').reply(200, {
520
448
  status: 'unhealthy',
521
449
  timestamp: '2024-01-01T00:00:00Z',
522
450
  version: '1.0.0',
@@ -528,11 +456,437 @@ describe('UsageService', () => {
528
456
  })
529
457
 
530
458
  it('should return false when health check fails', async () => {
531
- mockAxios.onGet('/v1/usage/health').reply(500)
459
+ mockAxios.onGet('/usage/health').reply(500)
532
460
 
533
461
  const result = await usageService.healthCheck()
534
462
 
535
463
  expect(result).toBe(false)
536
464
  })
537
465
  })
466
+
467
+ // Dashboard Analytics Tests
468
+ describe('getDashboardAnalytics', () => {
469
+ it('should get dashboard analytics with period parameter', async () => {
470
+ const params: DashboardAnalyticsRequest = {
471
+ period: '7d',
472
+ }
473
+
474
+ const response: DashboardAnalyticsResponse = {
475
+ status: 'success',
476
+ data: {
477
+ period: {
478
+ start: '2024-01-25',
479
+ end: '2024-01-31',
480
+ label: '7d',
481
+ },
482
+ daily_usage: [
483
+ {
484
+ date: '2024-01-25',
485
+ credits_consumed: 1250,
486
+ cost_usd: 3.75,
487
+ requests_count: 15,
488
+ average_credits_per_request: 83.33,
489
+ },
490
+ ],
491
+ totals: {
492
+ credits_consumed: 13870,
493
+ cost_usd: 41.61,
494
+ requests_count: 142,
495
+ },
496
+ averages: {
497
+ daily_credits: 1981.43,
498
+ daily_requests: 20.29,
499
+ },
500
+ trends: {
501
+ credits_consumed: 15.7,
502
+ requests_count: 8.3,
503
+ },
504
+ top_services: [
505
+ {
506
+ service_type: 'docs',
507
+ credits_consumed: 5230,
508
+ requests_count: 58,
509
+ },
510
+ ],
511
+ },
512
+ }
513
+
514
+ mockAxios.onGet('/usage/dashboard/analytics?period=7d').reply(200, response)
515
+
516
+ const result = await usageService.getDashboardAnalytics(params)
517
+
518
+ expect(result).toEqual(response)
519
+ })
520
+
521
+ it('should get dashboard analytics with all parameters', async () => {
522
+ const params: DashboardAnalyticsRequest = {
523
+ start_date: '2024-01-01',
524
+ end_date: '2024-01-31',
525
+ service_type: 'docs',
526
+ }
527
+
528
+ const response: DashboardAnalyticsResponse = {
529
+ status: 'success',
530
+ data: {
531
+ period: {
532
+ start: '2024-01-01',
533
+ end: '2024-01-31',
534
+ label: 'custom',
535
+ },
536
+ daily_usage: [],
537
+ totals: {
538
+ credits_consumed: 5000,
539
+ cost_usd: 15.0,
540
+ requests_count: 45,
541
+ },
542
+ averages: {
543
+ daily_credits: 161.29,
544
+ daily_requests: 1.45,
545
+ },
546
+ trends: {
547
+ credits_consumed: 12.5,
548
+ requests_count: 5.2,
549
+ },
550
+ top_services: [
551
+ {
552
+ service_type: 'docs',
553
+ credits_consumed: 5000,
554
+ requests_count: 45,
555
+ },
556
+ ],
557
+ },
558
+ }
559
+
560
+ mockAxios
561
+ .onGet(
562
+ '/usage/dashboard/analytics?start_date=2024-01-01&end_date=2024-01-31&service_type=docs'
563
+ )
564
+ .reply(200, response)
565
+
566
+ const result = await usageService.getDashboardAnalytics(params)
567
+
568
+ expect(result).toEqual(response)
569
+ })
570
+
571
+ it('should get dashboard analytics without parameters', async () => {
572
+ const response: DashboardAnalyticsResponse = {
573
+ status: 'success',
574
+ data: {
575
+ period: {
576
+ start: '2024-01-01',
577
+ end: '2024-01-07',
578
+ label: '7d',
579
+ },
580
+ daily_usage: [],
581
+ totals: {
582
+ credits_consumed: 1000,
583
+ cost_usd: 3.0,
584
+ requests_count: 10,
585
+ },
586
+ averages: {
587
+ daily_credits: 142.86,
588
+ daily_requests: 1.43,
589
+ },
590
+ trends: {
591
+ credits_consumed: 5.0,
592
+ requests_count: 2.0,
593
+ },
594
+ top_services: [],
595
+ },
596
+ }
597
+
598
+ mockAxios.onGet('/usage/dashboard/analytics').reply(200, response)
599
+
600
+ const result = await usageService.getDashboardAnalytics()
601
+
602
+ expect(result).toEqual(response)
603
+ })
604
+ })
605
+
606
+ describe('getUsageDetails', () => {
607
+ it('should get usage details with pagination parameters', async () => {
608
+ const params: UsageDetailsRequest = {
609
+ page: 1,
610
+ page_size: 25,
611
+ sort_by: 'credits_consumed',
612
+ sort_order: 'desc',
613
+ }
614
+
615
+ const response: UsageDetailsResponse = {
616
+ status: 'success',
617
+ data: [
618
+ {
619
+ id: 'rec_123456789',
620
+ created_at: '2024-01-31T14:30:15.123Z',
621
+ service_type: 'docs',
622
+ model_name: 'GPT-4',
623
+ usage_type: 'output_tokens',
624
+ units_consumed: 1250,
625
+ credits_consumed: 156,
626
+ cost_amount: 0.468,
627
+ },
628
+ ],
629
+ pagination: {
630
+ page: 1,
631
+ page_size: 25,
632
+ total_count: 142,
633
+ total_pages: 6,
634
+ has_next: true,
635
+ has_prev: false,
636
+ },
637
+ filters: {
638
+ period: null,
639
+ start_date: null,
640
+ end_date: null,
641
+ service_type: null,
642
+ },
643
+ }
644
+
645
+ mockAxios
646
+ .onGet(
647
+ '/usage/dashboard/details?page=1&page_size=25&sort_by=credits_consumed&sort_order=desc'
648
+ )
649
+ .reply(200, response)
650
+
651
+ const result = await usageService.getUsageDetails(params)
652
+
653
+ expect(result).toEqual(response)
654
+ })
655
+
656
+ it('should get usage details with filtering parameters', async () => {
657
+ const params: UsageDetailsRequest = {
658
+ period: '1m',
659
+ service_type: 'chat',
660
+ }
661
+
662
+ const response: UsageDetailsResponse = {
663
+ status: 'success',
664
+ data: [
665
+ {
666
+ id: 'rec_123456790',
667
+ created_at: '2024-01-30T10:15:20.456Z',
668
+ service_type: 'chat',
669
+ model_name: 'GPT-3.5 Turbo',
670
+ usage_type: 'input_tokens',
671
+ units_consumed: 890,
672
+ credits_consumed: 89,
673
+ cost_amount: null,
674
+ },
675
+ ],
676
+ pagination: {
677
+ page: 1,
678
+ page_size: 50,
679
+ total_count: 25,
680
+ total_pages: 1,
681
+ has_next: false,
682
+ has_prev: false,
683
+ },
684
+ filters: {
685
+ period: '1m',
686
+ start_date: null,
687
+ end_date: null,
688
+ service_type: 'chat',
689
+ },
690
+ }
691
+
692
+ mockAxios.onGet('/usage/dashboard/details?period=1m&service_type=chat').reply(200, response)
693
+
694
+ const result = await usageService.getUsageDetails(params)
695
+
696
+ expect(result).toEqual(response)
697
+ })
698
+ })
699
+
700
+ describe('getUsageSummary', () => {
701
+ it('should get usage summary dashboard with period parameter', async () => {
702
+ const params = {
703
+ period: '7d' as const,
704
+ }
705
+
706
+ const response: UsageSummaryResponse = {
707
+ status: 'success',
708
+ data: {
709
+ current_period: {
710
+ credits_consumed: 13870,
711
+ cost_usd: 41.61,
712
+ requests_count: 142,
713
+ },
714
+ previous_period: {
715
+ credits_consumed: 11990,
716
+ cost_usd: 35.97,
717
+ requests_count: 131,
718
+ },
719
+ billing_cycle: {
720
+ total_allotted: 50000,
721
+ total_consumed: 28450,
722
+ remaining_credits: 21550,
723
+ },
724
+ utilization_percentage: 56.9,
725
+ remaining_credits: 21550,
726
+ daily_average: 1981.43,
727
+ projected_monthly: 59443,
728
+ },
729
+ }
730
+
731
+ mockAxios.onGet('/usage/dashboard/summary?period=7d').reply(200, response)
732
+
733
+ const result = await usageService.getUsageSummary(params)
734
+
735
+ expect(result).toEqual(response)
736
+ })
737
+
738
+ it('should get usage summary dashboard with custom date range', async () => {
739
+ const params = {
740
+ start_date: '2024-01-01',
741
+ end_date: '2024-01-31',
742
+ }
743
+
744
+ const response: UsageSummaryResponse = {
745
+ status: 'success',
746
+ data: {
747
+ current_period: {
748
+ credits_consumed: 25000,
749
+ cost_usd: 75.0,
750
+ requests_count: 300,
751
+ },
752
+ previous_period: {
753
+ credits_consumed: 22000,
754
+ cost_usd: 66.0,
755
+ requests_count: 275,
756
+ },
757
+ billing_cycle: {
758
+ total_allotted: 50000,
759
+ total_consumed: 47000,
760
+ remaining_credits: 3000,
761
+ },
762
+ utilization_percentage: 94.0,
763
+ remaining_credits: 3000,
764
+ daily_average: 806.45,
765
+ projected_monthly: 25000,
766
+ },
767
+ }
768
+
769
+ mockAxios
770
+ .onGet('/usage/dashboard/summary?start_date=2024-01-01&end_date=2024-01-31')
771
+ .reply(200, response)
772
+
773
+ const result = await usageService.getUsageSummary(params)
774
+
775
+ expect(result).toEqual(response)
776
+ })
777
+ })
778
+
779
+ describe('getServiceBreakdown', () => {
780
+ it('should get service breakdown with period parameter', async () => {
781
+ const params: ServiceBreakdownRequest = {
782
+ period: '7d',
783
+ }
784
+
785
+ const response: ServiceBreakdownResponse = {
786
+ status: 'success',
787
+ data: {
788
+ period: {
789
+ start: '2024-01-25',
790
+ end: '2024-01-31',
791
+ label: '7d',
792
+ },
793
+ services: [
794
+ {
795
+ service_type: 'docs',
796
+ credits_consumed: 5230,
797
+ percentage: 37.71,
798
+ cost_usd: 15.69,
799
+ requests_count: 58,
800
+ trend: 12.5,
801
+ },
802
+ {
803
+ service_type: 'chat',
804
+ credits_consumed: 4120,
805
+ percentage: 29.71,
806
+ cost_usd: 12.36,
807
+ requests_count: 47,
808
+ trend: -5.2,
809
+ },
810
+ ],
811
+ total_credits: 13870,
812
+ total_cost: 41.61,
813
+ },
814
+ }
815
+
816
+ mockAxios.onGet('/usage/dashboard/services?period=7d').reply(200, response)
817
+
818
+ const result = await usageService.getServiceBreakdown(params)
819
+
820
+ expect(result).toEqual(response)
821
+ })
822
+
823
+ it('should get service breakdown with custom date range', async () => {
824
+ const params: ServiceBreakdownRequest = {
825
+ start_date: '2024-01-01',
826
+ end_date: '2024-01-31',
827
+ }
828
+
829
+ const response: ServiceBreakdownResponse = {
830
+ status: 'success',
831
+ data: {
832
+ period: {
833
+ start: '2024-01-01',
834
+ end: '2024-01-31',
835
+ label: 'custom',
836
+ },
837
+ services: [
838
+ {
839
+ service_type: 'codespace_task',
840
+ credits_consumed: 15000,
841
+ percentage: 60.0,
842
+ cost_usd: 45.0,
843
+ requests_count: 25,
844
+ trend: 28.4,
845
+ },
846
+ ],
847
+ total_credits: 25000,
848
+ total_cost: 75.0,
849
+ },
850
+ }
851
+
852
+ mockAxios
853
+ .onGet('/usage/dashboard/services?start_date=2024-01-01&end_date=2024-01-31')
854
+ .reply(200, response)
855
+
856
+ const result = await usageService.getServiceBreakdown(params)
857
+
858
+ expect(result).toEqual(response)
859
+ })
860
+
861
+ it('should get service breakdown without parameters', async () => {
862
+ const response: ServiceBreakdownResponse = {
863
+ status: 'success',
864
+ data: {
865
+ period: {
866
+ start: '2024-01-01',
867
+ end: '2024-01-07',
868
+ label: '7d',
869
+ },
870
+ services: [
871
+ {
872
+ service_type: 'api',
873
+ credits_consumed: 700,
874
+ percentage: 100.0,
875
+ cost_usd: 2.1,
876
+ requests_count: 5,
877
+ trend: 0.0,
878
+ },
879
+ ],
880
+ total_credits: 700,
881
+ total_cost: 2.1,
882
+ },
883
+ }
884
+
885
+ mockAxios.onGet('/usage/dashboard/services').reply(200, response)
886
+
887
+ const result = await usageService.getServiceBreakdown()
888
+
889
+ expect(result).toEqual(response)
890
+ })
891
+ })
538
892
  })