235 lines
8.9 KiB
Swift
235 lines
8.9 KiB
Swift
import Foundation
|
|
import XCTest
|
|
@testable import TranslatorPlugin
|
|
|
|
@MainActor
|
|
final class SelectedTextCapturePipelineTests: XCTestCase {
|
|
func testFirstSuccessfulStrategyWins() async {
|
|
let pipeline = SelectedTextCapturePipeline(strategies: [
|
|
StubSelectedTextCapture(
|
|
strategyID: .accessibility,
|
|
result: SelectedTextCaptureResult(
|
|
text: nil,
|
|
strategyID: .accessibility,
|
|
isEditable: false,
|
|
sourceApplicationBundleID: "com.example.first",
|
|
failureReason: "失败"
|
|
)
|
|
),
|
|
StubSelectedTextCapture(
|
|
strategyID: .browserAppleScript,
|
|
result: SelectedTextCaptureResult(
|
|
text: "selected text",
|
|
strategyID: .browserAppleScript,
|
|
isEditable: true,
|
|
sourceApplicationBundleID: "com.example.second",
|
|
failureReason: "忽略"
|
|
)
|
|
),
|
|
StubSelectedTextCapture(
|
|
strategyID: .simulatedCopy,
|
|
result: SelectedTextCaptureResult(
|
|
text: "later text",
|
|
strategyID: .simulatedCopy,
|
|
isEditable: false,
|
|
sourceApplicationBundleID: "com.example.third",
|
|
failureReason: nil
|
|
)
|
|
),
|
|
])
|
|
|
|
let result = await pipeline.capture(context: SelectedTextCaptureContext())
|
|
|
|
XCTAssertEqual(result.text, "selected text")
|
|
XCTAssertEqual(result.strategyID, .browserAppleScript)
|
|
XCTAssertTrue(result.isEditable)
|
|
XCTAssertEqual(result.sourceApplicationBundleID, "com.example.second")
|
|
XCTAssertNil(result.failureReason)
|
|
}
|
|
|
|
func testBlankTextFallsThroughAfterTrimming() async {
|
|
let pipeline = SelectedTextCapturePipeline(strategies: [
|
|
StubSelectedTextCapture(
|
|
strategyID: .accessibility,
|
|
result: SelectedTextCaptureResult(
|
|
text: " \n\t ",
|
|
strategyID: .accessibility,
|
|
isEditable: true,
|
|
sourceApplicationBundleID: "com.example.blank",
|
|
failureReason: nil
|
|
)
|
|
),
|
|
StubSelectedTextCapture(
|
|
strategyID: .browserAppleScript,
|
|
result: SelectedTextCaptureResult(
|
|
text: "browser text",
|
|
strategyID: .browserAppleScript,
|
|
isEditable: false,
|
|
sourceApplicationBundleID: "com.apple.Safari",
|
|
failureReason: nil
|
|
)
|
|
),
|
|
])
|
|
|
|
let result = await pipeline.capture(context: SelectedTextCaptureContext())
|
|
|
|
XCTAssertEqual(result.text, "browser text")
|
|
XCTAssertEqual(result.strategyID, .browserAppleScript)
|
|
XCTAssertEqual(result.sourceApplicationBundleID, "com.apple.Safari")
|
|
}
|
|
|
|
func testBrowserContextPrefersAppleScriptOverAccessibilityText() async {
|
|
let pipeline = SelectedTextCapturePipeline(strategies: [
|
|
StubSelectedTextCapture(
|
|
strategyID: .accessibility,
|
|
result: SelectedTextCaptureResult(
|
|
text: "accessibility text",
|
|
strategyID: .accessibility,
|
|
isEditable: true,
|
|
sourceApplicationBundleID: "com.apple.Safari",
|
|
failureReason: nil
|
|
)
|
|
),
|
|
StubSelectedTextCapture(
|
|
strategyID: .browserAppleScript,
|
|
result: SelectedTextCaptureResult(
|
|
text: "browser selection",
|
|
strategyID: .browserAppleScript,
|
|
isEditable: false,
|
|
sourceApplicationBundleID: "com.apple.Safari",
|
|
failureReason: nil
|
|
)
|
|
),
|
|
])
|
|
|
|
let result = await pipeline.capture(context: SelectedTextCaptureContext(frontmostApplicationBundleID: "com.apple.Safari"))
|
|
|
|
XCTAssertEqual(result.text, "browser selection")
|
|
XCTAssertEqual(result.strategyID, .browserAppleScript)
|
|
}
|
|
|
|
func testBrowserContextFallsBackToAccessibilityWhenAppleScriptFails() async {
|
|
let pipeline = SelectedTextCapturePipeline(strategies: [
|
|
StubSelectedTextCapture(
|
|
strategyID: .accessibility,
|
|
result: SelectedTextCaptureResult(
|
|
text: "accessibility fallback",
|
|
strategyID: .accessibility,
|
|
isEditable: true,
|
|
sourceApplicationBundleID: "com.apple.Safari",
|
|
failureReason: nil
|
|
)
|
|
),
|
|
StubSelectedTextCapture(
|
|
strategyID: .browserAppleScript,
|
|
result: SelectedTextCaptureResult(
|
|
text: nil,
|
|
strategyID: .browserAppleScript,
|
|
isEditable: false,
|
|
sourceApplicationBundleID: "com.apple.Safari",
|
|
failureReason: "自动化取词失败"
|
|
)
|
|
),
|
|
])
|
|
|
|
let result = await pipeline.capture(context: SelectedTextCaptureContext(frontmostApplicationBundleID: "com.apple.Safari"))
|
|
|
|
XCTAssertEqual(result.text, "accessibility fallback")
|
|
XCTAssertEqual(result.strategyID, .accessibility)
|
|
}
|
|
|
|
func testAllFailuresReturnsMissingSelection() async {
|
|
let pipeline = SelectedTextCapturePipeline(strategies: [
|
|
StubSelectedTextCapture(
|
|
strategyID: .accessibility,
|
|
result: SelectedTextCaptureResult(
|
|
text: nil,
|
|
strategyID: .accessibility,
|
|
isEditable: false,
|
|
sourceApplicationBundleID: nil,
|
|
failureReason: "失败"
|
|
)
|
|
),
|
|
StubSelectedTextCapture(
|
|
strategyID: .simulatedCopy,
|
|
result: SelectedTextCaptureResult(
|
|
text: nil,
|
|
strategyID: .simulatedCopy,
|
|
isEditable: false,
|
|
sourceApplicationBundleID: nil,
|
|
failureReason: "复制失败"
|
|
)
|
|
),
|
|
])
|
|
|
|
let result = await pipeline.capture(context: SelectedTextCaptureContext())
|
|
|
|
XCTAssertEqual(result, .missing)
|
|
XCTAssertEqual(result.failureReason, "未找到选中文本")
|
|
}
|
|
|
|
func testPermissionRequiredFailureIsPreservedWhenNoStrategySucceeds() async {
|
|
let pipeline = SelectedTextCapturePipeline(strategies: [
|
|
StubSelectedTextCapture(
|
|
strategyID: .accessibility,
|
|
result: SelectedTextCaptureResult(
|
|
text: nil,
|
|
strategyID: .accessibility,
|
|
isEditable: false,
|
|
sourceApplicationBundleID: "com.example.secure",
|
|
failureReason: "需要辅助功能授权"
|
|
)
|
|
),
|
|
StubSelectedTextCapture(
|
|
strategyID: .simulatedCopy,
|
|
result: SelectedTextCaptureResult(
|
|
text: nil,
|
|
strategyID: .simulatedCopy,
|
|
isEditable: false,
|
|
sourceApplicationBundleID: nil,
|
|
failureReason: "复制失败"
|
|
)
|
|
),
|
|
])
|
|
|
|
let result = await pipeline.capture(context: SelectedTextCaptureContext())
|
|
|
|
XCTAssertNil(result.text)
|
|
XCTAssertEqual(result.strategyID, .accessibility)
|
|
XCTAssertFalse(result.isEditable)
|
|
XCTAssertEqual(result.sourceApplicationBundleID, "com.example.secure")
|
|
XCTAssertEqual(result.failureReason, "需要辅助功能授权")
|
|
}
|
|
|
|
func testReturnedTextIsTrimmed() async {
|
|
let pipeline = SelectedTextCapturePipeline(strategies: [
|
|
StubSelectedTextCapture(
|
|
strategyID: .simulatedCopy,
|
|
result: SelectedTextCaptureResult(
|
|
text: "\n trimmed text \t",
|
|
strategyID: .simulatedCopy,
|
|
isEditable: false,
|
|
sourceApplicationBundleID: "com.example.app",
|
|
failureReason: nil
|
|
)
|
|
),
|
|
])
|
|
|
|
let result = await pipeline.capture(context: SelectedTextCaptureContext())
|
|
|
|
XCTAssertEqual(result.text, "trimmed text")
|
|
XCTAssertEqual(result.strategyID, .simulatedCopy)
|
|
XCTAssertEqual(result.sourceApplicationBundleID, "com.example.app")
|
|
XCTAssertNil(result.failureReason)
|
|
}
|
|
}
|
|
|
|
private struct StubSelectedTextCapture: SelectedTextCapturing {
|
|
let strategyID: SelectedTextCaptureStrategyID
|
|
let result: SelectedTextCaptureResult
|
|
|
|
func capture(context: SelectedTextCaptureContext) async -> SelectedTextCaptureResult {
|
|
result
|
|
}
|
|
}
|