@@ -13,9 +13,21 @@ import XCTest
13
13
import ArgumentParserTestHelpers
14
14
@testable import ArgumentParser
15
15
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
+ }
17
27
}
18
28
29
+ final class CompletionScriptTests : XCTestCase { }
30
+
19
31
extension CompletionScriptTests {
20
32
struct Path : ExpressibleByArgument {
21
33
var path : String
@@ -34,38 +46,47 @@ extension CompletionScriptTests {
34
46
}
35
47
36
48
struct NestedArguments : ParsableArguments {
37
- @Argument ( completion: . custom { _ in [ " t " , " u " , " v " ] } )
49
+ @Argument ( completion: . custom { _ in candidates ( prefix : " a " ) } )
38
50
var nestedArgument : String
39
51
}
40
52
41
53
struct Base : ParsableCommand {
42
54
static let configuration = CommandConfiguration (
43
55
commandName: " base-test " ,
44
- subcommands: [ SubCommand . self]
45
- )
56
+ subcommands: [ SubCommand . self, HiddenChild . self, EscapedCommand . self] )
46
57
47
58
@Option ( help: " The user's name. " ) var name : String
48
59
@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
+
51
62
@Option ( ) var path1 : Path
52
63
@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
+
55
66
@Flag ( help: . hidden) var verbose = false
56
67
@Flag var allowedKinds : [ Kind ] = [ ]
57
68
@Flag var kindCounter : Int
58
69
59
70
@Option ( ) var rep1 : [ String ]
60
71
@Option ( name: [ . short, . long] ) var rep2 : [ String ]
61
72
62
- @Argument ( completion: . custom { _ in [ " q " , " r " , " s " ] } ) var argument : String
73
+ @Argument ( completion: . custom { _ in candidates ( prefix : " d " ) } ) var argument : String
63
74
@OptionGroup var nested : NestedArguments
64
75
65
76
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
69
90
}
70
91
}
71
92
@@ -111,112 +132,75 @@ extension CompletionScriptTests {
111
132
112
133
extension CompletionScriptTests {
113
134
struct Custom : ParsableCommand {
114
- @Option ( name: . shortAndLong, completion: . custom { _ in [ " a " , " b " , " c " ] } )
135
+ @Option ( name: . shortAndLong, completion: . custom { _ in candidates ( prefix : " e " ) } )
115
136
var one : String
116
137
117
- @Argument ( completion: . custom { _ in [ " d " , " e " , " f " ] } )
138
+ @Argument ( completion: . custom { _ in candidates ( prefix : " f " ) } )
118
139
var two : String
119
140
120
- @Option ( name: . customShort( " z " ) , completion: . custom { _ in [ " x " , " y " , " z " ] } )
141
+ @Option ( name: . customShort( " z " ) , completion: . custom { _ in candidates ( prefix : " g " ) } )
121
142
var three : String
122
143
123
144
@OptionGroup var nested : NestedArguments
124
145
125
146
struct NestedArguments : ParsableArguments {
126
- @Argument ( completion: . custom { _ in [ " g " , " h " , " i " ] } )
147
+ @Argument ( completion: . custom { _ in candidates ( prefix : " h " ) } )
127
148
var four : String
128
149
}
129
150
}
130
-
131
- func verifyCustomOutput (
151
+
152
+ func assertCustomCompletion (
132
153
_ 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
135
158
) throws {
136
159
do {
160
+ setenv ( " SAP_SHELL " , shell, 1 )
161
+ defer { unsetenv ( " SAP_SHELL " ) }
137
162
_ = 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)
139
164
} catch let error as CommandError {
140
165
guard case . completionScriptCustomResponse( let output) = error. parserError else {
141
166
throw error
142
167
}
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)
144
177
}
145
178
}
146
-
147
- func testCustomCompletions( ) throws {
148
- try verifyCustomOutput ( " -o " , expectedOutput: " a \n b \n c " )
149
- try verifyCustomOutput ( " --one " , expectedOutput: " a \n b \n c " )
150
- try verifyCustomOutput ( " two " , expectedOutput: " d \n e \n f " )
151
- try verifyCustomOutput ( " -z " , expectedOutput: " x \n y \n z " )
152
- try verifyCustomOutput ( " nested.four " , expectedOutput: " g \n h \n i " )
153
-
154
- XCTAssertThrowsError ( try verifyCustomOutput ( " --bad " , expectedOutput: " " ) )
155
- XCTAssertThrowsError ( try verifyCustomOutput ( " four " , expectedOutput: " " ) )
156
- }
157
- }
158
179
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) )
171
193
}
172
- }
173
194
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 " )
195
197
}
196
198
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 " )
208
201
}
209
202
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 " )
221
205
}
222
206
}
0 commit comments