1{-# LANGUAGE OverloadedLists #-}
2{-# LANGUAGE OverloadedStrings #-}
3{-# LANGUAGE ScopedTypeVariables #-}
4{-# LANGUAGE QuasiQuotes #-}
5module Data.SwaggerSpec where
13import Data.Aeson.QQ.Simple
14import Data.HashMap.Strict (HashMap)
15import qualified Data.Set as Set
16import Data.Text (Text)
20import Test.Hspec hiding (example)
25 it "can decode the host port" $ do
26 let h = Just $ Host "localhost" (Just (fromInteger 8000))
28 swagger = swaggerExample
30 parsed :: Swagger = either error id $ eitherDecode' $ encode swagger
31 parsed ^. host `shouldBe` h
32 describe "License Object" $ licenseExample <=> licenseExampleJSON
33 describe "Contact Object" $ contactExample <=> contactExampleJSON
34 describe "Info Object" $ infoExample <=> infoExampleJSON
35 describe "Operation Object" $ operationExample <=> operationExampleJSON
36 describe "Schema Object" $ do
37 context "Primitive Sample" $ schemaPrimitiveExample <=> schemaPrimitiveExampleJSON
38 context "Simple Model" $ schemaSimpleModelExample <=> schemaSimpleModelExampleJSON
39 context "Model with Map/Dictionary Properties" $ schemaModelDictExample <=> schemaModelDictExampleJSON
40 context "Model with Arbitrary Properties" $ schemaAdditionalExample <=> schemaAdditionalExampleJSON
41 context "Model with Example" $ schemaWithExampleExample <=> schemaWithExampleExampleJSON
42 describe "Definitions Object" $ definitionsExample <=> definitionsExampleJSON
43 describe "Parameters Definition Object" $ paramsDefinitionExample <=> paramsDefinitionExampleJSON
44 describe "Responses Definition Object" $ responsesDefinitionExample <=> responsesDefinitionExampleJSON
45 describe "Security Definitions Object" $ securityDefinitionsExample <=> securityDefinitionsExampleJSON
46 describe "Composition Schema Example" $ compositionSchemaExample <=> compositionSchemaExampleJSON
47 describe "Swagger Object" $ do
48 context "Todo Example" $ swaggerExample <=> swaggerExampleJSON
49 context "PetStore Example" $
50 it "decodes successfully" $ do
51 fromJSON petstoreExampleJSON `shouldSatisfy` (\x -> case x of Success (_ :: Swagger) -> True; _ -> False)
56-- =======================================================================
58-- =======================================================================
62 & title .~ "Swagger Sample App"
63 & description ?~ "This is a sample server Petstore server."
64 & termsOfService ?~ "http://swagger.io/terms/"
65 & contact ?~ contactExample
66 & license ?~ licenseExample
69infoExampleJSON :: Value
70infoExampleJSON = [aesonQQ|
72 "title": "Swagger Sample App",
73 "description": "This is a sample server Petstore server.",
74 "termsOfService": "http://swagger.io/terms/",
76 "name": "API Support",
77 "url": "http://www.swagger.io/support",
78 "email": "support@swagger.io"
82 "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
88-- =======================================================================
90-- =======================================================================
92contactExample :: Contact
93contactExample = mempty
94 & name ?~ "API Support"
95 & url ?~ URL "http://www.swagger.io/support"
96 & email ?~ "support@swagger.io"
98contactExampleJSON :: Value
99contactExampleJSON = [aesonQQ|
101 "name": "API Support",
102 "url": "http://www.swagger.io/support",
103 "email": "support@swagger.io"
107-- =======================================================================
109-- =======================================================================
111licenseExample :: License
112licenseExample = "Apache 2.0"
113 & url ?~ URL "http://www.apache.org/licenses/LICENSE-2.0.html"
115licenseExampleJSON :: Value
116licenseExampleJSON = [aesonQQ|
118 "name": "Apache 2.0",
119 "url": "http://www.apache.org/licenses/LICENSE-2.0.html"
124-- =======================================================================
126-- =======================================================================
128operationExample :: Operation
129operationExample = mempty
130 & tags .~ Set.fromList ["pet"]
131 & summary ?~ "Updates a pet in the store with form data"
133 & operationId ?~ "updatePetWithForm"
134 & consumes ?~ MimeList ["application/x-www-form-urlencoded"]
135 & produces ?~ MimeList ["application/json", "application/xml"]
136 & parameters .~ map Inline
139 & description ?~ "ID of pet that needs to be updated"
141 & schema .~ ParamOther (stringSchema ParamPath)
144 & description ?~ "Updated name of the pet"
146 & schema .~ ParamOther (stringSchema ParamFormData)
149 & description ?~ "Updated status of the pet"
151 & schema .~ ParamOther (stringSchema ParamFormData)
154 & at 200 ?~ "Pet updated."
155 & at 405 ?~ "Invalid input"
156 & security .~ [SecurityRequirement [("petstore_auth", ["write:pets", "read:pets"])]]
158 stringSchema :: ParamLocation -> ParamOtherSchema
159 stringSchema loc = mempty
161 & type_ .~ SwaggerString
163operationExampleJSON :: Value
164operationExampleJSON = [aesonQQ|
169 "summary": "Updates a pet in the store with form data",
171 "operationId": "updatePetWithForm",
173 "application/x-www-form-urlencoded"
183 "description": "ID of pet that needs to be updated",
190 "description": "Updated name of the pet",
197 "description": "Updated status of the pet",
204 "description": "Pet updated."
207 "description": "Invalid input"
221-- =======================================================================
223-- =======================================================================
225schemaPrimitiveExample :: Schema
226schemaPrimitiveExample = mempty
227 & type_ .~ SwaggerString
230schemaPrimitiveExampleJSON :: Value
231schemaPrimitiveExampleJSON = [aesonQQ|
238schemaSimpleModelExample :: Schema
239schemaSimpleModelExample = mempty
240 & type_ .~ SwaggerObject
241 & required .~ [ "name" ]
243 [ ("name", Inline (mempty & type_ .~ SwaggerString))
244 , ("address", Ref (Reference "Address"))
245 , ("age", Inline $ mempty
247 & type_ .~ SwaggerInteger
248 & format ?~ "int32" ) ]
250schemaSimpleModelExampleJSON :: Value
251schemaSimpleModelExampleJSON = [aesonQQ|
262 "$ref": "#/definitions/Address"
273schemaModelDictExample :: Schema
274schemaModelDictExample = mempty
275 & type_ .~ SwaggerObject
276 & additionalProperties ?~ AdditionalPropertiesSchema (Inline (mempty & type_ .~ SwaggerString))
278schemaModelDictExampleJSON :: Value
279schemaModelDictExampleJSON = [aesonQQ|
282 "additionalProperties": {
288schemaAdditionalExample :: Schema
289schemaAdditionalExample = mempty
290 & type_ .~ SwaggerObject
291 & additionalProperties ?~ AdditionalPropertiesAllowed True
293schemaAdditionalExampleJSON :: Value
294schemaAdditionalExampleJSON = [aesonQQ|
297 "additionalProperties": true
301schemaWithExampleExample :: Schema
302schemaWithExampleExample = mempty
303 & type_ .~ SwaggerObject
305 [ ("id", Inline $ mempty
306 & type_ .~ SwaggerInteger
307 & format ?~ "int64" )
308 , ("name", Inline $ mempty
309 & type_ .~ SwaggerString) ]
310 & required .~ [ "name" ]
311 & example ?~ [aesonQQ|
318schemaWithExampleExampleJSON :: Value
319schemaWithExampleExampleJSON = [aesonQQ|
341-- =======================================================================
343-- =======================================================================
345definitionsExample :: HashMap Text Schema
347 [ ("Category", mempty
348 & type_ .~ SwaggerObject
350 [ ("id", Inline $ mempty
351 & type_ .~ SwaggerInteger
353 , ("name", Inline (mempty & type_ .~ SwaggerString)) ] )
355 & type_ .~ SwaggerObject
357 [ ("id", Inline $ mempty
358 & type_ .~ SwaggerInteger
360 , ("name", Inline (mempty & type_ .~ SwaggerString)) ] ) ]
362definitionsExampleJSON :: Value
363definitionsExampleJSON = [aesonQQ|
392-- =======================================================================
393-- Parameters Definition object
394-- =======================================================================
396paramsDefinitionExample :: HashMap Text Param
397paramsDefinitionExample =
398 [ ("skipParam", mempty
400 & description ?~ "number of items to skip"
402 & schema .~ ParamOther (mempty
404 & type_ .~ SwaggerInteger
405 & format ?~ "int32" ))
406 , ("limitParam", mempty
408 & description ?~ "max records to return"
410 & schema .~ ParamOther (mempty
412 & type_ .~ SwaggerInteger
413 & format ?~ "int32" )) ]
415paramsDefinitionExampleJSON :: Value
416paramsDefinitionExampleJSON = [aesonQQ|
421 "description": "number of items to skip",
429 "description": "max records to return",
437-- =======================================================================
438-- Responses Definition object
439-- =======================================================================
441responsesDefinitionExample :: HashMap Text Response
442responsesDefinitionExample =
443 [ ("NotFound", mempty & description .~ "Entity not found.")
444 , ("IllegalInput", mempty & description .~ "Illegal input for operation.") ]
446responsesDefinitionExampleJSON :: Value
447responsesDefinitionExampleJSON = [aesonQQ|
450 "description": "Entity not found."
453 "description": "Illegal input for operation."
458-- =======================================================================
459-- Responses Definition object
460-- =======================================================================
462securityDefinitionsExample :: HashMap Text SecurityScheme
463securityDefinitionsExample =
464 [ ("api_key", SecurityScheme
465 { _securitySchemeType = SecuritySchemeApiKey (ApiKeyParams "api_key" ApiKeyHeader)
466 , _securitySchemeDescription = Nothing })
467 , ("petstore_auth", SecurityScheme
468 { _securitySchemeType = SecuritySchemeOAuth2 (OAuth2Params
469 { _oauth2Flow = OAuth2Implicit "http://swagger.io/api/oauth/dialog"
471 [ ("write:pets", "modify pets in your account")
472 , ("read:pets", "read your pets") ] } )
473 , _securitySchemeDescription = Nothing }) ]
475securityDefinitionsExampleJSON :: Value
476securityDefinitionsExampleJSON = [aesonQQ|
485 "authorizationUrl": "http://swagger.io/api/oauth/dialog",
488 "write:pets": "modify pets in your account",
489 "read:pets": "read your pets"
495-- =======================================================================
497-- =======================================================================
499swaggerExample :: Swagger
500swaggerExample = mempty
505 & title .~ "Todo API"
507 & license._Just.url ?~ URL "http://mit.com"
508 & description ?~ "This is a an API that tests servant-swagger support for a Todo API")
509 & paths.at "/todo/{id}" ?~ (mempty & get ?~ ((mempty :: Operation)
510 & at 200 ?~ Inline (mempty
511 & description .~ "OK"
512 & schema ?~ Inline (mempty
513 & type_ .~ SwaggerObject
514 & example ?~ [aesonQQ|
517 "description": "get milk"
519 & description ?~ "This is some real Todo right here"
521 [ ("created", Inline $ mempty
522 & type_ .~ SwaggerInteger
524 , ("description", Inline (mempty & type_ .~ SwaggerString))]))
525 & produces ?~ MimeList [ "application/json" ]
530 & description ?~ "TodoId param"
531 & schema .~ ParamOther (mempty
533 & type_ .~ SwaggerString ) ]
534 & tags .~ Set.fromList [ "todo" ] ))
536swaggerExampleJSON :: Value
537swaggerExampleJSON = [aesonQQ|
548 "url": "http://mit.com",
551 "description": "This is a an API that tests servant-swagger support for a Todo API"
561 "description": "get milk"
564 "description": "This is some real Todo right here",
587 "description": "TodoId param"
599petstoreExampleJSON :: Value
600petstoreExampleJSON = [aesonQQ|
604 "description":"This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.",
606 "title":"Swagger Petstore",
607 "termsOfService":"http://swagger.io/terms/",
609 "email":"apiteam@swagger.io"
613 "url":"http://www.apache.org/licenses/LICENSE-2.0.html"
616 "host":"petstore.swagger.io",
621 "description":"Everything about your Pets",
623 "description":"Find out more",
624 "url":"http://swagger.io"
629 "description":"Access to Petstore orders"
633 "description":"Operations about user",
635 "description":"Find out more about our store",
636 "url":"http://swagger.io"
649 "summary":"Add a new pet to the store",
651 "operationId":"addPet",
664 "description":"Pet object that needs to be added to the store",
667 "$ref":"#/definitions/Pet"
673 "description":"Invalid input"
689 "summary":"Update an existing pet",
691 "operationId":"updatePet",
704 "description":"Pet object that needs to be added to the store",
707 "$ref":"#/definitions/Pet"
713 "description":"Invalid ID supplied"
716 "description":"Pet not found"
719 "description":"Validation exception"
732 "/pet/findByStatus":{
737 "summary":"Finds Pets by status",
738 "description":"Multiple status values can be provided with comma seperated strings",
739 "operationId":"findPetsByStatus",
748 "description":"Status values that need to be considered for filter",
758 "default":"available"
760 "collectionFormat":"csv"
765 "description":"successful operation",
769 "$ref":"#/definitions/Pet"
774 "description":"Invalid status value"
792 "summary":"Finds Pets by tags",
793 "description":"Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing.",
794 "operationId":"findPetsByTags",
803 "description":"Tags to filter by",
809 "collectionFormat":"csv"
814 "description":"successful operation",
818 "$ref":"#/definitions/Pet"
823 "description":"Invalid tag value"
841 "summary":"Find pet by ID",
842 "description":"Returns a single pet",
843 "operationId":"getPetById",
852 "description":"ID of pet to return",
860 "description":"successful operation",
862 "$ref":"#/definitions/Pet"
866 "description":"Invalid ID supplied"
869 "description":"Pet not found"
882 "summary":"Updates a pet in the store with form data",
884 "operationId":"updatePetWithForm",
886 "application/x-www-form-urlencoded"
896 "description":"ID of pet that needs to be updated",
904 "description":"Updated name of the pet",
911 "description":"Updated status of the pet",
918 "description":"Invalid input"
934 "summary":"Deletes a pet",
936 "operationId":"deletePet",
951 "description":"Pet id to delete",
959 "description":"Invalid pet value"
972 "/pet/{petId}/uploadImage":{
977 "summary":"uploads an image",
979 "operationId":"uploadFile",
981 "multipart/form-data"
990 "description":"ID of pet to update",
996 "name":"additionalMetadata",
998 "description":"Additional data to pass to server",
1005 "description":"file to upload",
1012 "description":"successful operation",
1014 "$ref":"#/definitions/ApiResponse"
1028 "/store/inventory":{
1033 "summary":"Returns pet inventories by status",
1034 "description":"Returns a map of status codes to quantities",
1035 "operationId":"getInventory",
1042 "description":"successful operation",
1045 "additionalProperties":{
1064 "summary":"Place an order for a pet",
1066 "operationId":"placeOrder",
1075 "description":"order placed for purchasing the pet",
1078 "$ref":"#/definitions/Order"
1084 "description":"successful operation",
1086 "$ref":"#/definitions/Order"
1090 "description":"Invalid Order"
1095 "/store/order/{orderId}":{
1100 "summary":"Find purchase order by ID",
1101 "description":"For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions",
1102 "operationId":"getOrderById",
1111 "description":"ID of pet that needs to be fetched",
1121 "description":"successful operation",
1123 "$ref":"#/definitions/Order"
1127 "description":"Invalid ID supplied"
1130 "description":"Order not found"
1138 "summary":"Delete purchase order by ID",
1139 "description":"For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors",
1140 "operationId":"deleteOrder",
1149 "description":"ID of the order that needs to be deleted",
1157 "description":"Invalid ID supplied"
1160 "description":"Order not found"
1170 "summary":"Create user",
1171 "description":"This can only be done by the logged in user.",
1172 "operationId":"createUser",
1181 "description":"Created user object",
1184 "$ref":"#/definitions/User"
1190 "description":"successful operation"
1195 "/user/createWithArray":{
1200 "summary":"Creates list of users with given input array",
1202 "operationId":"createUsersWithArrayInput",
1211 "description":"List of user object",
1216 "$ref":"#/definitions/User"
1223 "description":"successful operation"
1228 "/user/createWithList":{
1233 "summary":"Creates list of users with given input array",
1235 "operationId":"createUsersWithListInput",
1244 "description":"List of user object",
1249 "$ref":"#/definitions/User"
1256 "description":"successful operation"
1266 "summary":"Logs user into the system",
1268 "operationId":"loginUser",
1277 "description":"The user name for login",
1284 "description":"The password for login in clear text",
1291 "description":"successful operation",
1299 "description":"calls per hour allowed by the user"
1303 "format":"date-time",
1304 "description":"date in UTC when toekn expires"
1309 "description":"Invalid username/password supplied"
1319 "summary":"Logs out current logged in user session",
1321 "operationId":"logoutUser",
1329 "description":"successful operation"
1334 "/user/{username}":{
1339 "summary":"Get user by user name",
1341 "operationId":"getUserByName",
1350 "description":"The name that needs to be fetched. Use user1 for testing. ",
1357 "description":"successful operation",
1359 "$ref":"#/definitions/User"
1363 "description":"Invalid username supplied"
1366 "description":"User not found"
1374 "summary":"Updated user",
1375 "description":"This can only be done by the logged in user.",
1376 "operationId":"updateUser",
1385 "description":"name that need to be deleted",
1392 "description":"Updated user object",
1395 "$ref":"#/definitions/User"
1401 "description":"Invalid user supplied"
1404 "description":"User not found"
1412 "summary":"Delete user",
1413 "description":"This can only be done by the logged in user.",
1414 "operationId":"deleteUser",
1423 "description":"The name that needs to be deleted",
1430 "description":"Invalid username supplied"
1433 "description":"User not found"
1439 "securityDefinitions":{
1442 "authorizationUrl":"http://petstore.swagger.io/api/oauth/dialog",
1445 "write:pets":"modify pets in your account",
1446 "read:pets":"read your pets"
1473 "format":"date-time"
1477 "description":"Order Status",
1536 "description":"User Status"
1570 "$ref":"#/definitions/Category"
1593 "$ref":"#/definitions/Tag"
1598 "description":"pet status in the store",
1627 "description":"Find out more about Swagger",
1628 "url":"http://swagger.io"
1633compositionSchemaExample :: Schema
1634compositionSchemaExample = mempty
1635 & type_ .~ SwaggerObject
1636 & Data.Swagger.allOf ?~ [
1637 Ref (Reference "Other")
1639 & type_ .~ SwaggerObject
1641 [ ("greet", Inline $ mempty
1642 & type_ .~ SwaggerString) ])
1645compositionSchemaExampleJSON :: Value
1646compositionSchemaExampleJSON = [aesonQQ|
1651 "$ref": "#/definitions/Other"
1656 "greet": { "type": "string" }
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list