Skip to content

Commit

Permalink
Port integration tests Request module from old codebase
Browse files Browse the repository at this point in the history
This provides `unsafeRequest`, renamed to `request`, plus some
variations.

A little bit of the DSL module and the Scenario module was ported so
that I could test the function.

Relates to #55 and #56
  • Loading branch information
rvl committed Mar 20, 2019
1 parent 609aa53 commit c96db92
Show file tree
Hide file tree
Showing 6 changed files with 498 additions and 3 deletions.
21 changes: 20 additions & 1 deletion .weeder.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,23 @@
- message:
- name: Module not compiled
- module: Cardano.Launcher.Windows

- section:
- name: test:integration
- message:
- name: Redundant build-depends entry
- depends: cardano-wallet
- message:
- name: Weeds exported
- module:
- name: Test.Integration.Framework.DSL
- identifier:
- expectSuccess
- pendingWith
- xscenario
- module:
- name: Test.Integration.Framework.Request
- identifier:
- $-
- ClientError
- DecodeFailure
- HttpException
16 changes: 15 additions & 1 deletion cardano-wallet.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,24 @@ test-suite integration
-Werror
build-depends:
base
, aeson
, async
, bytestring
, cardano-wallet
, exceptions
, fmt
, generic-lens
, hspec
, hspec-core
, http-client
, http-types
, lens
, mtl
, process
, transformers
, say
, text
, transformers

type:
exitcode-stdio-1.0
hs-source-dirs:
Expand All @@ -171,6 +182,9 @@ test-suite integration
other-modules:
Cardano.NetworkLayer.HttpBridgeSpec
Cardano.Launcher
Test.Integration.Framework.DSL
Test.Integration.Framework.Request
Test.Integration.Framework.Scenario
if os(windows)
build-depends: Win32
other-modules: Cardano.Launcher.Windows
Expand Down
64 changes: 63 additions & 1 deletion test/integration/Main.hs
Original file line number Diff line number Diff line change
@@ -1 +1,63 @@
{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
module Main where

import Control.Concurrent
( threadDelay )
import Control.Concurrent.MVar
( newMVar )

import Data.Aeson
( Value )
import Data.Text
( Text )
import Network.HTTP.Client
( Manager, defaultManagerSettings, newManager )
import Prelude
import System.Process
( proc, withCreateProcess )
import Test.Hspec
( beforeAll, describe, hspec )

import qualified Data.Text as T

import Test.Integration.Framework.DSL
( Context (..)
, Scenarios
, expectError
, request
, request_
, scenario
, verify
)
import Test.Integration.Framework.Request
( RequestException (..) )

import qualified Cardano.NetworkLayer.HttpBridgeSpec as HttpBridge

withWallet :: ((Text, Manager) -> IO a) -> IO a
withWallet action = do
let launch = proc "cardano-wallet-server" testMnemonic
testMnemonic = ["ring","congress","face","smile","torch","length","purse","bind","rule","reopen","label","ask","town","town","argue"]
baseURL = T.pack "http://localhost:8090/"
manager <- newManager defaultManagerSettings
withCreateProcess launch $ \_ _ _ _ph -> do
threadDelay 1000000
action (baseURL, manager)

main :: IO ()
main = withWallet $ \http -> do
hspec $ do
describe "Cardano.NetworkLayer.HttpBridge" HttpBridge.spec

beforeAll (newMVar $ Context () http) $ do
describe "Integration test framework" dummySpec

dummySpec :: Scenarios Context
dummySpec = do
scenario "Try the API which isn't implemented yet" $ do
response <- request ("GET", "api/wallets") Nothing
verify (response :: Either RequestException Value)
[ expectError
]

scenario "request_ function is always successful" $ do
request_ ("GET", "api/xyzzy") Nothing
134 changes: 134 additions & 0 deletions test/integration/Test/Integration/Framework/DSL.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE LambdaCase #-}

module Test.Integration.Framework.DSL
(
-- * Scenario
scenario
, xscenario
, pendingWith
, Scenarios
, Context(..)

-- * Steps
, request
, request_
, successfulRequest
, verify

-- * Expectations
, expectSuccess
, expectError
, RequestException(..)

-- * Helpers
, ($-)
) where

import Prelude hiding
( fail )

import Control.Concurrent.MVar
( MVar )
import Control.Monad.Fail
( MonadFail (..) )
import Control.Monad.IO.Class
( MonadIO, liftIO )
import Data.Function
( (&) )
import Data.Text
( Text )
import GHC.Generics
( Generic )
import Network.HTTP.Client
( Manager )
import Test.Hspec.Core.Spec
( SpecM, it, xit )

import qualified Test.Hspec.Core.Spec as H

import Test.Integration.Framework.Request
( RequestException (..), request, request_, successfulRequest, ($-) )
import Test.Integration.Framework.Scenario
( Scenario )

--
-- SCENARIO
--

data Context = Context
{ _hlint :: ()
-- ^ Something to stop hlint complaining
, _manager
:: (Text, Manager)
-- ^ The underlying BaseUrl and Manager used by the Wallet Client
} deriving (Generic)


-- | Just a type-alias to 'SpecM', like 'scenario'. Ultimately, everything is
-- made in such way that we can use normal (albeit lifted) HSpec functions and
-- utilities if needed (and rely on its CLI as well when needed).
type Scenarios ctx = SpecM (MVar ctx) ()

-- | Just a slightly-specialized alias for 'it' to help lil'GHC.
scenario
:: String
-> Scenario Context IO ()
-> Scenarios Context
scenario = it

xscenario
:: String
-> Scenario Context IO ()
-> Scenarios Context
xscenario = xit

-- | Lifted version of `H.pendingWith` allowing for temporarily skipping
-- scenarios from execution with a reason, like:
--
-- scenario title $ do
-- pendingWith "This test fails due to bug #213"
-- test
pendingWith
:: (MonadIO m, MonadFail m)
=> String
-> m ()
pendingWith = liftIO . H.pendingWith

-- | Apply 'a' to all actions in sequence
verify :: (Monad m) => a -> [a -> m ()] -> m ()
verify a = mapM_ (a &)


-- | Expect an errored response, without any further assumptions
expectError
:: (MonadIO m, MonadFail m, Show a)
=> Either RequestException a
-> m ()
expectError = \case
Left _ -> return ()
Right a -> wantedErrorButSuccess a


-- | Expect a successful response, without any further assumptions
expectSuccess
:: (MonadIO m, MonadFail m, Show a)
=> Either RequestException a
-> m ()
expectSuccess = \case
Left e -> wantedSuccessButError e
Right _ -> return ()

wantedSuccessButError
:: (MonadFail m, Show e)
=> e
-> m void
wantedSuccessButError =
fail . ("expected a successful response but got an error: " <>) . show

wantedErrorButSuccess
:: (MonadFail m, Show a)
=> a
-> m void
wantedErrorButSuccess =
fail . ("expected an error but got a successful response: " <>) . show
Loading

0 comments on commit c96db92

Please sign in to comment.