Skip to content

Commit

Permalink
Merge pull request #18 from aviaviavi/mixed_contains
Browse files Browse the repository at this point in the history
adding mixedContains to account for both contains and not contains
  • Loading branch information
aviaviavi authored May 23, 2018
2 parents 9799493 + dbaa32e commit 8c1b2ec
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 16 deletions.
4 changes: 2 additions & 2 deletions curl-runnings.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
--
-- see: https://github.com/sol/hpack
--
-- hash: e22614c4e739f355b79fac77eb1cf5c8111237f2adc4aebcccbbb3b118e8d817
-- hash: 7bb221552afcd01d9eb59facb28651cb408688b95fd4fa710adee06dfa6e84ce

name: curl-runnings
version: 0.6.0
version: 0.7.0
synopsis: A framework for declaratively writing curl based API tests
description: Please see the README on Github at <https://github.com/aviaviavi/curl-runnings#readme>
category: Testing
Expand Down
25 changes: 23 additions & 2 deletions examples/example-spec.json
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,33 @@
"name": "test 5",
"url": "http://your-url.com/other/path",
"requestMethod": "GET",
"expectData": {
"contains": [
{
"keyValueMatch": {
"key": "okay",
"value": true
}
}
],
"notContains": [
{
"valueMatch": false
}
]
},
"expectStatus": 200
},
{
"name": "test 6",
"url": "http://your-url.com/other/path",
"requestMethod": "GET",
"headers": "Content-Type: application/json",
"expectStatus": 200,
"expectHeaders": "Content-Type: application/json; Hello: world"
},
{
"name": "test 6",
"name": "test 7",
"url": "http://your-url.com/other/path",
"requestMethod": "GET",
"headers": "Content-Type: application/json",
Expand All @@ -83,7 +104,7 @@
]
},
{
"name": "test 7",
"name": "test 8",
"url": "http://your-url.com/other/path",
"requestMethod": "GET",
"headers": "Content-Type: application/json",
Expand Down
24 changes: 19 additions & 5 deletions examples/example-spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@
url: http://your-url.com/other/path
requestMethod: GET
expectData:
# In the `notContains` case of data validation, a list of matchers is specified. Currently,
# possible types are `valueMatch` | `keyValueMatch`.
# In the `notContains` case of data validation, a list of matchers is specified. If any
# matcher is found in the response payload, the test will fail. Currently,
# possible matchers are `valueMatch` | `keyValueMatch`.
notContains:
- keyValueMatch:
key: okay
Expand All @@ -62,17 +63,30 @@
expectStatus: 200

- name: test 5
url: http://your-url.com/other/path
requestMethod: GET
expectData:
# you can have both a contains and a notContains block in your expectData
contains:
- keyValueMatch:
key: okay
value: true
notContains:
- valueMatch: false
expectStatus: 200

- name: test 6
url: http://your-url.com/other/path
requestMethod: GET
# Specify the headers you want to sent, just like the -H flag in a curl command
# IE "key: value; key: value; ..."
headers: "Content-Type: application/json"
expectStatus: 200
# The response must constain at least these headers exactly.
# The response must contain at least these headers exactly.
# Header strings again match the -H syntax from curl
expectHeaders: "Content-Type: application/json; Hello: world"

- name: test 6
- name: test 7
url: http://your-url.com/other/path
requestMethod: GET
headers: "Content-Type: application/json"
Expand All @@ -82,7 +96,7 @@
-
key: "Key-With-Val-We-Dont-Care-About"

- name: test 7
- name: test 8
url: http://your-url.com/other/path
requestMethod: GET
headers: "Content-Type: application/json"
Expand Down
2 changes: 1 addition & 1 deletion package.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: curl-runnings
version: 0.6.0
version: 0.7.0
github: aviaviavi/curl-runnings
license: MIT
author: Avi Press
Expand Down
12 changes: 12 additions & 0 deletions src/Testing/CurlRunnings.hs
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,18 @@ checkBody state curlCase@(CurlCase _ _ _ _ _ (Just (NotContains subexprs)) _ _)
DataFailure curlCase (NotContains updatedMatcher) (Just receivedBody)
else Nothing

-- | We are checking for both contains and notContains vals, and we have a payload to check
checkBody state curlCase@(CurlCase _ _ _ _ _ (Just m@(MixedContains subexprs)) _ _) receivedBody =
let failure = join $
find
isJust
(map
(\subexpr ->
checkBody state curlCase {expectData = Just subexpr} receivedBody)
subexprs)
in
fmap (\_ -> DataFailure curlCase m receivedBody ) failure

-- | We expected a body but didn't get one
checkBody _ curlCase@(CurlCase _ _ _ _ _ (Just anything) _ _) Nothing =
Just $ DataFailure curlCase anything Nothing
Expand Down
38 changes: 32 additions & 6 deletions src/Testing/CurlRunnings/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -62,20 +62,37 @@ instance ToJSON HttpMethod
data JsonMatcher
-- | Performs `==`
= Exactly Value
-- | A list of matchers to make assertions about some subset of the response.
-- | A list of matchers to make assertions that contains values exist in the response
| Contains [JsonSubExpr]
-- | A list of matchers to make assertions that contains values do not exist in the response
| NotContains [JsonSubExpr]
-- | We're specifiying both Contains and NotContains matchers
| MixedContains [JsonMatcher]
deriving (Show, Generic)

instance ToJSON JsonMatcher

instance FromJSON JsonMatcher where
parseJSON (Object v)
| isJust $ H.lookup "exactly" v = Exactly <$> v .: "exactly"
| isJust (H.lookup "contains" v) && isJust (H.lookup "notContains" v) = do
c <- Contains <$> v .: "contains"
n <- NotContains <$> v .: "notContains"
return $ MixedContains [c, n]
| isJust $ H.lookup "contains" v = Contains <$> v .: "contains"
| isJust $ H.lookup "notContains" v = NotContains <$> v .: "notContains"
parseJSON invalid = typeMismatch "JsonMatcher" invalid

-- | Simple predicate to check value constructor type
isContains :: JsonMatcher -> Bool
isContains (Contains _) = True
isContains _ = False

-- | Simple predicate to check value constructor type
isNotContains :: JsonMatcher -> Bool
isNotContains (NotContains _) = True
isNotContains _ = False

-- | A representation of a single header
data Header =
Header T.Text
Expand Down Expand Up @@ -124,14 +141,14 @@ data QueryError
instance Show QueryError where
show (QueryParseError t q) = printf "error parsing query %s: %s" q $ T.unpack t
show (NullPointer full part) = printf "null pointer in %s at %s" (T.unpack full) $ T.unpack part
show (QueryTypeMismatch message val) = printf "type error: %s %s" (message) $ show val
show (QueryTypeMismatch message val) = printf "type error: %s %s" message $ show val
show (QueryValidationError message) = printf "invalid query: %s" message

parseHeader :: T.Text -> Either T.Text Header
parseHeader str =
case map T.strip $ T.splitOn ":" str of
[key, val] -> Right $ Header key val
anythingElse -> Left . T.pack $ "bad header found: " ++ (show anythingElse)
anythingElse -> Left . T.pack $ "bad header found: " ++ show anythingElse

parseHeaders :: T.Text -> Either T.Text Headers
parseHeaders str =
Expand Down Expand Up @@ -247,7 +264,7 @@ data AssertionFailure

colorizeExpects :: String -> String
colorizeExpects t =
let expectedColor = makeRed "Excpected:"
let expectedColor = makeRed "Expected:"
actualColor = makeRed "Actual:"
replacedExpected = T.replace "Expected:" (T.pack expectedColor) (T.pack t)
in T.unpack $ T.replace "Actual:" (T.pack actualColor) replacedExpected
Expand Down Expand Up @@ -292,6 +309,14 @@ instance Show AssertionFailure where
(url curlCase)
(B8.unpack (encodePretty expectedVals))
(B8.unpack (encodePretty receivedVal))
(MixedContains expectedVals) ->
colorizeExpects $
printf
"JSON response from %s didn't satisfy the matcher. Expected: %s to each be subvalues and %s not to be subvalues in: %s"
(url curlCase)
(B8.unpack (encodePretty (filter isContains expectedVals)))
(B8.unpack (encodePretty (filter isNotContains expectedVals)))
(B8.unpack (encodePretty receivedVal))
show (HeaderFailure curlCase expected receivedHeaders) =
colorizeExpects $
printf
Expand Down Expand Up @@ -366,6 +391,7 @@ data Index
| ArrayIndex Integer
deriving (Show)

printOriginalQuery :: Index -> String
printOriginalQuery (CaseResultIndex t) = "SUITE[" ++ show t ++ "]"
printOriginalQuery (KeyIndex key) = "." ++ T.unpack key
printOriginalQuery (ArrayIndex i) = printf "[%d]" i
Expand All @@ -392,8 +418,8 @@ data InterpolatedQuery
printQueryString :: InterpolatedQuery -> String
printQueryString (LiteralText t) = show t
printQueryString (InterpolatedQuery raw (Query indexes)) =
printf "%s$<%s>" raw (concat $ map show indexes)
printQueryString (NonInterpolatedQuery (Query indexes)) = printf "$<%s>" (concat $ map show indexes)
printf "%s$<%s>" raw $ concatMap show indexes
printQueryString (NonInterpolatedQuery (Query indexes)) = printf "$<%s>" (concatMap show indexes)

-- | The full string in which a query appears, eg "prefix-${{SUITE[0].key.another_key[0].last_key}}"
type FullQueryText = T.Text
Expand Down

0 comments on commit 8c1b2ec

Please sign in to comment.