637 lines
20 KiB
Swift
637 lines
20 KiB
Swift
import AppKit
|
|
import CryptoKit
|
|
import XCTest
|
|
@testable import ClipBored
|
|
|
|
final class PasteActionServiceTests: XCTestCase {
|
|
private var tempURLs: [URL] = []
|
|
|
|
override func tearDown() {
|
|
tempURLs.forEach { try? FileManager.default.removeItem(at: $0) }
|
|
tempURLs.removeAll()
|
|
super.tearDown()
|
|
}
|
|
|
|
func testCopyWritesTextToPasteboard() {
|
|
let service = PasteActionService()
|
|
let item = ClipboardItem(
|
|
id: UUID(),
|
|
kind: .text,
|
|
displayText: "Hello",
|
|
payload: "Hello",
|
|
payloadHash: "hash",
|
|
createdAt: Date(),
|
|
lastUsedAt: Date(),
|
|
useCount: 0,
|
|
sourceApp: nil,
|
|
imagePath: nil,
|
|
thumbnailPath: nil
|
|
)
|
|
|
|
XCTAssertEqual(service.copy(item), .copied)
|
|
XCTAssertEqual(NSPasteboard.general.string(forType: .string), "Hello")
|
|
}
|
|
|
|
func testCopyWritesCodeSnippetAsPlainString() {
|
|
let service = PasteActionService()
|
|
let snippet = "func greet(name: String) -> String {\n return \"Hi \\(name)\"\n}"
|
|
let item = ClipboardItem(
|
|
id: UUID(),
|
|
kind: .code,
|
|
displayText: "Swift Snippet",
|
|
payload: snippet,
|
|
payloadHash: "hash",
|
|
createdAt: Date(),
|
|
lastUsedAt: Date(),
|
|
useCount: 0,
|
|
sourceApp: "Xcode",
|
|
imagePath: nil,
|
|
thumbnailPath: nil
|
|
)
|
|
|
|
XCTAssertEqual(service.copy(item), .copied)
|
|
XCTAssertEqual(NSPasteboard.general.string(forType: .string), snippet)
|
|
}
|
|
|
|
func testPasteboardWritersExposeTextForDragOut() {
|
|
let service = PasteActionService()
|
|
let item = ClipboardItem(
|
|
id: UUID(),
|
|
kind: .text,
|
|
displayText: "Drag text",
|
|
payload: "Drag text",
|
|
payloadHash: "hash",
|
|
createdAt: Date(),
|
|
lastUsedAt: Date(),
|
|
useCount: 0,
|
|
sourceApp: nil,
|
|
imagePath: nil,
|
|
thumbnailPath: nil
|
|
)
|
|
|
|
let pasteboard = NSPasteboard.withUniqueName()
|
|
pasteboard.clearContents()
|
|
|
|
XCTAssertTrue(pasteboard.writeObjects(service.pasteboardWriters(for: item)))
|
|
XCTAssertEqual(pasteboard.string(forType: .string), "Drag text")
|
|
}
|
|
|
|
func testPasteboardWritersExposeURLAndTitleForDragOut() {
|
|
let service = PasteActionService()
|
|
let item = ClipboardItem(
|
|
id: UUID(),
|
|
kind: .url,
|
|
displayText: "Apple",
|
|
payload: "https://apple.com",
|
|
payloadHash: "hash",
|
|
createdAt: Date(),
|
|
lastUsedAt: Date(),
|
|
useCount: 0,
|
|
sourceApp: nil,
|
|
imagePath: nil,
|
|
thumbnailPath: nil
|
|
)
|
|
|
|
let pasteboard = NSPasteboard.withUniqueName()
|
|
pasteboard.clearContents()
|
|
|
|
XCTAssertTrue(pasteboard.writeObjects(service.pasteboardWriters(for: item)))
|
|
XCTAssertEqual(pasteboard.string(forType: .string), "https://apple.com")
|
|
XCTAssertEqual(pasteboard.string(forType: .URL), "https://apple.com")
|
|
XCTAssertEqual(
|
|
pasteboard.string(forType: NSPasteboard.PasteboardType(rawValue: "public.url-name")),
|
|
"Apple"
|
|
)
|
|
}
|
|
|
|
func testCopyWritesColorToPasteboardWithHexFallback() throws {
|
|
let service = PasteActionService()
|
|
let item = ClipboardItem(
|
|
id: UUID(),
|
|
kind: .color,
|
|
displayText: "#0A84FF",
|
|
payload: "#0A84FF",
|
|
payloadHash: "hash",
|
|
createdAt: Date(),
|
|
lastUsedAt: Date(),
|
|
useCount: 0,
|
|
sourceApp: nil,
|
|
imagePath: nil,
|
|
thumbnailPath: nil
|
|
)
|
|
|
|
XCTAssertEqual(service.copy(item), .copied)
|
|
let restored = try XCTUnwrap(NSColor(from: NSPasteboard.general))
|
|
XCTAssertEqual(ColorPayload.hexString(from: restored), "#0A84FF")
|
|
XCTAssertEqual(NSPasteboard.general.string(forType: .string), "#0A84FF")
|
|
XCTAssertEqual(service.copyPlainText(item), .copiedPlainText)
|
|
XCTAssertEqual(NSPasteboard.general.string(forType: .string), "#0A84FF")
|
|
}
|
|
|
|
func testPasteWithoutTargetCopiesWithoutRequestingAutomaticPaste() {
|
|
let service = PasteActionService()
|
|
let item = ClipboardItem(
|
|
id: UUID(),
|
|
kind: .text,
|
|
displayText: "No target",
|
|
payload: "No target",
|
|
payloadHash: "hash",
|
|
createdAt: Date(),
|
|
lastUsedAt: Date(),
|
|
useCount: 0,
|
|
sourceApp: nil,
|
|
imagePath: nil,
|
|
thumbnailPath: nil
|
|
)
|
|
|
|
XCTAssertEqual(service.paste(item, targetApp: nil), .copied)
|
|
XCTAssertEqual(NSPasteboard.general.string(forType: .string), "No target")
|
|
}
|
|
|
|
func testAutomaticPasteActivatesTargetAndSchedulesKeyboardPasteWhenPermissionGranted() throws {
|
|
var activatedProcessID: pid_t?
|
|
let targetApp = try makeRunningTargetApp()
|
|
var didScheduleKeyboardPaste = false
|
|
let service = PasteActionService(
|
|
accessibilityPermissionProvider: { true },
|
|
targetActivator: { app in
|
|
activatedProcessID = app.processIdentifier
|
|
return true
|
|
},
|
|
keyboardPasteScheduler: { _ in
|
|
didScheduleKeyboardPaste = true
|
|
}
|
|
)
|
|
|
|
XCTAssertEqual(service.paste(makeTextItem("Paste into target"), targetApp: targetApp), .pasted)
|
|
XCTAssertEqual(activatedProcessID, targetApp.processIdentifier)
|
|
XCTAssertTrue(didScheduleKeyboardPaste)
|
|
XCTAssertEqual(NSPasteboard.general.string(forType: .string), "Paste into target")
|
|
}
|
|
|
|
func testAutomaticPlainTextPasteActivatesTargetAndSchedulesKeyboardPasteWhenPermissionGranted() throws {
|
|
var activatedProcessID: pid_t?
|
|
let targetApp = try makeRunningTargetApp()
|
|
var didScheduleKeyboardPaste = false
|
|
let service = PasteActionService(
|
|
accessibilityPermissionProvider: { true },
|
|
targetActivator: { app in
|
|
activatedProcessID = app.processIdentifier
|
|
return true
|
|
},
|
|
keyboardPasteScheduler: { _ in
|
|
didScheduleKeyboardPaste = true
|
|
}
|
|
)
|
|
let item = ClipboardItem(
|
|
id: UUID(),
|
|
kind: .url,
|
|
displayText: "Apple",
|
|
payload: "https://apple.com",
|
|
payloadHash: "hash",
|
|
createdAt: Date(),
|
|
lastUsedAt: Date(),
|
|
useCount: 0,
|
|
sourceApp: nil,
|
|
imagePath: nil,
|
|
thumbnailPath: nil
|
|
)
|
|
|
|
XCTAssertEqual(service.pastePlainText(item, targetApp: targetApp), .pastedPlainText)
|
|
XCTAssertEqual(activatedProcessID, targetApp.processIdentifier)
|
|
XCTAssertTrue(didScheduleKeyboardPaste)
|
|
XCTAssertEqual(NSPasteboard.general.string(forType: .string), "https://apple.com")
|
|
XCTAssertNil(NSPasteboard.general.string(forType: .URL))
|
|
}
|
|
|
|
func testAutomaticPasteDoesNotPostShortcutWhenTargetActivationFails() throws {
|
|
var didAttemptActivation = false
|
|
let targetApp = try makeRunningTargetApp()
|
|
let service = PasteActionService(
|
|
accessibilityPermissionProvider: { true },
|
|
targetActivator: { _ in
|
|
didAttemptActivation = true
|
|
return false
|
|
},
|
|
keyboardPasteScheduler: { _ in
|
|
XCTFail("Keyboard paste should not be scheduled when target activation fails")
|
|
}
|
|
)
|
|
|
|
XCTAssertEqual(service.paste(makeTextItem("Activation failed"), targetApp: targetApp), .copied)
|
|
XCTAssertTrue(didAttemptActivation)
|
|
XCTAssertEqual(NSPasteboard.general.string(forType: .string), "Activation failed")
|
|
}
|
|
|
|
func testAutomaticPasteWithoutPermissionDoesNotActivateTarget() throws {
|
|
let targetApp = try makeRunningTargetApp()
|
|
let service = PasteActionService(
|
|
accessibilityPermissionProvider: { false },
|
|
targetActivator: { _ in
|
|
XCTFail("Target should not be activated without Accessibility permission")
|
|
return true
|
|
},
|
|
keyboardPasteScheduler: { _ in
|
|
XCTFail("Keyboard paste should not be scheduled without Accessibility permission")
|
|
}
|
|
)
|
|
|
|
XCTAssertEqual(service.paste(makeTextItem("Needs permission"), targetApp: targetApp), .copiedNeedsPermission)
|
|
XCTAssertEqual(NSPasteboard.general.string(forType: .string), "Needs permission")
|
|
}
|
|
|
|
func testCopyMissingFileDoesNotClearExistingPasteboard() {
|
|
let service = PasteActionService()
|
|
let board = NSPasteboard.general
|
|
board.clearContents()
|
|
XCTAssertTrue(board.setString("keep me", forType: .string))
|
|
|
|
let item = ClipboardItem(
|
|
id: UUID(),
|
|
kind: .file,
|
|
displayText: "Missing file",
|
|
payload: "/tmp/clipbored-missing-\(UUID().uuidString)",
|
|
payloadHash: "hash",
|
|
createdAt: Date(),
|
|
lastUsedAt: Date(),
|
|
useCount: 0,
|
|
sourceApp: nil,
|
|
imagePath: nil,
|
|
thumbnailPath: nil
|
|
)
|
|
|
|
XCTAssertEqual(service.copy(item), .failed("Could not write item to clipboard."))
|
|
XCTAssertEqual(board.string(forType: .string), "keep me")
|
|
}
|
|
|
|
func testCopyEmptyTextDoesNotClearExistingPasteboard() {
|
|
let service = PasteActionService()
|
|
let board = NSPasteboard.general
|
|
board.clearContents()
|
|
XCTAssertTrue(board.setString("keep me", forType: .string))
|
|
|
|
let item = ClipboardItem(
|
|
id: UUID(),
|
|
kind: .text,
|
|
displayText: "",
|
|
payload: "",
|
|
payloadHash: "hash",
|
|
createdAt: Date(),
|
|
lastUsedAt: Date(),
|
|
useCount: 0,
|
|
sourceApp: nil,
|
|
imagePath: nil,
|
|
thumbnailPath: nil
|
|
)
|
|
|
|
XCTAssertEqual(service.copy(item), .failed("Could not write item to clipboard."))
|
|
XCTAssertEqual(board.string(forType: .string), "keep me")
|
|
}
|
|
|
|
func testCopyWritesURLType() {
|
|
let service = PasteActionService()
|
|
let item = ClipboardItem(
|
|
id: UUID(),
|
|
kind: .url,
|
|
displayText: "Apple",
|
|
payload: "https://apple.com",
|
|
payloadHash: "hash",
|
|
createdAt: Date(),
|
|
lastUsedAt: Date(),
|
|
useCount: 0,
|
|
sourceApp: nil,
|
|
imagePath: nil,
|
|
thumbnailPath: nil
|
|
)
|
|
|
|
XCTAssertEqual(service.copy(item), .copied)
|
|
XCTAssertEqual(NSPasteboard.general.string(forType: .string), "https://apple.com")
|
|
XCTAssertEqual(NSPasteboard.general.string(forType: .URL), "https://apple.com")
|
|
XCTAssertEqual(
|
|
NSPasteboard.general.string(forType: NSPasteboard.PasteboardType(rawValue: "public.url-name")),
|
|
"Apple"
|
|
)
|
|
}
|
|
|
|
func testCopyWritesRichTextRTFAndPlainStringFallback() throws {
|
|
let directory = try makeTempDirectory()
|
|
let cacheService = ClipboardCacheService(baseURL: directory, encryptionService: fixedEncryptionService())
|
|
let attributed = NSAttributedString(
|
|
string: "Styled clipboard text",
|
|
attributes: [.font: NSFont.boldSystemFont(ofSize: 15)]
|
|
)
|
|
let rtfData = try XCTUnwrap(
|
|
attributed.rtf(from: NSRange(location: 0, length: attributed.length), documentAttributes: [:])
|
|
)
|
|
let path = try XCTUnwrap(cacheService.cacheRichText(rtfData, id: UUID()))
|
|
let service = PasteActionService(cacheService: cacheService)
|
|
let item = ClipboardItem(
|
|
id: UUID(),
|
|
kind: .richText,
|
|
displayText: attributed.string,
|
|
payload: path,
|
|
payloadHash: "hash",
|
|
createdAt: Date(),
|
|
lastUsedAt: Date(),
|
|
useCount: 0,
|
|
sourceApp: nil,
|
|
imagePath: nil,
|
|
thumbnailPath: nil
|
|
)
|
|
|
|
XCTAssertEqual(service.copy(item), .copied)
|
|
XCTAssertEqual(NSPasteboard.general.data(forType: .rtf), rtfData)
|
|
XCTAssertEqual(NSPasteboard.general.string(forType: .string), attributed.string)
|
|
}
|
|
|
|
func testCopyPlainTextStripsRichTextFormatting() throws {
|
|
let directory = try makeTempDirectory()
|
|
let cacheService = ClipboardCacheService(baseURL: directory, encryptionService: fixedEncryptionService())
|
|
let attributed = NSAttributedString(
|
|
string: "Styled clipboard text",
|
|
attributes: [.font: NSFont.boldSystemFont(ofSize: 15)]
|
|
)
|
|
let rtfData = try XCTUnwrap(
|
|
attributed.rtf(from: NSRange(location: 0, length: attributed.length), documentAttributes: [:])
|
|
)
|
|
let path = try XCTUnwrap(cacheService.cacheRichText(rtfData, id: UUID()))
|
|
let service = PasteActionService(cacheService: cacheService)
|
|
let item = ClipboardItem(
|
|
id: UUID(),
|
|
kind: .richText,
|
|
displayText: attributed.string,
|
|
payload: path,
|
|
payloadHash: "hash",
|
|
createdAt: Date(),
|
|
lastUsedAt: Date(),
|
|
useCount: 0,
|
|
sourceApp: nil,
|
|
imagePath: nil,
|
|
thumbnailPath: nil
|
|
)
|
|
|
|
XCTAssertEqual(service.copyPlainText(item), .copiedPlainText)
|
|
XCTAssertEqual(NSPasteboard.general.string(forType: .string), attributed.string)
|
|
XCTAssertNil(NSPasteboard.general.data(forType: .rtf))
|
|
}
|
|
|
|
func testCopyLegacyRichTextWritesPlainPayloadWhenRTFCacheIsUnavailable() {
|
|
let service = PasteActionService()
|
|
let item = ClipboardItem(
|
|
id: UUID(),
|
|
kind: .richText,
|
|
displayText: "Legacy rich text",
|
|
payload: "Legacy rich text",
|
|
payloadHash: "hash",
|
|
createdAt: Date(),
|
|
lastUsedAt: Date(),
|
|
useCount: 0,
|
|
sourceApp: nil,
|
|
imagePath: nil,
|
|
thumbnailPath: nil
|
|
)
|
|
|
|
XCTAssertEqual(service.copy(item), .copied)
|
|
XCTAssertEqual(NSPasteboard.general.string(forType: .string), "Legacy rich text")
|
|
XCTAssertNil(NSPasteboard.general.data(forType: .rtf))
|
|
}
|
|
|
|
func testCopyRichTextWithMissingCacheWritesDisplayTextInsteadOfPath() throws {
|
|
let missingPath = try makeTempDirectory().appendingPathComponent("missing-rich-text.rtf").path
|
|
let service = PasteActionService()
|
|
let item = ClipboardItem(
|
|
id: UUID(),
|
|
kind: .richText,
|
|
displayText: "Readable rich text",
|
|
payload: missingPath,
|
|
payloadHash: "hash",
|
|
createdAt: Date(),
|
|
lastUsedAt: Date(),
|
|
useCount: 0,
|
|
sourceApp: nil,
|
|
imagePath: nil,
|
|
thumbnailPath: nil
|
|
)
|
|
|
|
XCTAssertFalse(FileManager.default.fileExists(atPath: missingPath))
|
|
XCTAssertEqual(service.copy(item), .copied)
|
|
XCTAssertEqual(NSPasteboard.general.string(forType: .string), "Readable rich text")
|
|
}
|
|
|
|
func testCopyPlainTextForURLOmitsURLPasteboardTypes() {
|
|
let service = PasteActionService()
|
|
let item = ClipboardItem(
|
|
id: UUID(),
|
|
kind: .url,
|
|
displayText: "Apple",
|
|
payload: "https://apple.com",
|
|
payloadHash: "hash",
|
|
createdAt: Date(),
|
|
lastUsedAt: Date(),
|
|
useCount: 0,
|
|
sourceApp: nil,
|
|
imagePath: nil,
|
|
thumbnailPath: nil
|
|
)
|
|
|
|
XCTAssertEqual(service.copyPlainText(item), .copiedPlainText)
|
|
XCTAssertEqual(NSPasteboard.general.string(forType: .string), "https://apple.com")
|
|
XCTAssertNil(NSPasteboard.general.string(forType: .URL))
|
|
XCTAssertNil(NSPasteboard.general.string(forType: NSPasteboard.PasteboardType(rawValue: "public.url-name")))
|
|
}
|
|
|
|
func testCopyWritesFileReferenceType() throws {
|
|
let fileURL = try makeTempFile(contents: "file contents")
|
|
let service = PasteActionService()
|
|
let item = ClipboardItem(
|
|
id: UUID(),
|
|
kind: .file,
|
|
displayText: fileURL.path,
|
|
payload: fileURL.path,
|
|
payloadHash: "hash",
|
|
createdAt: Date(),
|
|
lastUsedAt: Date(),
|
|
useCount: 0,
|
|
sourceApp: nil,
|
|
imagePath: nil,
|
|
thumbnailPath: nil
|
|
)
|
|
|
|
XCTAssertEqual(service.copy(item), .copied)
|
|
let objects = NSPasteboard.general.readObjects(forClasses: [NSURL.self], options: nil) as? [URL]
|
|
XCTAssertEqual(objects?.first?.standardizedFileURL, fileURL.standardizedFileURL)
|
|
XCTAssertEqual(NSPasteboard.general.string(forType: .string), fileURL.path)
|
|
}
|
|
|
|
func testCopyWritesMultipleFileReferences() throws {
|
|
let firstURL = try makeTempFile(contents: "first file")
|
|
let secondURL = try makeTempFile(contents: "second file")
|
|
let payload = FilePayload.payload(from: [firstURL, secondURL])
|
|
let service = PasteActionService()
|
|
let item = ClipboardItem(
|
|
id: UUID(),
|
|
kind: .file,
|
|
displayText: "2 files",
|
|
payload: payload,
|
|
payloadHash: "hash",
|
|
createdAt: Date(),
|
|
lastUsedAt: Date(),
|
|
useCount: 0,
|
|
sourceApp: nil,
|
|
imagePath: nil,
|
|
thumbnailPath: nil
|
|
)
|
|
|
|
XCTAssertEqual(service.copy(item), .copied)
|
|
let objects = NSPasteboard.general.readObjects(forClasses: [NSURL.self], options: nil) as? [URL]
|
|
XCTAssertEqual(objects?.map(\.standardizedFileURL), [firstURL.standardizedFileURL, secondURL.standardizedFileURL])
|
|
XCTAssertEqual(NSPasteboard.general.string(forType: .string), payload)
|
|
}
|
|
|
|
func testCopyWritesPDFData() throws {
|
|
let pdfData = Data("%PDF-1.4\nclipbored\n%%EOF".utf8)
|
|
let fileURL = try makeTempFile(contents: pdfData)
|
|
let service = PasteActionService()
|
|
let item = ClipboardItem(
|
|
id: UUID(),
|
|
kind: .pdf,
|
|
displayText: "PDF",
|
|
payload: fileURL.path,
|
|
payloadHash: "hash",
|
|
createdAt: Date(),
|
|
lastUsedAt: Date(),
|
|
useCount: 0,
|
|
sourceApp: nil,
|
|
imagePath: nil,
|
|
thumbnailPath: nil
|
|
)
|
|
|
|
XCTAssertEqual(service.copy(item), .copied)
|
|
XCTAssertEqual(NSPasteboard.general.data(forType: .pdf), pdfData)
|
|
}
|
|
|
|
func testCopyWritesAudioData() throws {
|
|
let directory = try makeTempDirectory()
|
|
let cacheService = ClipboardCacheService(baseURL: directory, encryptionService: fixedEncryptionService())
|
|
let audioData = Data([1, 3, 5, 7, 9])
|
|
let path = try XCTUnwrap(cacheService.cacheAudio(audioData, id: UUID()))
|
|
let service = PasteActionService(cacheService: cacheService)
|
|
let item = ClipboardItem(
|
|
id: UUID(),
|
|
kind: .audio,
|
|
displayText: "Audio",
|
|
payload: path,
|
|
payloadHash: "hash",
|
|
createdAt: Date(),
|
|
lastUsedAt: Date(),
|
|
useCount: 0,
|
|
sourceApp: nil,
|
|
imagePath: nil,
|
|
thumbnailPath: nil
|
|
)
|
|
|
|
XCTAssertEqual(service.copy(item), .copied)
|
|
XCTAssertEqual(NSPasteboard.general.data(forType: .sound), audioData)
|
|
}
|
|
|
|
func testCopyWritesVideoData() throws {
|
|
let directory = try makeTempDirectory()
|
|
let cacheService = ClipboardCacheService(baseURL: directory, encryptionService: fixedEncryptionService())
|
|
let videoData = Data([0, 0, 0, 24, 102, 116, 121, 112, 109, 112, 52, 50])
|
|
let path = try XCTUnwrap(cacheService.cacheVideo(videoData, id: UUID(), fileExtension: "mp4"))
|
|
let service = PasteActionService(cacheService: cacheService)
|
|
let item = ClipboardItem(
|
|
id: UUID(),
|
|
kind: .video,
|
|
displayText: "Video",
|
|
payload: path,
|
|
payloadHash: "hash",
|
|
createdAt: Date(),
|
|
lastUsedAt: Date(),
|
|
useCount: 0,
|
|
sourceApp: nil,
|
|
imagePath: nil,
|
|
thumbnailPath: nil
|
|
)
|
|
|
|
XCTAssertEqual(service.copy(item), .copied)
|
|
XCTAssertEqual(NSPasteboard.general.data(forType: VideoPayload.pasteboardTypes[0]), videoData)
|
|
XCTAssertEqual(service.copyPlainText(item), .copiedPlainText)
|
|
XCTAssertEqual(NSPasteboard.general.string(forType: .string), "Video")
|
|
}
|
|
|
|
func testCopyWritesEncryptedPDFData() throws {
|
|
let directory = try makeTempDirectory()
|
|
let cacheService = ClipboardCacheService(baseURL: directory, encryptionService: fixedEncryptionService())
|
|
let pdfData = Data("%PDF-1.4\nencrypted clipbored\n%%EOF".utf8)
|
|
let path = try XCTUnwrap(cacheService.cachePDF(pdfData, id: UUID()))
|
|
let service = PasteActionService(cacheService: cacheService)
|
|
let item = ClipboardItem(
|
|
id: UUID(),
|
|
kind: .pdf,
|
|
displayText: "PDF",
|
|
payload: path,
|
|
payloadHash: "hash",
|
|
createdAt: Date(),
|
|
lastUsedAt: Date(),
|
|
useCount: 0,
|
|
sourceApp: nil,
|
|
imagePath: nil,
|
|
thumbnailPath: nil
|
|
)
|
|
|
|
XCTAssertTrue(ClipboardEncryptionService.isProtected(try Data(contentsOf: URL(fileURLWithPath: path))))
|
|
XCTAssertEqual(service.copy(item), .copied)
|
|
XCTAssertEqual(NSPasteboard.general.data(forType: .pdf), pdfData)
|
|
}
|
|
|
|
private func makeTempFile(contents: String) throws -> URL {
|
|
try makeTempFile(contents: Data(contents.utf8))
|
|
}
|
|
|
|
private func makeTextItem(_ value: String) -> ClipboardItem {
|
|
ClipboardItem(
|
|
id: UUID(),
|
|
kind: .text,
|
|
displayText: value,
|
|
payload: value,
|
|
payloadHash: "hash",
|
|
createdAt: Date(),
|
|
lastUsedAt: Date(),
|
|
useCount: 0,
|
|
sourceApp: nil,
|
|
imagePath: nil,
|
|
thumbnailPath: nil
|
|
)
|
|
}
|
|
|
|
private func makeRunningTargetApp() throws -> NSRunningApplication {
|
|
try XCTUnwrap(
|
|
NSWorkspace.shared.runningApplications.first {
|
|
!$0.isTerminated && $0.processIdentifier > 0
|
|
}
|
|
)
|
|
}
|
|
|
|
private func makeTempFile(contents: Data) throws -> URL {
|
|
let directory = try makeTempDirectory()
|
|
let url = directory.appendingPathComponent("payload")
|
|
try contents.write(to: url)
|
|
return url
|
|
}
|
|
|
|
private func makeTempDirectory() throws -> URL {
|
|
let directory = FileManager.default.temporaryDirectory
|
|
.appendingPathComponent("clipboredtests", isDirectory: true)
|
|
.appendingPathComponent(UUID().uuidString, isDirectory: true)
|
|
try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true)
|
|
tempURLs.append(directory)
|
|
return directory
|
|
}
|
|
|
|
private func fixedEncryptionService(byte: UInt8 = 7) -> ClipboardEncryptionService {
|
|
let keyData = Data(repeating: byte, count: 32)
|
|
return ClipboardEncryptionService(keyProvider: { SymmetricKey(data: keyData) })
|
|
}
|
|
}
|