// AIAgentSkillLayoutTests.swift // OSGKeyboardTests @testable import OSGKeyboardShared import XCTest @MainActor final class AIAgentSkillLayoutTests: XCTestCase { private func makeDefaults() -> UserDefaults { let suite = "group.com.osgkeyboard.shared.tests.skills.\(UUID().uuidString)" let defaults = UserDefaults(suiteName: suite)! defaults.removePersistentDomain(forName: suite) return defaults } func testFreshInstallEnablesDefaultTransformSkills() { let defaults = makeDefaults() let layout = AppGroupStore(defaults: defaults).agentSkillLayout XCTAssertEqual(layout.enabledIDs, AIAgentSkillLayout.defaultEnabledIDs) XCTAssertTrue(layout.confirmedShortcutIDs.isEmpty) } func testEmptyEnabledListIsPreserved() { let defaults = makeDefaults() let store = AppGroupStore(defaults: defaults) store.setAgentSkillLayout( AIAgentSkillLayout(enabledIDs: [], confirmedShortcutIDs: []) ) XCTAssertEqual(store.agentSkillLayout.enabledIDs, []) } func testCannotEnableExportSkillBeforeShortcutConfirmation() { let store = AIAgentSkillLayoutStore(defaults: makeDefaults()) XCTAssertEqual( store.enable(AIClipboardSkillCatalog.extractTodosID), .needsShortcut ) XCTAssertFalse(store.layout.isEnabled(AIClipboardSkillCatalog.extractTodosID)) } func testConfirmShortcutAutoEnablesWhenSlotAvailable() { let store = AIAgentSkillLayoutStore(defaults: makeDefaults()) XCTAssertEqual( store.confirmShortcutAndEnable(AIClipboardSkillCatalog.extractTodosID), .enabled ) XCTAssertTrue(store.layout.hasConfirmedShortcut(AIClipboardSkillCatalog.extractTodosID)) XCTAssertEqual( store.layout.enabledIDs.last, AIClipboardSkillCatalog.extractTodosID ) } func testSanitizedDropsUnconfirmedExportAndUnknownIDs() { let layout = AIAgentSkillLayout( enabledIDs: ["reply", "extractTodos", "unknown"], confirmedShortcutIDs: [] ).sanitized() XCTAssertEqual(layout.enabledIDs, ["reply"]) } func testSanitizedKeepsConfirmedExport() { let layout = AIAgentSkillLayout( enabledIDs: ["reply", "extractTodos"], confirmedShortcutIDs: ["extractTodos"] ).sanitized() XCTAssertEqual(layout.enabledIDs, ["reply", "extractTodos"]) } func testIsFullUsesEnabledCount() { let full = AIAgentSkillLayout( enabledIDs: (0..")) let items = URLComponents(url: url!, resolvingAgainstBaseURL: false)?.queryItems ?? [] XCTAssertEqual(items.first { $0.name == "text" }?.value, text) XCTAssertTrue(text.contains("||OSG_NOTE||")) } func testShortcutsRunURLIncludesNameAndText() { let shortcutName = AIClipboardSkillCatalog.extractTodosShortcutName let url = AIAgentShortcutRun.shortcutsRunURL(name: shortcutName, text: "买牛奶\n回邮件") XCTAssertEqual(url?.scheme, "shortcuts") XCTAssertEqual(url?.host, "run-shortcut") let items = URLComponents(url: url!, resolvingAgainstBaseURL: false)?.queryItems ?? [] XCTAssertEqual(items.first { $0.name == "name" }?.value, "OSGExtractTodos") XCTAssertEqual(items.first { $0.name == "input" }?.value, "text") XCTAssertEqual(items.first { $0.name == "text" }?.value, "买牛奶\n回邮件") XCTAssertNil(items.first { $0.name == "x-success" }) } func testXCallbackRunURLUsesCallbackHost() { let url = AIAgentShortcutRun.shortcutsRunURL( name: AIClipboardSkillCatalog.extractTodosShortcutName, text: "买牛奶", xSuccess: "osgkeyboard://skill/shortcut-result?status=success", xError: "osgkeyboard://skill/shortcut-result?status=error", xCancel: "osgkeyboard://skill/shortcut-result?status=cancel" ) XCTAssertEqual(url?.scheme, "shortcuts") XCTAssertEqual(url?.host, "x-callback-url") XCTAssertEqual(url?.path, "/run-shortcut") let items = URLComponents(url: url!, resolvingAgainstBaseURL: false)?.queryItems ?? [] XCTAssertEqual(items.first { $0.name == "text" }?.value, "买牛奶") XCTAssertEqual( items.first { $0.name == "x-success" }?.value, "osgkeyboard://skill/shortcut-result?status=success" ) } func testPreviewEscapesNewlines() { XCTAssertEqual(AIAgentShortcutRun.preview("买牛奶\n回邮件"), "买牛奶\\n回邮件") } func testExtractTodosUsesBundledShortcut() { let skill = AIClipboardSkillCatalog.skill(id: AIClipboardSkillCatalog.extractTodosID) XCTAssertNil(skill?.shortcutICloudURL) XCTAssertEqual(skill?.shortcutName, "OSGExtractTodos") XCTAssertEqual(skill?.shortcutResourceName, "OSGExtractTodos") } func testExtractEventsUsesBundledShortcut() { let skill = AIClipboardSkillCatalog.skill(id: AIClipboardSkillCatalog.extractEventsID) XCTAssertNil(skill?.shortcutICloudURL) XCTAssertEqual(skill?.shortcutName, "OSGExtractEvents") XCTAssertEqual( skill?.shortcutResourceName, "OSGExtractEvents" ) XCTAssertEqual(skill?.systemImage, "calendar") XCTAssertFalse(skill?.isDefault ?? true) } func testNavigateDoesNotRequireShortcut() { let skill = AIClipboardSkillCatalog.skill(id: AIClipboardSkillCatalog.navigateID) XCTAssertNil(skill?.shortcutName) XCTAssertNil(skill?.shortcutICloudURL) XCTAssertNil(skill?.shortcutResourceName) XCTAssertEqual( skill?.systemImage, "arrow.triangle.turn.up.right.diamond.fill" ) XCTAssertFalse(skill?.isDefault ?? true) XCTAssertEqual(skill?.kind, .export) XCTAssertFalse(skill?.requiresShortcut ?? true) } func testNavigateEnablesWithoutShortcutConfirmation() { let store = AIAgentSkillLayoutStore(defaults: makeDefaults()) XCTAssertEqual( store.enable(AIClipboardSkillCatalog.navigateID), .enabled ) XCTAssertTrue(store.layout.isEnabled(AIClipboardSkillCatalog.navigateID)) } func testSaveToNotesUsesBundledShortcutUntilICloudShareExists() { let skill = AIClipboardSkillCatalog.skill(id: AIClipboardSkillCatalog.saveToNotesID) XCTAssertNil(skill?.shortcutICloudURL) XCTAssertEqual(skill?.shortcutName, "OSGSaveToNotes") XCTAssertEqual(skill?.shortcutResourceName, "OSGSaveToNotes") XCTAssertEqual(skill?.systemImage, "note.text") XCTAssertFalse(skill?.isDefault ?? true) XCTAssertTrue(skill?.requiresShortcut ?? false) } func testCannotEnableSaveToNotesBeforeShortcutConfirmation() { let store = AIAgentSkillLayoutStore(defaults: makeDefaults()) XCTAssertEqual( store.enable(AIClipboardSkillCatalog.saveToNotesID), .needsShortcut ) XCTAssertFalse(store.layout.isEnabled(AIClipboardSkillCatalog.saveToNotesID)) } func testICloudShareLinkMapsToShortcutsInstallURL() { let share = URL(string: "https://www.icloud.com/shortcuts/65bf33ba4206484ba78d582eaf1e9c44")! let url = AIAgentShortcutRun.shortcutsInstallURL(from: share) XCTAssertEqual(url?.scheme, "shortcuts") XCTAssertEqual(url?.host, "shortcuts") XCTAssertEqual(url?.path, "/65bf33ba4206484ba78d582eaf1e9c44") XCTAssertEqual( AIAgentShortcutRun.iCloudShareToken(from: share), "65bf33ba4206484ba78d582eaf1e9c44" ) } }