packages feed

tasty-wai (empty) → 0.1.0.0

raw patch · 6 files changed

+267/−0 lines, 6 filesdep +basedep +bytestringdep +http-typessetup-changed

Dependencies added: base, bytestring, http-types, tasty, tasty-wai, wai, wai-extra

Files

+ CHANGELOG.md view
@@ -0,0 +1,5 @@+# Revision history for tasty-wai++## 0.1.0.0 -- 2018-12-04++* First version. Released on an unsuspecting world.
+ LICENCE view
@@ -0,0 +1,31 @@+Copyright (c) 2018, Commonwealth Scientific and Industrial Research Organisation+(CSIRO) ABN 41 687 119 230.++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of QFPL nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ src/Test/Tasty/Wai.hs view
@@ -0,0 +1,116 @@+-- | Types and functions for testing 'wai' endpoints using the 'tasty' testing framework.+--+module Test.Tasty.Wai+  (+    -- * Types+    Sess (..)++    -- * Creation+  , testWai++    -- * Helpers+  , get+  , post+  , put+  , assertStatus'++    -- * Request Builders+  , buildRequest+  , buildRequestWithBody++  , module Network.Wai.Test+  ) where++import qualified Control.Exception    as E++import qualified Data.ByteString      as BS+import qualified Data.ByteString.Lazy as LBS+import           Data.Monoid          ((<>))++import           Network.HTTP.Types   (StdMethod)+import qualified Network.HTTP.Types   as HTTP++import           Test.Tasty.Providers (IsTest (..), Progress (..), TestName,+                                       TestTree, singleTest, testFailed,+                                       testPassed)+import           Test.Tasty.Runners   (formatMessage)++import           Network.Wai          (Application, Request, requestMethod)+import           Network.Wai.Test++-- | Data structure for carrying around the info needed to build and run a test.+data Sess = S Application TestName (Session ())++instance IsTest Sess where+  -- No options yet+  testOptions = mempty++  run _ (S app tName sess) yieldProgress = do++    -- We don't really have progress to report, so state that we're running a+    -- test but do nothing else.+    yieldProgress $ Progress ("Running " <> tName) 0++    -- The wai-extra testing uses `throwIO` to indicate a test failure and+    -- converts that error into a 'String'. The result of the individual+    -- 'Session a' isn't important for the test?+    E.try (runSession sess app) >>= either toFailure toPass+    where+      toFailure (WaiTestFailure s) = testFailed <$> (formatMessage s)+      toPass     _                 = pure (testPassed mempty)++-- | Create an empty 'Request' using the given HTTP Method and route.+buildRequest+  :: StdMethod+  -> BS.ByteString+  -> Request+buildRequest mth rpath = flip setPath rpath $ defaultRequest+  { requestMethod = HTTP.renderStdMethod mth+  }++-- | As per 'buildRequest' but requires body content.+buildRequestWithBody+  :: StdMethod+  -> BS.ByteString+  -> LBS.ByteString+  -> SRequest+buildRequestWithBody mth rpath =+  SRequest (buildRequest mth rpath)++-- | Run a test case against a 'Application'.+--+-- This module re-exports the functions from 'wai-extra' for constructing the+-- 'Session' that is executed against a given endpoint.+--+-- A small test case may look like:+--+-- @+-- import MyApp (app)+--+-- testWai app "List Topics" $ do+--       res <- get "fudge/view"+--       assertStatus' HTTP.status200 res+-- @+--+testWai :: Application -> TestName -> Session () -> TestTree+testWai a tn = singleTest tn . S a tn++-- | Submit a 'HTTP.GET' request to the provided endpoint.+get :: BS.ByteString -> Session SResponse+get = request . buildRequest HTTP.GET++-- | Submit a 'HTTP.POST' request to the given endpoint with the provided+-- 'LBS.ByteString' as the body content.+post :: BS.ByteString -> LBS.ByteString -> Session SResponse+post r = srequest . buildRequestWithBody HTTP.POST r++-- | Submit a 'HTTP.PUT' request to the given endpoint with the provided+-- 'LBS.ByteString' as the body content.+put :: BS.ByteString -> LBS.ByteString -> Session SResponse+put r = srequest . buildRequestWithBody HTTP.PUT r++-- | An alternative helper function for checking the status code on a response+-- that lets you use the functions from 'Network.HTTP.Types' as opposed to bare+-- numbers.+assertStatus' :: HTTP.Status -> SResponse -> Session ()+assertStatus' c = assertStatus (HTTP.statusCode c)
+ tasty-wai.cabal view
@@ -0,0 +1,63 @@+-- Initial tasty-wai.cabal generated by cabal init.  For further+-- documentation, see http://haskell.org/cabal/users-guide/++name:                tasty-wai+version:             0.1.0.0+synopsis:            Test 'wai' endpoints via Test.Tasty+description:         Helper functions and runners for testing wai endpoints using the Tasty testing infrastructure.+license:             BSD3+license-file:        LICENCE+author:              QFPL @ Data61+maintainer:          sean.chalmers@data61.csiro.au++copyright:           Copyright (C) 2018 Commonwealth Scientific and Industrial Research Organisation (CSIRO)++category:            Testing,Web++build-type:          Simple+extra-source-files:  CHANGELOG.md+cabal-version:       >=1.10++tested-with:         GHC == 7.10.3+                   , GHC == 8.0.2+                   , GHC == 8.2.2+                   , GHC == 8.4.1+                   , GHC == 8.6.1++source-repository head+    type: git+    location: https://github.com/qfpl/tasty-wai++library+  exposed-modules:     Test.Tasty.Wai++  -- other-modules:+  -- other-extensions:++  build-depends:       base >=4.8 && <4.13+                     , tasty >= 0.8 && < 1.3+                     , bytestring == 0.10.*+                     , wai == 3.2.*+                     , wai-extra == 3.0.*+                     , http-types >= 0.9 && < 0.13++  hs-source-dirs:      src+  default-language:    Haskell2010+++test-suite tests+  default-language:    Haskell2010++  type:                exitcode-stdio-1.0++  ghc-options:         -threaded++  hs-source-dirs:      test+  main-is:             Test.hs++  build-depends:       base >=4.8 && <4.13+                     , tasty >= 0.8 && < 1.3+                     , bytestring == 0.10.*+                     , wai == 3.2.*+                     , http-types >= 0.9 && < 0.13+                     , tasty-wai
+ test/Test.hs view
@@ -0,0 +1,50 @@+{-# LANGUAGE OverloadedStrings #-}+module Main where++import           Network.Wai        (Application)+import qualified Network.Wai        as W++import qualified Network.HTTP.Types as H++import           Test.Tasty         (defaultMain, testGroup)+import           Test.Tasty.Wai     (assertBody, assertStatus, assertStatus',+                                     get, post, testWai)++testApp :: Application+testApp rq cb = do+  let+    mkresp s = W.responseLBS s []+    resp404 = mkresp H.status404+    resp200 = mkresp H.status200++  resp <- case (W.requestMethod rq, W.pathInfo rq) of++    -- Ye olde...+    ("GET", ["hello"]) -> pure $ resp200 "world!"++    -- Echo me this!+    ("POST", ["echo"]) -> resp200 <$> W.strictRequestBody rq++    -- Well, then...+    _ -> pure $ resp404 "no route"++  cb resp++main :: IO ()+main = defaultMain $ testGroup "Tasty-Wai Tests"++  [ testWai testApp "Hello to World" $ do+      res <- get "hello"+      assertBody "world!" res++  , testWai testApp "Echo to thee" $ do+      res <- post "echo" "thus"+      assertStatus' H.status200 res -- Use functions from Network.HTTP.Types+      assertStatus 200 res          -- Use raw ints+      assertBody "thus" res++  , testWai testApp "Will die!" $ do+      res <- get "not-a-thing"+      assertStatus' H.status404 res+      assertBody "no route" res+  ]