Files
steipete--codexbar/Sources/CodexBar/PreferencesProvidersPane+Testing.swift
2026-07-13 12:22:33 +08:00

290 lines
11 KiB
Swift

#if DEBUG
import CodexBarCore
import SwiftUI
extension ProvidersPane {
func _test_binding(for provider: UsageProvider) -> Binding<Bool> {
self.binding(for: provider)
}
func _test_providerSubtitle(_ provider: UsageProvider) -> String {
self.providerSubtitle(provider)
}
func _test_providerSidebarSubtitle(_ provider: UsageProvider) -> String {
self.providerSidebarSubtitle(provider)
}
func _test_moveProviders(fromOffsets: IndexSet, toOffset: Int) {
self.moveProviders(fromOffsets: fromOffsets, toOffset: toOffset)
}
func _test_menuBarMetricPicker(for provider: UsageProvider) -> ProviderSettingsPickerDescriptor? {
self.menuBarMetricPicker(for: provider)
}
func _test_settingsPickers(for provider: UsageProvider) -> [ProviderSettingsPickerDescriptor] {
guard let impl = ProviderCatalog.implementation(for: provider) else { return [] }
var statusTextByID: [String: String] = [:]
var lastAppActiveRunAtByID: [String: Date] = [:]
let context = ProviderSettingsContext(
provider: provider,
settings: self.settings,
store: self.store,
boolBinding: { keyPath in
Binding(
get: { self.settings[keyPath: keyPath] },
set: { self.settings[keyPath: keyPath] = $0 })
},
stringBinding: { keyPath in
Binding(
get: { self.settings[keyPath: keyPath] },
set: { self.settings[keyPath: keyPath] = $0 })
},
statusText: { id in
statusTextByID[id]
},
setStatusText: { id, text in
if let text {
statusTextByID[id] = text
} else {
statusTextByID.removeValue(forKey: id)
}
},
lastAppActiveRunAt: { id in
lastAppActiveRunAtByID[id]
},
setLastAppActiveRunAt: { id, date in
if let date {
lastAppActiveRunAtByID[id] = date
} else {
lastAppActiveRunAtByID.removeValue(forKey: id)
}
},
requestConfirmation: { _ in },
runLoginFlow: {})
return impl.settingsPickers(context: context)
.filter { $0.isVisible?() ?? true }
}
func _test_tokenAccountDescriptor(for provider: UsageProvider) -> ProviderSettingsTokenAccountsDescriptor? {
self.tokenAccountDescriptor(for: provider)
}
func _test_menuCardModel(for provider: UsageProvider) -> UsageMenuCardView.Model {
self.menuCardModel(for: provider)
}
func _test_openAIWebDiagnostic(for provider: UsageProvider) -> String? {
self.openAIWebDiagnostic(for: provider)
}
func _test_providerErrorDisplay(for provider: UsageProvider) -> ProviderErrorDisplay? {
self.providerErrorDisplay(provider)
}
func _test_codexAccountsSectionState() -> CodexAccountsSectionState? {
self.codexAccountsSectionState(for: .codex)
}
func _test_selectCodexVisibleAccount(id: String) async {
await self.selectCodexVisibleAccount(id: id)
}
func _test_addManagedCodexAccount() async {
await self.addManagedCodexAccount()
}
func _test_reauthenticateCodexAccount(_ account: CodexVisibleAccount) async {
await self.reauthenticateCodexAccount(account)
}
func _test_requestCodexSystemVisibleAccount(id: String) async {
await self.requestCodexSystemVisibleAccount(id: id)
}
}
@MainActor
enum ProvidersPaneTestHarness {
static func exercise(settings: SettingsStore, store: UsageStore) {
self.prepareTestState(settings: settings, store: store)
let pane = ProvidersPane(settings: settings, store: store)
self.exercisePaneBasics(pane: pane)
let descriptors = self.makeDescriptors()
self.exerciseDetailViews(store: store, descriptors: descriptors)
}
private static func prepareTestState(settings: SettingsStore, store: UsageStore) {
store.versions[.codex] = "1.0.0"
store.versions[.claude] = "2.0.0 (build 123)"
store.versions[.cursor] = nil
store._setSnapshotForTesting(
UsageSnapshot(primary: nil, secondary: nil, updatedAt: Date()),
provider: .codex)
store._setSnapshotForTesting(
UsageSnapshot(primary: nil, secondary: nil, updatedAt: Date()),
provider: .minimax)
store._setErrorForTesting(String(repeating: "x", count: 200), provider: .cursor)
store.lastSourceLabels[.minimax] = "cookies"
store.refreshingProviders.insert(.codex)
settings.claudeCookieSource = .manual
settings.cursorCookieSource = .manual
settings.opencodeCookieSource = .manual
settings.opencodegoCookieSource = .manual
settings.factoryCookieSource = .manual
settings.minimaxCookieSource = .manual
settings.augmentCookieSource = .manual
}
private static func exercisePaneBasics(pane: ProvidersPane) {
_ = pane._test_binding(for: .codex).wrappedValue
_ = pane._test_providerSubtitle(.codex)
_ = pane._test_providerSubtitle(.claude)
_ = pane._test_providerSubtitle(.cursor)
_ = pane._test_providerSubtitle(.opencode)
_ = pane._test_providerSubtitle(.opencodego)
_ = pane._test_providerSubtitle(.zai)
_ = pane._test_providerSubtitle(.synthetic)
_ = pane._test_providerSubtitle(.minimax)
_ = pane._test_providerSubtitle(.kimi)
_ = pane._test_providerSubtitle(.gemini)
_ = pane._test_menuBarMetricPicker(for: .codex)
_ = pane._test_menuBarMetricPicker(for: .gemini)
_ = pane._test_menuBarMetricPicker(for: .zai)
if let descriptor = pane._test_tokenAccountDescriptor(for: .claude) {
_ = descriptor.isVisible?()
_ = descriptor.accounts()
}
}
private static func exerciseDetailViews(store: UsageStore, descriptors: ProviderListTestDescriptors) {
var isEnabled = true
let enabledBinding = Binding(get: { isEnabled }, set: { isEnabled = $0 })
let pane = ProvidersPane(settings: store.settings, store: store)
let model = pane._test_menuCardModel(for: .codex)
var expanded = false
let expandedBinding = Binding(get: { expanded }, set: { expanded = $0 })
_ = ProviderDetailView(
provider: .codex,
store: store,
isEnabled: enabledBinding,
subtitle: "Subtitle",
model: model,
openAIWebDiagnostic: pane._test_openAIWebDiagnostic(for: .codex),
settingsPickers: [descriptors.picker],
settingsToggles: [descriptors.toggle],
settingsFields: [descriptors.fieldPlain, descriptors.fieldSecure],
settingsTokenAccounts: descriptors.tokenAccountsEmpty,
errorDisplay: ProviderErrorDisplay(preview: "Preview", full: "Full"),
isErrorExpanded: expandedBinding,
onCopyError: { _ in },
onRefresh: {},
showsSupplementarySettingsContent: true,
supplementarySettingsContent: {
Section("Accounts") {
Text("Supplementary")
}
}).body
}
private static func makeDescriptors() -> ProviderListTestDescriptors {
let toggleBinding = Binding(get: { true }, set: { _ in })
let actionBordered = ProviderSettingsActionDescriptor(
id: "action-bordered",
title: "Bordered",
style: .bordered,
isVisible: { true },
perform: { await Task.yield() })
let actionLink = ProviderSettingsActionDescriptor(
id: "action-link",
title: "Link",
style: .link,
isVisible: { true },
perform: { await Task.yield() })
let toggle = ProviderSettingsToggleDescriptor(
id: "toggle",
title: "Toggle",
subtitle: "Toggle subtitle",
binding: toggleBinding,
statusText: { "Status" },
actions: [actionBordered, actionLink],
isVisible: { true },
onChange: nil,
onAppDidBecomeActive: nil,
onAppearWhenEnabled: nil)
let picker = ProviderSettingsPickerDescriptor(
id: "picker",
title: "Picker",
subtitle: "Picker subtitle",
dynamicSubtitle: nil,
binding: Binding(get: { "a" }, set: { _ in }),
options: [
ProviderSettingsPickerOption(id: "a", title: "Option A"),
ProviderSettingsPickerOption(id: "b", title: "Option B"),
],
isVisible: { true },
onChange: nil,
trailingText: { "Trailing" })
let fieldPlain = ProviderSettingsFieldDescriptor(
id: "plain",
title: "Field",
subtitle: "Field subtitle",
kind: .plain,
placeholder: "Placeholder",
binding: Binding(get: { "" }, set: { _ in }),
actions: [actionBordered],
isVisible: { true },
onActivate: nil)
let fieldSecure = ProviderSettingsFieldDescriptor(
id: "secure",
title: "Secure",
subtitle: "Secure subtitle",
kind: .secure,
placeholder: "Secure",
binding: Binding(get: { "" }, set: { _ in }),
actions: [actionLink],
isVisible: { true },
onActivate: nil)
let tokenAccountsEmpty = ProviderSettingsTokenAccountsDescriptor(
id: "accounts-empty",
title: "Accounts",
subtitle: "Accounts subtitle",
placeholder: "Token",
provider: .codex,
isVisible: { true },
accounts: { [] },
activeIndex: { 0 },
setActiveIndex: { _ in },
showsOrganizationField: false,
showsTeamModeControls: false,
addAccount: { _, _, _, _, _ in },
updateAccount: { _, _, _, _ in },
removeAccount: { _ in },
primaryAddActionTitle: nil,
primaryAddAction: nil,
openConfigFile: {},
reloadFromDisk: {})
return ProviderListTestDescriptors(
toggle: toggle,
picker: picker,
fieldPlain: fieldPlain,
fieldSecure: fieldSecure,
tokenAccountsEmpty: tokenAccountsEmpty)
}
}
private struct ProviderListTestDescriptors {
let toggle: ProviderSettingsToggleDescriptor
let picker: ProviderSettingsPickerDescriptor
let fieldPlain: ProviderSettingsFieldDescriptor
let fieldSecure: ProviderSettingsFieldDescriptor
let tokenAccountsEmpty: ProviderSettingsTokenAccountsDescriptor
}
#endif