11import XCTest
22@testable import VibeMeter
33
4+ @MainActor
45final class ClaudeProviderIntegrationTests : XCTestCase {
56
67 // MARK: - Properties
78
8- private var provider : ClaudeProvider !
9- private var mockLogManager : MockClaudeLogManager !
10- private var mockSettingsManager : MockSettingsManager !
11-
12- // MARK: - Setup
13-
14- override func setUp( ) async throws {
15- try await super. setUp ( )
16-
17- mockSettingsManager = MockSettingsManager ( )
18- mockLogManager = MockClaudeLogManager ( )
19-
20- provider = await ClaudeProvider (
21- settingsManager: mockSettingsManager,
22- logManager: mockLogManager
23- )
24- }
9+ private lazy var mockSettingsManager = MockSettingsManager ( )
10+ private lazy var mockLogManager = ClaudeLogManagerMock ( )
11+ private lazy var provider = ClaudeProvider (
12+ settingsManager: mockSettingsManager,
13+ logManager: mockLogManager
14+ )
2515
2616 // MARK: - User Info Tests
2717
2818 func testFetchUserInfoWithAccess( ) async throws {
2919 // Given
30- mockLogManager. hasAccess = true
20+ mockLogManager. setHasAccess ( true )
3121
3222 // When
3323 let userInfo = try await provider. fetchUserInfo ( authToken: " dummy " )
@@ -39,7 +29,7 @@ final class ClaudeProviderIntegrationTests: XCTestCase {
3929
4030 func testFetchUserInfoWithoutAccess( ) async {
4131 // Given
42- mockLogManager. hasAccess = false
32+ mockLogManager. setHasAccess ( false )
4333
4434 // When/Then
4535 do {
@@ -58,8 +48,8 @@ final class ClaudeProviderIntegrationTests: XCTestCase {
5848
5949 func testFetchUsageDataWithLowUsage( ) async throws {
6050 // Given
61- mockLogManager. hasAccess = true
62- mockLogManager. currentWindow = FiveHourWindow (
51+ mockLogManager. setHasAccess ( true )
52+ mockLogManager. calculateFiveHourWindowResult = FiveHourWindow (
6353 used: 10.0 ,
6454 total: 100.0 ,
6555 resetDate: Date ( ) . addingTimeInterval ( 5 * 60 * 60 ) ,
@@ -79,8 +69,8 @@ final class ClaudeProviderIntegrationTests: XCTestCase {
7969
8070 func testFetchUsageDataWithHighUsage( ) async throws {
8171 // Given
82- mockLogManager. hasAccess = true
83- mockLogManager. currentWindow = FiveHourWindow (
72+ mockLogManager. setHasAccess ( true )
73+ mockLogManager. calculateFiveHourWindowResult = FiveHourWindow (
8474 used: 85.5 ,
8575 total: 100.0 ,
8676 resetDate: Date ( ) . addingTimeInterval ( 5 * 60 * 60 ) ,
@@ -98,8 +88,8 @@ final class ClaudeProviderIntegrationTests: XCTestCase {
9888
9989 func testFetchUsageDataWithNoUsage( ) async throws {
10090 // Given
101- mockLogManager. hasAccess = true
102- mockLogManager. currentWindow = FiveHourWindow (
91+ mockLogManager. setHasAccess ( true )
92+ mockLogManager. calculateFiveHourWindowResult = FiveHourWindow (
10393 used: 0.0 ,
10494 total: 100.0 ,
10595 resetDate: Date ( ) . addingTimeInterval ( 5 * 60 * 60 ) ,
@@ -119,7 +109,7 @@ final class ClaudeProviderIntegrationTests: XCTestCase {
119109
120110 func testFetchMonthlyInvoiceWithData( ) async throws {
121111 // Given
122- mockLogManager. hasAccess = true
112+ mockLogManager. setHasAccess ( true )
123113 let now = Date ( )
124114 let calendar = Calendar . current
125115 let month = calendar. component ( . month, from: now) - 1 // 0-indexed
@@ -131,24 +121,20 @@ final class ClaudeProviderIntegrationTests: XCTestCase {
131121 timestamp: now. addingTimeInterval ( - 24 * 60 * 60 ) , // Yesterday
132122 model: " claude-3-5-sonnet-latest " ,
133123 inputTokens: 10_000 ,
134- outputTokens: 5_000 ,
135- projectId: nil ,
136- id: " test-1 "
124+ outputTokens: 5_000
137125 ) ,
138126 ClaudeLogEntry (
139127 timestamp: now. addingTimeInterval ( - 48 * 60 * 60 ) , // 2 days ago
140128 model: " claude-3-5-sonnet-latest " ,
141129 inputTokens: 20_000 ,
142- outputTokens: 10_000 ,
143- projectId: nil ,
144- id: " test-2 "
130+ outputTokens: 10_000
145131 )
146132 ]
147133
148- mockLogManager. dailyUsage = [
134+ mockLogManager. setDailyUsage ( [
149135 calendar. startOfDay ( for: now. addingTimeInterval ( - 24 * 60 * 60 ) ) : [ entries [ 0 ] ] ,
150136 calendar. startOfDay ( for: now. addingTimeInterval ( - 48 * 60 * 60 ) ) : [ entries [ 1 ] ]
151- ]
137+ ] )
152138
153139 // When
154140 let invoice = try await provider. fetchMonthlyInvoice (
@@ -173,8 +159,8 @@ final class ClaudeProviderIntegrationTests: XCTestCase {
173159
174160 func testFetchMonthlyInvoiceWithNoData( ) async throws {
175161 // Given
176- mockLogManager. hasAccess = true
177- mockLogManager. dailyUsage = [ : ]
162+ mockLogManager. setHasAccess ( true )
163+ mockLogManager. setDailyUsage ( [ : ] )
178164
179165 let now = Date ( )
180166 let calendar = Calendar . current
@@ -198,7 +184,7 @@ final class ClaudeProviderIntegrationTests: XCTestCase {
198184
199185 func testValidateTokenWithAccess( ) async {
200186 // Given
201- mockLogManager. hasAccess = true
187+ mockLogManager. setHasAccess ( true )
202188
203189 // When
204190 let isValid = await provider. validateToken ( authToken: " dummy " )
@@ -209,7 +195,7 @@ final class ClaudeProviderIntegrationTests: XCTestCase {
209195
210196 func testValidateTokenWithoutAccess( ) async {
211197 // Given
212- mockLogManager. hasAccess = false
198+ mockLogManager. setHasAccess ( false )
213199
214200 // When
215201 let isValid = await provider. validateToken ( authToken: " dummy " )
@@ -222,20 +208,20 @@ final class ClaudeProviderIntegrationTests: XCTestCase {
222208
223209 func testRequestFileAccess( ) async {
224210 // Given
225- mockLogManager. hasAccess = false
226- mockLogManager. accessRequestResult = true
211+ mockLogManager. setHasAccess ( false )
212+ mockLogManager. requestLogAccessResult = true
227213
228214 // When
229215 let granted = await provider. requestFileAccess ( )
230216
231217 // Then
232218 XCTAssertTrue ( granted)
233- XCTAssertTrue ( mockLogManager. requestLogAccessCalled )
219+ XCTAssertTrue ( mockLogManager. callCount ( for : " requestLogAccess " ) > 0 )
234220 }
235221
236222 func testHasFileAccess( ) async {
237223 // Given
238- mockLogManager. hasAccess = true
224+ mockLogManager. setHasAccess ( true )
239225
240226 // When
241227 let hasAccess = await provider. hasFileAccess ( )
@@ -248,8 +234,8 @@ final class ClaudeProviderIntegrationTests: XCTestCase {
248234
249235 func testFetchUsageDataPerformance( ) async throws {
250236 // Given
251- mockLogManager. hasAccess = true
252- mockLogManager. currentWindow = FiveHourWindow (
237+ mockLogManager. setHasAccess ( true )
238+ mockLogManager. calculateFiveHourWindowResult = FiveHourWindow (
253239 used: 50.0 ,
254240 total: 100.0 ,
255241 resetDate: Date ( ) . addingTimeInterval ( 5 * 60 * 60 ) ,
@@ -267,55 +253,3 @@ final class ClaudeProviderIntegrationTests: XCTestCase {
267253 }
268254}
269255
270- // MARK: - Mock ClaudeLogManager
271-
272- @MainActor
273- final class MockClaudeLogManager : ClaudeLogManagerProtocol {
274- var hasAccess = true
275- var isProcessing = false
276- var lastError : Error ?
277- var dailyUsage : [ Date : [ ClaudeLogEntry ] ] = [ : ]
278- var currentWindow = FiveHourWindow (
279- used: 0 ,
280- total: 100 ,
281- resetDate: Date ( ) . addingTimeInterval ( 5 * 60 * 60 ) ,
282- tokensUsed: 0 ,
283- estimatedTokenLimit: 500_000
284- )
285- var accessRequestResult = true
286- var requestLogAccessCalled = false
287-
288- func requestLogAccess( ) async -> Bool {
289- requestLogAccessCalled = true
290- hasAccess = accessRequestResult
291- return accessRequestResult
292- }
293-
294- func revokeAccess( ) {
295- hasAccess = false
296- }
297-
298- func getDailyUsage( ) async -> [ Date : [ ClaudeLogEntry ] ] {
299- return dailyUsage
300- }
301-
302- func getDailyUsageWithProgress( delegate: ClaudeLogProgressDelegate ? ) async -> [ Date : [ ClaudeLogEntry ] ] {
303- return dailyUsage
304- }
305-
306- func invalidateCache( ) {
307- // No-op
308- }
309-
310- func calculateFiveHourWindow( from dailyUsage: [ Date : [ ClaudeLogEntry ] ] ) -> FiveHourWindow {
311- return currentWindow
312- }
313-
314- func countTokens( in text: String ) -> Int {
315- return text. count * 2 // Simple estimation
316- }
317-
318- func getCurrentWindowUsage( ) async -> FiveHourWindow {
319- return currentWindow
320- }
321- }
0 commit comments