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`. A little bit of the DSL module was
ported so that I could test the function.

Relates to #56
  • Loading branch information
rvl committed Mar 19, 2019
1 parent 8b1bcbc commit 1c8faa4
Show file tree
Hide file tree
Showing 6 changed files with 460 additions and 0 deletions.
20 changes: 20 additions & 0 deletions .weeder.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,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
41 changes: 41 additions & 0 deletions cardano-wallet.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,47 @@ test-suite unit
build-depends: unix, say
other-modules: Cardano.Launcher.POSIX

test-suite integration
default-language:
Haskell2010
default-extensions:
OverloadedStrings
NoImplicitPrelude
ghc-options:
-threaded -rtsopts
-Wall
-O2
if (!flag(development))
ghc-options:
-Werror

build-depends:
base
, aeson
, bytestring
, cardano-wallet
, exceptions
, generic-lens
, hspec
, hspec-core
, http-client
, http-types
, lens
, mtl
, process
, text

type:
exitcode-stdio-1.0
hs-source-dirs:
test/integration
main-is:
Main.hs
other-modules:
Test.Integration.Framework.DSL
Test.Integration.Framework.Request
Test.Integration.Framework.Scenario

executable cardano-wallet-server
default-language:
Haskell2010
Expand Down
52 changes: 52 additions & 0 deletions test/integration/Main.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
module Main where

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

import Data.Aeson
( Value )
import Data.String
( fromString )
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, scenario, unsafeRequest, verify )
import Test.Integration.Framework.Request
( RequestException (..) )

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
beforeAll (newMVar $ Context () http) $ do
describe "Dummy Request" dummySpec

dummySpec :: Scenarios Context
dummySpec = do
scenario "Try the API which isn't implemented yet" $ do
let endpoint = "api/wallets"
response <- unsafeRequest ("GET", fromString endpoint) Nothing
verify (response :: Either RequestException Value)
[ expectError
]
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
, unsafeRequest
, 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.Generics.Product.Typed
( HasType, typed )
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 (..), unsafeRequest, ($-) )
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 1c8faa4

Please sign in to comment.