Commit b255639dd5
Verified · cmc
Layout: unified · split
Tests/KeycaskCLITests/ClipboardTests.swift +101
| @@ -64,4 +64,105 @@ import Testing | |||
| 64 | let r = try cli.run(["clip", "nope"]) | 64 | let r = try cli.run(["clip", "nope"]) |
| 65 | #expect(r.status == 3) | 65 | #expect(r.status == 3) |
| 66 | } | 66 | } |
| 67 | |||
| 68 | #if !os(Windows) | ||
| 69 | /// A temp directory of clipboard tools backed by a file, so tests never | ||
| 70 | /// touch the real clipboard. | ||
| 71 | struct Stub { | ||
| 72 | let dir: URL | ||
| 73 | |||
| 74 | var file: URL { dir.appendingPathComponent("clip.txt") } | ||
| 75 | var environment: [String: String] { ["PATH": "\(dir.path):/bin:/usr/bin"] } | ||
| 76 | |||
| 77 | init() throws { | ||
| 78 | dir = FileManager.default.temporaryDirectory | ||
| 79 | .appendingPathComponent("keycask-clip-stub-\(UUID().uuidString)") | ||
| 80 | try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) | ||
| 81 | #if os(macOS) | ||
| 82 | try install("pbcopy", "#!/bin/sh\ncat > \"$(dirname \"$0\")/clip.txt\"\n") | ||
| 83 | try install( | ||
| 84 | "pbpaste", "#!/bin/sh\ncat \"$(dirname \"$0\")/clip.txt\" 2>/dev/null\n") | ||
| 85 | #else | ||
| 86 | try install( | ||
| 87 | "xclip", | ||
| 88 | """ | ||
| 89 | #!/bin/sh | ||
| 90 | for a in "$@"; do | ||
| 91 | if [ "$a" = "-o" ]; then | ||
| 92 | cat "$(dirname "$0")/clip.txt" 2>/dev/null | ||
| 93 | exit 0 | ||
| 94 | fi | ||
| 95 | done | ||
| 96 | cat > "$(dirname "$0")/clip.txt" | ||
| 97 | |||
| 98 | """) | ||
| 99 | #endif | ||
| 100 | } | ||
| 101 | |||
| 102 | func contents() -> String { | ||
| 103 | (try? String(contentsOf: file, encoding: .utf8)) ?? "" | ||
| 104 | } | ||
| 105 | |||
| 106 | func set(_ text: String) throws { | ||
| 107 | try Data(text.utf8).write(to: file) | ||
| 108 | } | ||
| 109 | |||
| 110 | private func install(_ name: String, _ script: String) throws { | ||
| 111 | let url = dir.appendingPathComponent(name) | ||
| 112 | try Data(script.utf8).write(to: url) | ||
| 113 | try FileManager.default.setAttributes( | ||
| 114 | [.posixPermissions: 0o755], ofItemAtPath: url.path) | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | @Test func clipCopiesTheFieldThroughTheTool() throws { | ||
| 119 | let cli = try CLI.initialized() | ||
| 120 | let stub = try Stub() | ||
| 121 | try cli.run(["add", "t", "--generate"]) | ||
| 122 | let expected = try cli.run(["show", "t", "--field", "password"]).stdout | ||
| 123 | .trimmingCharacters(in: .whitespacesAndNewlines) | ||
| 124 | |||
| 125 | let start = Date() | ||
| 126 | let r = try cli.run(["clip", "t"], extraEnvironment: stub.environment) | ||
| 127 | let elapsed = Date().timeIntervalSince(start) | ||
| 128 | |||
| 129 | #expect(r.status == 0) | ||
| 130 | #expect(r.stdout.contains("copied password of t")) | ||
| 131 | #expect(stub.contents() == expected) | ||
| 132 | #expect(elapsed < 5) | ||
| 133 | } | ||
| 134 | |||
| 135 | @Test func generateCopyWritesTheTool() throws { | ||
| 136 | let cli = try CLI() | ||
| 137 | let stub = try Stub() | ||
| 138 | let r = try cli.run( | ||
| 139 | ["generate", "--copy"], passphrase: nil, extraEnvironment: stub.environment) | ||
| 140 | #expect(r.status == 0) | ||
| 141 | let copied = stub.contents() | ||
| 142 | #expect(copied.count == 24) | ||
| 143 | #expect(!r.stdout.contains(copied)) | ||
| 144 | } | ||
| 145 | |||
| 146 | @Test func daemonClearsWhenClipboardStillHoldsSecret() throws { | ||
| 147 | let cli = try CLI() | ||
| 148 | let stub = try Stub() | ||
| 149 | try stub.set("probe") | ||
| 150 | let r = try cli.run( | ||
| 151 | ["clipboard-daemon", "1"], stdin: #"{"secret":"probe"}"#, passphrase: nil, | ||
| 152 | extraEnvironment: stub.environment) | ||
| 153 | #expect(r.status == 0) | ||
| 154 | #expect(stub.contents() == "") | ||
| 155 | } | ||
| 156 | |||
| 157 | @Test func daemonLeavesForeignContentAlone() throws { | ||
| 158 | let cli = try CLI() | ||
| 159 | let stub = try Stub() | ||
| 160 | try stub.set("other") | ||
| 161 | let r = try cli.run( | ||
| 162 | ["clipboard-daemon", "1"], stdin: #"{"secret":"probe"}"#, passphrase: nil, | ||
| 163 | extraEnvironment: stub.environment) | ||
| 164 | #expect(r.status == 0) | ||
| 165 | #expect(stub.contents() == "other") | ||
| 166 | } | ||
| 167 | #endif | ||
| 67 | } | 168 | } |