feat: copy translation and dismiss with Return

This commit is contained in:
2026-10-17 23:21:51 +02:00
parent 9eb16ddd5a
commit 038a5b78a0
4 changed files with 67 additions and 8 deletions
@@ -58,6 +58,45 @@ private func descendants(_ view: NSView) -> [NSView] { [view] + view.subviews.fl
@Suite(.serialized)
struct TranslationExecutionTests {
@Test @MainActor
func primaryActionCopiesCompletedTranslationAndResetsAfterEditing() async throws {
_ = NSApplication.shared
let suite = "TranslateCopy.\(UUID().uuidString)"
let defaults = UserDefaults(suiteName: suite)!
let pasteboard = NSPasteboard.withUniqueName()
defer {
defaults.removePersistentDomain(forName: suite)
pasteboard.releaseGlobally()
}
let requests = TranslationRequests()
let tool = TranslationController(defaults: defaults,
myMemory: { try await requests.translate($0) }, pasteboard: pasteboard)
tool.input = { "Hello" }
var dismissed = false
tool.dismiss = { dismissed = true }
let button = try #require(descendants(tool.view).compactMap { $0 as? NSButton }
.first { $0.action == NSSelectorFromString("performPrimaryAction") })
button.performClick(nil)
try await waitForTranslation { requests.pending.count == 1 }
tool.performPrimaryAction()
#expect(!dismissed)
requests.pending[0].resume(returning: "こんにちは")
try await waitForTranslation { button.isEnabled }
tool.performPrimaryAction()
#expect(pasteboard.string(forType: .string) == "こんにちは")
#expect(dismissed)
dismissed = false
tool.inputChanged()
button.performClick(nil)
try await waitForTranslation { requests.pending.count == 2 }
#expect(!dismissed)
requests.pending[1].resume(returning: "再翻訳")
try await waitForTranslation { button.isEnabled }
button.performClick(nil)
#expect(pasteboard.string(forType: .string) == "再翻訳")
#expect(dismissed)
}
@Test @MainActor
func translationExecutionIsExplicitAndMyMemoryNeverTouchesCredentials() async throws {
_ = NSApplication.shared
@@ -103,7 +142,7 @@ func translationExecutionRejectsOldCompletionsWithoutClearingNewRequests() async
let views = descendants(tool.view)
let output = try #require(views.compactMap { $0 as? NSTextView }.first)
let provider = tool.providerPicker
let button = try #require(views.compactMap { $0 as? NSButton }.first { $0.action == NSSelectorFromString("translate") })
let button = try #require(views.compactMap { $0 as? NSButton }.first { $0.action == NSSelectorFromString("performPrimaryAction") })
tool.translate()
try await waitForTranslation { requests.pending.count == 1 }
input = "second"
@@ -160,7 +199,7 @@ func translationExecutionRecoversFromCredentialAndRequestFailures() async throws
let field = try #require(settingsViews.compactMap { $0 as? NSSecureTextField }.first)
let output = try #require(views.compactMap { $0 as? NSTextView }.first)
let status = try #require(views.compactMap { $0 as? NSTextField }.first { $0.accessibilityLabel() == "Translation status and errors" })
let button = try #require(views.compactMap { $0 as? NSButton }.first { $0.action == NSSelectorFromString("translate") })
let button = try #require(views.compactMap { $0 as? NSButton }.first { $0.action == NSSelectorFromString("performPrimaryAction") })
let save = try #require(settingsViews.compactMap { $0 as? NSButton }.first { $0.action == NSSelectorFromString("saveKey") })
let forget = try #require(settingsViews.compactMap { $0 as? NSButton }.first { $0.action == NSSelectorFromString("forgetKey") })
let openSettings = try #require(views.compactMap { $0 as? NSButton }.first { $0.action == NSSelectorFromString("openSettings") })