@@ -57,6 +57,73 @@ extension UnparsedValuesEndToEndTests {
5757 }
5858}
5959
60+ // MARK: Two value + unparsed optional variable
61+
62+ fileprivate struct Hogeraa : ParsableArguments {
63+ var fullName : String ? = " Full Name "
64+ }
65+
66+ fileprivate struct Hogera : ParsableArguments {
67+ @Option ( ) var firstName : String
68+ @Flag ( ) var hasLastName = false
69+ var fullName : String ?
70+ mutating func validate( ) throws {
71+ if hasLastName { fullName = " \( firstName) LastName " }
72+ }
73+ }
74+
75+ fileprivate struct Piyo : ParsableArguments {
76+ @Option ( ) var firstName : String
77+ @Flag ( ) var hasLastName = false
78+ var fullName : String !
79+ mutating func validate( ) throws {
80+ fullName = firstName + ( hasLastName ? " LastName " : " " )
81+ }
82+ }
83+
84+ extension UnparsedValuesEndToEndTests {
85+ func testParsing_TwoPlusOptionalUnparsed( ) throws {
86+ AssertParse ( Hogeraa . self, [ ] ) { hogeraa in
87+ XCTAssertEqual ( hogeraa. fullName, " Full Name " )
88+ }
89+
90+ AssertParse ( Hogera . self, [ " --first-name " , " Hogera " ] ) { hogera in
91+ XCTAssertEqual ( hogera. firstName, " Hogera " )
92+ XCTAssertFalse ( hogera. hasLastName)
93+ XCTAssertNil ( hogera. fullName)
94+ }
95+ AssertParse ( Hogera . self, [ " --first-name " , " Hogera " , " --has-last-name " ] ) { hogera in
96+ XCTAssertEqual ( hogera. firstName, " Hogera " )
97+ XCTAssertTrue ( hogera. hasLastName)
98+ XCTAssertEqual ( hogera. fullName, " Hogera LastName " )
99+ }
100+
101+ AssertParse ( Piyo . self, [ " --first-name " , " Hogera " ] ) { piyo in
102+ XCTAssertEqual ( piyo. firstName, " Hogera " )
103+ XCTAssertFalse ( piyo. hasLastName)
104+ XCTAssertEqual ( piyo. fullName, " Hogera " )
105+ }
106+ AssertParse ( Piyo . self, [ " --first-name " , " Hogera " , " --has-last-name " ] ) { piyo in
107+ XCTAssertEqual ( piyo. firstName, " Hogera " )
108+ XCTAssertTrue ( piyo. hasLastName)
109+ XCTAssertEqual ( piyo. fullName, " Hogera LastName " )
110+ }
111+ }
112+
113+ func testParsing_TwoPlusOptionalUnparsed_Fails( ) throws {
114+ XCTAssertThrowsError ( try Hogeraa . parse ( [ " --full-name " ] ) )
115+ XCTAssertThrowsError ( try Hogeraa . parse ( [ " --full-name " , " Hogera Piyo " ] ) )
116+ XCTAssertThrowsError ( try Hogera . parse ( [ ] ) )
117+ XCTAssertThrowsError ( try Hogera . parse ( [ " --first-name " ] ) )
118+ XCTAssertThrowsError ( try Hogera . parse ( [ " --first-name " , " Hogera " , " --full-name " ] ) )
119+ XCTAssertThrowsError ( try Hogera . parse ( [ " --first-name " , " Hogera " , " --full-name " , " Hogera Piyo " ] ) )
120+ XCTAssertThrowsError ( try Piyo . parse ( [ ] ) )
121+ XCTAssertThrowsError ( try Piyo . parse ( [ " --first-name " ] ) )
122+ XCTAssertThrowsError ( try Piyo . parse ( [ " --first-name " , " Hogera " , " --full-name " ] ) )
123+ XCTAssertThrowsError ( try Piyo . parse ( [ " --first-name " , " Hogera " , " --full-name " , " Hogera Piyo " ] ) )
124+ }
125+ }
126+
60127// MARK: Nested unparsed decodable type
61128
62129
@@ -106,3 +173,86 @@ extension UnparsedValuesEndToEndTests {
106173 XCTAssertThrowsError ( try Foo . parse ( [ " --one " , " aaa " ] ) )
107174 }
108175}
176+
177+ // MARK: Nested unparsed optional decodable type
178+
179+ fileprivate struct Barr : ParsableCommand {
180+ var baz : Baz ? = Baz ( name: " Some Name " , age: 105 )
181+ }
182+
183+ fileprivate struct Bar : ParsableCommand {
184+ @Flag var bar : Bool = false
185+ var baz : Baz ?
186+ var bazz : Bazz ?
187+ mutating func validate( ) throws {
188+ if bar {
189+ baz = Baz ( name: " Some " , age: 100 )
190+ bazz = Bazz ( name: " Other " , age: 101 )
191+ }
192+ }
193+ }
194+
195+ fileprivate struct Baz : Decodable {
196+ var name : String ?
197+ var age : Int !
198+ }
199+
200+ fileprivate struct Bazz : Decodable {
201+ var name : String ?
202+ var age : Int
203+ }
204+
205+ extension UnparsedValuesEndToEndTests {
206+ func testUnparsedNestedOptionalValue( ) {
207+ AssertParse ( Barr . self, [ ] ) { barr in
208+ XCTAssertNotNil ( barr. baz)
209+ XCTAssertEqual ( barr. baz? . age, 105 )
210+ XCTAssertEqual ( barr. baz? . name, " Some Name " )
211+ }
212+
213+ AssertParse ( Bar . self, [ ] ) { bar in
214+ XCTAssertFalse ( bar. bar)
215+ XCTAssertNil ( bar. baz)
216+ XCTAssertNil ( bar. baz? . age)
217+ XCTAssertNil ( bar. baz? . name)
218+ XCTAssertNil ( bar. bazz)
219+ XCTAssertNil ( bar. bazz? . age)
220+ XCTAssertNil ( bar. bazz? . name)
221+ }
222+
223+ AssertParse ( Bar . self, [ " --bar " ] ) { bar in
224+ XCTAssertTrue ( bar. bar)
225+ XCTAssertNotNil ( bar. baz)
226+ XCTAssertEqual ( bar. baz? . name, " Some " )
227+ XCTAssertEqual ( bar. baz? . age, 100 )
228+ XCTAssertNotNil ( bar. bazz)
229+ XCTAssertEqual ( bar. bazz? . name, " Other " )
230+ XCTAssertEqual ( bar. bazz? . age, 101 )
231+ }
232+ }
233+
234+ func testUnparsedNestedOptionalValue_Fails( ) {
235+ XCTAssertThrowsError ( try Bar . parse ( [ " --baz " , " xyz " ] ) )
236+ XCTAssertThrowsError ( try Bar . parse ( [ " --bazz " , " xyz " ] ) )
237+ XCTAssertThrowsError ( try Bar . parse ( [ " --name " , " None " ] ) )
238+ XCTAssertThrowsError ( try Bar . parse ( [ " --age " , " 123 " ] ) )
239+ XCTAssertThrowsError ( try Bar . parse ( [ " --bar " , " --name " , " None " ] ) )
240+ XCTAssertThrowsError ( try Bar . parse ( [ " --bar " , " --age " , " 123 " ] ) )
241+ XCTAssertThrowsError ( try Bar . parse ( [ " --bar " , " --baz " ] ) )
242+ XCTAssertThrowsError ( try Bar . parse ( [ " --bar " , " --baz " , " xyz " ] ) )
243+ XCTAssertThrowsError ( try Bar . parse ( [ " --bar " , " --baz " , " --name " , " None " ] ) )
244+ XCTAssertThrowsError ( try Bar . parse ( [ " --bar " , " --baz " , " xyz " , " --name " ] ) )
245+ XCTAssertThrowsError ( try Bar . parse ( [ " --bar " , " --baz " , " xyz " , " --name " , " None " ] ) )
246+ XCTAssertThrowsError ( try Bar . parse ( [ " --bar " , " --baz " , " --age " , " None " ] ) )
247+ XCTAssertThrowsError ( try Bar . parse ( [ " --bar " , " --baz " , " xyz " , " --age " ] ) )
248+ XCTAssertThrowsError ( try Bar . parse ( [ " --bar " , " --baz " , " xyz " , " --age " , " None " ] ) )
249+ XCTAssertThrowsError ( try Bar . parse ( [ " --bar " , " --bazz " ] ) )
250+ XCTAssertThrowsError ( try Bar . parse ( [ " --bar " , " --bazz " , " xyz " ] ) )
251+ XCTAssertThrowsError ( try Bar . parse ( [ " --bar " , " --bazz " , " --name " , " None " ] ) )
252+ XCTAssertThrowsError ( try Bar . parse ( [ " --bar " , " --bazz " , " xyz " , " --name " ] ) )
253+ XCTAssertThrowsError ( try Bar . parse ( [ " --bar " , " --bazz " , " xyz " , " --name " , " None " ] ) )
254+ XCTAssertThrowsError ( try Bar . parse ( [ " --bar " , " --bazz " , " --age " , " None " ] ) )
255+ XCTAssertThrowsError ( try Bar . parse ( [ " --bar " , " --bazz " , " xyz " , " --age " ] ) )
256+ XCTAssertThrowsError ( try Bar . parse ( [ " --bar " , " --bazz " , " xyz " , " --age " , " None " ] ) )
257+ }
258+ }
0 commit comments