154 lines
6.6 KiB
Swift
154 lines
6.6 KiB
Swift
import CodexBarCore
|
|
import Foundation
|
|
import Testing
|
|
@testable import CodexBar
|
|
|
|
@Suite(.serialized)
|
|
@MainActor
|
|
struct CodexSystemPromotionUITests {
|
|
@Test
|
|
func `promotion coordinator promotes immediately`() async throws {
|
|
let container = try CodexAccountPromotionTestContainer(
|
|
suiteName: "CodexSystemPromotionUITests-coordinator-immediate")
|
|
defer { container.tearDown() }
|
|
|
|
let target = try container.createManagedAccount(
|
|
persistedEmail: "managed@example.com",
|
|
authAccountID: "acct-managed")
|
|
try container.persistAccounts([target])
|
|
_ = try container.writeLiveOAuthAuthFile(email: "live@example.com", accountID: "acct-live")
|
|
|
|
let managedVisibleAccountID = try #require(container.settings.codexVisibleAccountProjection.visibleAccounts
|
|
.first(where: { $0.storedAccountID == target.id })?
|
|
.id)
|
|
let coordinator = CodexAccountPromotionCoordinator(service: container.makeService())
|
|
|
|
let result = await coordinator.promote(managedAccountID: target.id)
|
|
|
|
let promotionResult: CodexAccountPromotionResult
|
|
switch result {
|
|
case let .success(value):
|
|
promotionResult = value
|
|
case let .failure(error):
|
|
Issue.record("Expected successful promotion, got \(error)")
|
|
throw PromotionTestError.unexpectedDisposition
|
|
}
|
|
|
|
#expect(promotionResult.outcome == .promoted)
|
|
#expect(container.settings.codexActiveSource == .liveSystem)
|
|
#expect(container.settings.codexVisibleAccountProjection.liveVisibleAccountID == managedVisibleAccountID)
|
|
#expect(coordinator.userFacingError == nil)
|
|
}
|
|
|
|
@Test
|
|
func `promotion coordinator blocks while live reauthentication is running`() async throws {
|
|
let container = try CodexAccountPromotionTestContainer(
|
|
suiteName: "CodexSystemPromotionUITests-coordinator-live-reauth")
|
|
defer { container.tearDown() }
|
|
|
|
let target = try container.createManagedAccount(
|
|
persistedEmail: "managed@example.com",
|
|
authAccountID: "acct-managed")
|
|
try container.persistAccounts([target])
|
|
_ = try container.writeLiveOAuthAuthFile(email: "live@example.com", accountID: "acct-live")
|
|
container.settings.codexActiveSource = .managedAccount(id: target.id)
|
|
|
|
let coordinator = CodexAccountPromotionCoordinator(service: container.makeService())
|
|
coordinator.setLiveReauthenticationInProgress(true)
|
|
|
|
let result = await coordinator.promote(managedAccountID: target.id)
|
|
|
|
let error: CodexSystemAccountPromotionUserFacingError
|
|
switch result {
|
|
case .success:
|
|
Issue.record("Expected blocked promotion while live reauthentication is running")
|
|
throw PromotionTestError.unexpectedDisposition
|
|
case let .failure(value):
|
|
error = value
|
|
}
|
|
|
|
#expect(error.title == "Could not switch system account")
|
|
#expect(error.message == "Finish the current managed account change before switching the system account.")
|
|
#expect(coordinator.userFacingError == error)
|
|
#expect(coordinator.isInteractionBlocked())
|
|
#expect(container.settings.codexActiveSource == .managedAccount(id: target.id))
|
|
}
|
|
|
|
@Test
|
|
func `codex menu descriptor includes system account submenu`() throws {
|
|
let container = try CodexAccountPromotionTestContainer(
|
|
suiteName: "CodexSystemPromotionUITests-menu-descriptor")
|
|
defer { container.tearDown() }
|
|
|
|
let managedAccountID = UUID()
|
|
let managedAccount = try container.createManagedAccount(
|
|
id: managedAccountID,
|
|
persistedEmail: "managed@example.com",
|
|
authAccountID: "acct-managed")
|
|
try container.persistAccounts([managedAccount])
|
|
container.settings._test_liveSystemCodexAccount = ObservedSystemCodexAccount(
|
|
email: "live@example.com",
|
|
codexHomePath: container.liveHomeURL.path,
|
|
observedAt: Date())
|
|
|
|
let descriptor = MenuDescriptor.build(
|
|
provider: .codex,
|
|
store: container.usageStore,
|
|
settings: container.settings,
|
|
account: UsageFetcher().loadAccountInfo(),
|
|
managedCodexAccountCoordinator: ManagedCodexAccountCoordinator(),
|
|
codexAccountPromotionCoordinator: CodexAccountPromotionCoordinator(
|
|
service: container.makeService()),
|
|
updateReady: false)
|
|
|
|
let submenu = try #require(descriptor.sections
|
|
.flatMap(\.entries)
|
|
.compactMap { entry -> (String, String?, [MenuDescriptor.SubmenuItem])? in
|
|
guard case let .submenu(title, systemImageName, items) = entry else { return nil }
|
|
return (title, systemImageName, items)
|
|
}
|
|
.first(where: { $0.0 == "System Account" }))
|
|
|
|
#expect(submenu.1 == MenuDescriptor.MenuActionSystemImage.systemAccount.rawValue)
|
|
#expect(submenu.2.map(\.title) == ["live@example.com", "managed@example.com"])
|
|
#expect(submenu.2.count == 2)
|
|
#expect(submenu.2[0].isChecked)
|
|
#expect(submenu.2[0].isEnabled == false)
|
|
#expect(submenu.2[0].action == nil)
|
|
#expect(submenu.2[1].isChecked == false)
|
|
#expect(submenu.2[1].isEnabled)
|
|
#expect(submenu.2[1].action == .requestCodexSystemPromotion(managedAccountID))
|
|
}
|
|
|
|
@Test
|
|
func `codex menu descriptor hides single live system account submenu`() throws {
|
|
let container = try CodexAccountPromotionTestContainer(
|
|
suiteName: "CodexSystemPromotionUITests-menu-single-live")
|
|
defer { container.tearDown() }
|
|
|
|
container.settings._test_liveSystemCodexAccount = ObservedSystemCodexAccount(
|
|
email: "live@example.com",
|
|
codexHomePath: container.liveHomeURL.path,
|
|
observedAt: Date())
|
|
|
|
let descriptor = MenuDescriptor.build(
|
|
provider: .codex,
|
|
store: container.usageStore,
|
|
settings: container.settings,
|
|
account: UsageFetcher().loadAccountInfo(),
|
|
managedCodexAccountCoordinator: ManagedCodexAccountCoordinator(),
|
|
codexAccountPromotionCoordinator: CodexAccountPromotionCoordinator(
|
|
service: container.makeService()),
|
|
updateReady: false)
|
|
|
|
let hasSystemAccountSubmenu = descriptor.sections
|
|
.flatMap(\.entries)
|
|
.contains { entry in
|
|
guard case let .submenu(title, _, _) = entry else { return false }
|
|
return title == "System Account"
|
|
}
|
|
|
|
#expect(!hasSystemAccountSubmenu)
|
|
}
|
|
}
|