Skip to content

Commit 45b5c74

Browse files
authored
Combine completion script tests (#699)
Removes a ton of redundant completion script tests and combines unique components into a single common set of tests.
1 parent cea1a08 commit 45b5c74

File tree

5 files changed

+136
-591
lines changed

5 files changed

+136
-591
lines changed

Tests/ArgumentParserUnitTests/CompletionScriptTests.swift

+74-90
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,21 @@ import XCTest
1313
import ArgumentParserTestHelpers
1414
@testable import ArgumentParser
1515

16-
final class CompletionScriptTests: XCTestCase {
16+
fileprivate func candidates(prefix: String) -> [String] {
17+
switch CompletionShell.requesting {
18+
case CompletionShell.bash:
19+
return ["\(prefix)1_bash", "\(prefix)2_bash", "\(prefix)3_bash"]
20+
case CompletionShell.fish:
21+
return ["\(prefix)1_fish", "\(prefix)2_fish", "\(prefix)3_fish"]
22+
case CompletionShell.zsh:
23+
return ["\(prefix)1_zsh", "\(prefix)2_zsh", "\(prefix)3_zsh"]
24+
default:
25+
return []
26+
}
1727
}
1828

29+
final class CompletionScriptTests: XCTestCase {}
30+
1931
extension CompletionScriptTests {
2032
struct Path: ExpressibleByArgument {
2133
var path: String
@@ -34,38 +46,47 @@ extension CompletionScriptTests {
3446
}
3547

3648
struct NestedArguments: ParsableArguments {
37-
@Argument(completion: .custom { _ in ["t", "u", "v"] })
49+
@Argument(completion: .custom { _ in candidates(prefix: "a") })
3850
var nestedArgument: String
3951
}
4052

4153
struct Base: ParsableCommand {
4254
static let configuration = CommandConfiguration(
4355
commandName: "base-test",
44-
subcommands: [SubCommand.self]
45-
)
56+
subcommands: [SubCommand.self, HiddenChild.self, EscapedCommand.self])
4657

4758
@Option(help: "The user's name.") var name: String
4859
@Option() var kind: Kind
49-
@Option(completion: .list(["1", "2", "3"])) var otherKind: Kind
50-
60+
@Option(completion: .list(candidates(prefix: "b"))) var otherKind: Kind
61+
5162
@Option() var path1: Path
5263
@Option() var path2: Path?
53-
@Option(completion: .list(["a", "b", "c"])) var path3: Path
54-
64+
@Option(completion: .list(candidates(prefix: "c"))) var path3: Path
65+
5566
@Flag(help: .hidden) var verbose = false
5667
@Flag var allowedKinds: [Kind] = []
5768
@Flag var kindCounter: Int
5869

5970
@Option() var rep1: [String]
6071
@Option(name: [.short, .long]) var rep2: [String]
6172

62-
@Argument(completion: .custom { _ in ["q", "r", "s"] }) var argument: String
73+
@Argument(completion: .custom { _ in candidates(prefix: "d") }) var argument: String
6374
@OptionGroup var nested: NestedArguments
6475

6576
struct SubCommand: ParsableCommand {
66-
static let configuration = CommandConfiguration(
67-
commandName: "sub-command"
68-
)
77+
static let configuration = CommandConfiguration(commandName: "sub-command")
78+
}
79+
80+
struct HiddenChild: ParsableCommand {
81+
static let configuration = CommandConfiguration(shouldDisplay: false)
82+
}
83+
84+
struct EscapedCommand: ParsableCommand {
85+
@Option(help: #"Escaped chars: '[]\."#)
86+
var one: String
87+
88+
@Argument(completion: .custom { _ in candidates(prefix: "i") })
89+
var two: String
6990
}
7091
}
7192

@@ -111,112 +132,75 @@ extension CompletionScriptTests {
111132

112133
extension CompletionScriptTests {
113134
struct Custom: ParsableCommand {
114-
@Option(name: .shortAndLong, completion: .custom { _ in ["a", "b", "c"] })
135+
@Option(name: .shortAndLong, completion: .custom { _ in candidates(prefix: "e") })
115136
var one: String
116137

117-
@Argument(completion: .custom { _ in ["d", "e", "f"] })
138+
@Argument(completion: .custom { _ in candidates(prefix: "f") })
118139
var two: String
119140

120-
@Option(name: .customShort("z"), completion: .custom { _ in ["x", "y", "z"] })
141+
@Option(name: .customShort("z"), completion: .custom { _ in candidates(prefix: "g") })
121142
var three: String
122143

123144
@OptionGroup var nested: NestedArguments
124145

125146
struct NestedArguments: ParsableArguments {
126-
@Argument(completion: .custom { _ in ["g", "h", "i"] })
147+
@Argument(completion: .custom { _ in candidates(prefix: "h") })
127148
var four: String
128149
}
129150
}
130-
131-
func verifyCustomOutput(
151+
152+
func assertCustomCompletion(
132153
_ arg: String,
133-
expectedOutput: String,
134-
file: StaticString = #filePath, line: UInt = #line
154+
shell: String,
155+
prefix: String = "",
156+
file: StaticString = #filePath,
157+
line: UInt = #line
135158
) throws {
136159
do {
160+
setenv("SAP_SHELL", shell, 1)
161+
defer { unsetenv("SAP_SHELL") }
137162
_ = try Custom.parse(["---completion", "--", arg])
138-
XCTFail("Didn't error as expected", file: (file), line: line)
163+
XCTFail("Didn't error as expected", file: file, line: line)
139164
} catch let error as CommandError {
140165
guard case .completionScriptCustomResponse(let output) = error.parserError else {
141166
throw error
142167
}
143-
XCTAssertEqual(expectedOutput, output, file: (file), line: line)
168+
AssertEqualStrings(
169+
actual: output,
170+
expected: """
171+
\(prefix)1_\(shell)
172+
\(prefix)2_\(shell)
173+
\(prefix)3_\(shell)
174+
""",
175+
file: file,
176+
line: line)
144177
}
145178
}
146-
147-
func testCustomCompletions() throws {
148-
try verifyCustomOutput("-o", expectedOutput: "a\nb\nc")
149-
try verifyCustomOutput("--one", expectedOutput: "a\nb\nc")
150-
try verifyCustomOutput("two", expectedOutput: "d\ne\nf")
151-
try verifyCustomOutput("-z", expectedOutput: "x\ny\nz")
152-
try verifyCustomOutput("nested.four", expectedOutput: "g\nh\ni")
153-
154-
XCTAssertThrowsError(try verifyCustomOutput("--bad", expectedOutput: ""))
155-
XCTAssertThrowsError(try verifyCustomOutput("four", expectedOutput: ""))
156-
}
157-
}
158179

159-
extension CompletionScriptTests {
160-
struct EscapedCommand: ParsableCommand {
161-
@Option(help: #"Escaped chars: '[]\."#)
162-
var one: String
163-
164-
@Argument(completion: .custom { _ in ["d", "e", "f"] })
165-
var two: String
166-
}
167-
168-
func testEscaped_Zsh() throws {
169-
let script1 = EscapedCommand.completionScript(for: .zsh)
170-
try assertSnapshot(actual: script1, extension: "zsh")
180+
func assertCustomCompletions(
181+
shell: String,
182+
file: StaticString = #filePath,
183+
line: UInt = #line
184+
) throws {
185+
try assertCustomCompletion("-o", shell: shell, prefix: "e", file: file, line: line)
186+
try assertCustomCompletion("--one", shell: shell, prefix: "e", file: file, line: line)
187+
try assertCustomCompletion("two", shell: shell, prefix: "f", file: file, line: line)
188+
try assertCustomCompletion("-z", shell: shell, prefix: "g", file: file, line: line)
189+
try assertCustomCompletion("nested.four", shell: shell, prefix: "h", file: file, line: line)
190+
191+
XCTAssertThrowsError(try assertCustomCompletion("--bad", shell: shell, file: file, line: line))
192+
XCTAssertThrowsError(try assertCustomCompletion("four", shell: shell, file: file, line: line))
171193
}
172-
}
173194

174-
// MARK: - Test Hidden Subcommand
175-
struct Parent: ParsableCommand {
176-
static let configuration = CommandConfiguration(subcommands: [HiddenChild.self])
177-
}
178-
179-
struct HiddenChild: ParsableCommand {
180-
static let configuration = CommandConfiguration(shouldDisplay: false)
181-
}
182-
183-
extension CompletionScriptTests {
184-
func testHiddenSubcommand_Zsh() throws {
185-
let script1 = try CompletionsGenerator(command: Parent.self, shell: .zsh)
186-
.generateCompletionScript()
187-
try assertSnapshot(actual: script1, extension: "zsh")
188-
189-
let script2 = try CompletionsGenerator(command: Parent.self, shellName: "zsh")
190-
.generateCompletionScript()
191-
try assertSnapshot(actual: script2, extension: "zsh")
192-
193-
let script3 = Parent.completionScript(for: .zsh)
194-
try assertSnapshot(actual: script3, extension: "zsh")
195+
func testBashCustomCompletions() throws {
196+
try assertCustomCompletions(shell: "bash")
195197
}
196198

197-
func testHiddenSubcommand_Bash() throws {
198-
let script1 = try CompletionsGenerator(command: Parent.self, shell: .bash)
199-
.generateCompletionScript()
200-
try assertSnapshot(actual: script1, extension: "bash")
201-
202-
let script2 = try CompletionsGenerator(command: Parent.self, shellName: "bash")
203-
.generateCompletionScript()
204-
try assertSnapshot(actual: script2, extension: "bash")
205-
206-
let script3 = Parent.completionScript(for: .bash)
207-
try assertSnapshot(actual: script3, extension: "bash")
199+
func testFishCustomCompletions() throws {
200+
try assertCustomCompletions(shell: "fish")
208201
}
209202

210-
func testHiddenSubcommand_Fish() throws {
211-
let script1 = try CompletionsGenerator(command: Parent.self, shell: .fish)
212-
.generateCompletionScript()
213-
try assertSnapshot(actual: script1, extension: "fish")
214-
215-
let script2 = try CompletionsGenerator(command: Parent.self, shellName: "fish")
216-
.generateCompletionScript()
217-
try assertSnapshot(actual: script2, extension: "fish")
218-
219-
let script3 = Parent.completionScript(for: .fish)
220-
try assertSnapshot(actual: script3, extension: "fish")
203+
func testZshCustomCompletions() throws {
204+
try assertCustomCompletions(shell: "zsh")
221205
}
222206
}

0 commit comments

Comments
 (0)