ReadKeep/readeckTests/Helpers/TestMocks.swift
Ilyas Hallak a227c275f3 feat: Implement extended font system and offline sync improvements
- Add 10 new fonts (Literata, Merriweather, Source Serif, Lato, Montserrat, Source Sans)
- Support Apple system fonts and Google Fonts (OFL 1.1 licensed)
- Extend FontFamily enum with new fonts and categories
- Update FontSettingsViewModel and WebView with font support
- Force WebView reload when font settings change
- Refactor OfflineSyncManager with protocol and improved error handling
- Add test mocks and OfflineSyncManagerTests with 9 test cases
- Add OpenSourceLicensesView and FontDebugView
- Bump build number
- Update localization strings
2025-12-10 21:25:39 +01:00

167 lines
5.2 KiB
Swift

//
// TestMocks.swift
// readeckTests
//
// Created by Ilyas Hallak
//
import Foundation
import CoreData
@testable import readeck
// MARK: - Mock API
@MainActor
class TestMockAPI: PAPI {
var tokenProvider: TokenProvider = TestMockTokenProvider()
var createBookmarkCalls: [(CreateBookmarkRequestDto, Result<CreateBookmarkResponseDto, Error>)] = []
var createBookmarkResults: [Result<CreateBookmarkResponseDto, Error>] = []
private var callIndex = 0
func createBookmark(createRequest: CreateBookmarkRequestDto) async throws -> CreateBookmarkResponseDto {
guard callIndex < createBookmarkResults.count else {
throw APIError.serverError(500)
}
let result = createBookmarkResults[callIndex]
callIndex += 1
createBookmarkCalls.append((createRequest, result))
switch result {
case .success(let response):
return response
case .failure(let error):
throw error
}
}
func reset() {
createBookmarkCalls.removeAll()
callIndex = 0
}
// MARK: - Unimplemented Methods
func login(endpoint: String, username: String, password: String) async throws -> UserDto {
fatalError("Not implemented for tests")
}
func getBookmarks(state: BookmarkState?, limit: Int?, offset: Int?, search: String?, type: [BookmarkType]?, tag: String?) async throws -> BookmarksPageDto {
fatalError("Not implemented for tests")
}
func getBookmark(id: String) async throws -> BookmarkDetailDto {
fatalError("Not implemented for tests")
}
func getBookmarkArticle(id: String) async throws -> String {
fatalError("Not implemented for tests")
}
func updateBookmark(id: String, updateRequest: UpdateBookmarkRequestDto) async throws {
fatalError("Not implemented for tests")
}
func deleteBookmark(id: String) async throws {
fatalError("Not implemented for tests")
}
func searchBookmarks(search: String) async throws -> BookmarksPageDto {
fatalError("Not implemented for tests")
}
func getBookmarkLabels() async throws -> [BookmarkLabelDto] {
fatalError("Not implemented for tests")
}
func getBookmarkAnnotations(bookmarkId: String) async throws -> [AnnotationDto] {
fatalError("Not implemented for tests")
}
func createAnnotation(bookmarkId: String, color: String, startOffset: Int, endOffset: Int, startSelector: String, endSelector: String) async throws -> AnnotationDto {
fatalError("Not implemented for tests")
}
func deleteAnnotation(bookmarkId: String, annotationId: String) async throws {
fatalError("Not implemented for tests")
}
}
// MARK: - Mock Token Provider
class TestMockTokenProvider: TokenProvider {
func getToken() async -> String? { return "mock-token" }
func setToken(_ token: String) async {}
func clearToken() async {}
func getEndpoint() async -> String? { return "https://mock.example.com" }
func setEndpoint(_ endpoint: String) async {}
func clearEndpoint() async {}
}
// MARK: - Test CoreData Manager
class TestCoreDataManager {
let context: NSManagedObjectContext
init() {
let managedObjectModel = NSManagedObjectModel.mergedModel(from: [Bundle.main])!
let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: managedObjectModel)
try! persistentStoreCoordinator.addPersistentStore(
ofType: NSInMemoryStoreType,
configurationName: nil,
at: nil,
options: nil
)
context = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
context.persistentStoreCoordinator = persistentStoreCoordinator
context.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy
}
func createTestBookmark(url: String, title: String, tags: String? = nil) -> ArticleURLEntity {
let entity = ArticleURLEntity(context: context)
entity.url = url
entity.title = title
entity.tags = tags
entity.id = UUID()
try! context.save()
return entity
}
func fetchAllBookmarks() -> [ArticleURLEntity] {
let fetchRequest: NSFetchRequest<ArticleURLEntity> = ArticleURLEntity.fetchRequest()
return (try? context.fetch(fetchRequest)) ?? []
}
func clearAll() {
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = ArticleURLEntity.fetchRequest()
let deleteRequest = NSBatchDeleteRequest(fetchRequest: fetchRequest)
try? context.execute(deleteRequest)
try? context.save()
}
}
// MARK: - Testable OfflineSyncManager
@MainActor
class TestableOfflineSyncManager: OfflineSyncManager {
let mockCoreDataManager: TestCoreDataManager
init(api: PAPI, coreDataManager: TestCoreDataManager) {
self.mockCoreDataManager = coreDataManager
super.init(api: api)
}
override func getOfflineBookmarks() -> [ArticleURLEntity] {
return mockCoreDataManager.fetchAllBookmarks()
}
override func deleteOfflineBookmark(_ entity: ArticleURLEntity) {
mockCoreDataManager.context.delete(entity)
try? mockCoreDataManager.context.save()
}
}