@@ -24,25 +24,27 @@ final class BuiltinValidationTests: XCTestCase {
2424 ] )
2525
2626 let withoutReferenceValidations = Validator ( ) . skippingReferenceValidations ( )
27- XCTAssertEqual ( withoutReferenceValidations. validationDescriptions. count, 8 )
27+ XCTAssertEqual ( withoutReferenceValidations. validationDescriptions. count, 9 )
2828 XCTAssertEqual ( withoutReferenceValidations. validationDescriptions, [
2929 " The names of Tags in the Document are unique " ,
3030 " The names of Servers in the Document are unique " ,
3131 " Path Item parameters are unique (identity is defined by the \' name \' and \' location \' ) " ,
3232 " Operation parameters are unique (identity is defined by the \' name \' and \' location \' ) " ,
33+ " Querystring parameters are unique and do not coexist with query parameters " ,
3334 " All Operation Ids in Document are unique " ,
3435 " Server Variable \' s enum is either not defined or is non-empty (if defined). " ,
3536 " Server Variable \' s default must exist in enum, if enum is defined. " ,
3637 " Parameter styles are all compatible with their locations "
3738 ] )
3839
3940 let defaultValidations = Validator ( )
40- XCTAssertEqual ( defaultValidations. validationDescriptions. count, 18 )
41+ XCTAssertEqual ( defaultValidations. validationDescriptions. count, 19 )
4142 XCTAssertEqual ( defaultValidations. validationDescriptions, [
4243 " The names of Tags in the Document are unique " ,
4344 " The names of Servers in the Document are unique " ,
4445 " Path Item parameters are unique (identity is defined by the \' name \' and \' location \' ) " ,
4546 " Operation parameters are unique (identity is defined by the \' name \' and \' location \' ) " ,
47+ " Querystring parameters are unique and do not coexist with query parameters " ,
4648 " All Operation Ids in Document are unique " ,
4749 " Server Variable \' s enum is either not defined or is non-empty (if defined). " ,
4850 " Server Variable \' s default must exist in enum, if enum is defined. " ,
@@ -60,12 +62,13 @@ final class BuiltinValidationTests: XCTestCase {
6062 ] )
6163
6264 let stricterReferenceValidations = Validator ( ) . validatingAllReferencesFoundInComponents ( )
63- XCTAssertEqual ( stricterReferenceValidations. validationDescriptions. count, 18 )
65+ XCTAssertEqual ( stricterReferenceValidations. validationDescriptions. count, 19 )
6466 XCTAssertEqual ( stricterReferenceValidations. validationDescriptions, [
6567 " The names of Tags in the Document are unique " ,
6668 " The names of Servers in the Document are unique " ,
6769 " Path Item parameters are unique (identity is defined by the \' name \' and \' location \' ) " ,
6870 " Operation parameters are unique (identity is defined by the \' name \' and \' location \' ) " ,
71+ " Querystring parameters are unique and do not coexist with query parameters " ,
6972 " All Operation Ids in Document are unique " ,
7073 " Server Variable \' s enum is either not defined or is non-empty (if defined). " ,
7174 " Server Variable \' s default must exist in enum, if enum is defined. " ,
@@ -1483,4 +1486,135 @@ final class BuiltinValidationTests: XCTestCase {
14831486 XCTAssertEqual ( errorCollection? . values. first? . codingPath. stringValue, " .paths[ \' /hello \' ].get.parameters[0] " )
14841487 }
14851488 }
1489+
1490+ func test_duplicateQuerystringParametersOnPathItem_fails( ) throws {
1491+ let document = OpenAPI . Document (
1492+ info: . init( title: " test " , version: " 1.0 " ) ,
1493+ servers: [ ] ,
1494+ paths: [
1495+ " /hello " : . init(
1496+ parameters: [
1497+ . parameter( OpenAPI . Parameter. querystring ( name: " first " , content: [ : ] ) ) ,
1498+ . parameter( OpenAPI . Parameter. querystring ( name: " second " , content: [ : ] ) )
1499+ ] ,
1500+ get: . init( responses: [ : ] )
1501+ )
1502+ ] ,
1503+ components: . noComponents
1504+ )
1505+
1506+ let validator = Validator . blank. validating ( . querystringParametersAreCompatible)
1507+
1508+ XCTAssertThrowsError ( try document. validate ( using: validator) ) { error in
1509+ let errorCollection = error as? ValidationErrorCollection
1510+ XCTAssertEqual ( errorCollection? . values. first? . reason, " Path Item parameters must not contain more than one `querystring` parameter " )
1511+ XCTAssertEqual ( errorCollection? . values. first? . codingPath. stringValue, " .paths[ \' /hello \' ].parameters " )
1512+ }
1513+ }
1514+
1515+ func test_duplicateQuerystringParametersAcrossPathItemAndOperation_fails( ) throws {
1516+ let document = OpenAPI . Document (
1517+ info: . init( title: " test " , version: " 1.0 " ) ,
1518+ servers: [ ] ,
1519+ paths: [
1520+ " /hello " : . init(
1521+ parameters: [
1522+ . parameter( OpenAPI . Parameter. querystring ( name: " first " , content: [ : ] ) )
1523+ ] ,
1524+ get: . init(
1525+ parameters: [
1526+ . parameter( OpenAPI . Parameter. querystring ( name: " second " , content: [ : ] ) )
1527+ ] ,
1528+ responses: [ : ]
1529+ )
1530+ )
1531+ ] ,
1532+ components: . noComponents
1533+ )
1534+
1535+ let validator = Validator . blank. validating ( . querystringParametersAreCompatible)
1536+
1537+ XCTAssertThrowsError ( try document. validate ( using: validator) ) { error in
1538+ let errorCollection = error as? ValidationErrorCollection
1539+ XCTAssertEqual ( errorCollection? . values. first? . reason, " Operation parameters must not contain more than one `querystring` parameter, including inherited Path Item parameters " )
1540+ XCTAssertEqual ( errorCollection? . values. first? . codingPath. stringValue, " .paths[ \' /hello \' ].get.parameters " )
1541+ }
1542+ }
1543+
1544+ func test_querystringAndQueryParametersOnOperation_fails( ) throws {
1545+ let document = OpenAPI . Document (
1546+ info: . init( title: " test " , version: " 1.0 " ) ,
1547+ servers: [ ] ,
1548+ paths: [
1549+ " /hello " : . init(
1550+ get: . init(
1551+ parameters: [
1552+ . parameter( OpenAPI . Parameter. query ( name: " query " , schema: . string) ) ,
1553+ . parameter( OpenAPI . Parameter. querystring ( name: " querystring " , content: [ : ] ) )
1554+ ] ,
1555+ responses: [ : ]
1556+ )
1557+ )
1558+ ] ,
1559+ components: . noComponents
1560+ )
1561+
1562+ let validator = Validator . blank. validating ( . querystringParametersAreCompatible)
1563+
1564+ XCTAssertThrowsError ( try document. validate ( using: validator) ) { error in
1565+ let errorCollection = error as? ValidationErrorCollection
1566+ XCTAssertEqual ( errorCollection? . values. first? . reason, " Operation parameters must not mix `querystring` and `query` parameter locations " )
1567+ XCTAssertEqual ( errorCollection? . values. first? . codingPath. stringValue, " .paths[ \' /hello \' ].get.parameters " )
1568+ }
1569+ }
1570+
1571+ func test_querystringAndQueryParametersAcrossPathItemAndOperation_fails( ) throws {
1572+ let document = OpenAPI . Document (
1573+ info: . init( title: " test " , version: " 1.0 " ) ,
1574+ servers: [ ] ,
1575+ paths: [
1576+ " /hello " : . init(
1577+ parameters: [
1578+ . parameter( OpenAPI . Parameter. query ( name: " query " , schema: . string) )
1579+ ] ,
1580+ get: . init(
1581+ parameters: [
1582+ . parameter( OpenAPI . Parameter. querystring ( name: " querystring " , content: [ : ] ) )
1583+ ] ,
1584+ responses: [ : ]
1585+ )
1586+ )
1587+ ] ,
1588+ components: . noComponents
1589+ )
1590+
1591+ let validator = Validator . blank. validating ( . querystringParametersAreCompatible)
1592+
1593+ XCTAssertThrowsError ( try document. validate ( using: validator) ) { error in
1594+ let errorCollection = error as? ValidationErrorCollection
1595+ XCTAssertEqual ( errorCollection? . values. first? . reason, " Operation parameters must not mix `querystring` and `query` parameter locations, including inherited Path Item parameters " )
1596+ XCTAssertEqual ( errorCollection? . values. first? . codingPath. stringValue, " .paths[ \' /hello \' ].get.parameters " )
1597+ }
1598+ }
1599+
1600+ func test_singleQuerystringParameter_succeeds( ) throws {
1601+ let document = OpenAPI . Document (
1602+ info: . init( title: " test " , version: " 1.0 " ) ,
1603+ servers: [ ] ,
1604+ paths: [
1605+ " /hello " : . init(
1606+ get: . init(
1607+ parameters: [
1608+ . parameter( OpenAPI . Parameter. querystring ( name: " querystring " , content: [ : ] ) )
1609+ ] ,
1610+ responses: [ : ]
1611+ )
1612+ )
1613+ ] ,
1614+ components: . noComponents
1615+ )
1616+
1617+ let validator = Validator . blank. validating ( . querystringParametersAreCompatible)
1618+ try document. validate ( using: validator)
1619+ }
14861620}
0 commit comments