0

I have an application written on top of Wai, configured to have some custom state and be testable with Test.Hspec.Wai.

I can test request/response interactions, but I haven't been able to figure out how to test for state changes; specifically, if my application state is a TVar Text, how do I get the value out of it inside the test, in order to verify its value?

-- app :: TVar Text -> IO Application
-- is defined in my application library

wrapp :: Text -> IO (TVar Text, Application)
wrapp s = do
  s' <- newTVarIO s
  a <- app s'
  return (s', a)

spec :: Spec
spec = withState (wrapp "hello") $ do
  describe "x" $ it "x" $ do
      st <- getState -- st is TVar Text.
      s <- undefined -- WHAT DO I PUT HERE TO GET THE STATE OUT OF TVar?
      get "/" `shouldRespondWith` "\"hello, world!\""
      s `shouldBe` "hello"

*) Note that the getState method I'm talking about here is not exported in the latest LTS at the time of writing; add hspec-wai-0.10.1 to extra-deps to get a version that has all the features mentioned here.

Tomas Aschan
  • 58,548
  • 56
  • 243
  • 402
  • I think, you did right, only got confused with types. What's `st` in your case? Does `stuff` really accept that? – arrowd Nov 14 '19 at 07:26
  • @arrowd Yeah, confused with types is exactly my problem, I guess. The `st` in my question is just the wording from the Hspec-Wai documentation; it's not really clear to me what it is, or should be, for it to work. `stuff` is a getter on my state type (my state is basically `type MyState = MyState { stuff :: Maybe Text }`, so _if_ I manage to tell the test what my state type is correctly, then it should work. Once I have this working, I'm also going to want to modify my state to be a `TVar MyState`, so that might complicate things I guess... :/ – Tomas Aschan Nov 18 '19 at 21:23

1 Answers1

-1

I think the problem is that you forgot to wrap whole your spec into with app, like it is done in hspec-wais README:

spec :: Spec
spec = with app $ do
  describe "GET /" $ do
    it "responds with 200" $ do
      get "/" `shouldRespondWith` 200
arrowd
  • 33,231
  • 8
  • 79
  • 110
  • Note that in my original snippet I do have `with app`, but not at the top-level of the stack. If I have to move it there, how do I control the initial state of the app? – Tomas Aschan Nov 20 '19 at 19:39
  • I re-worded the question and provided a shorter code sample of what I'm trying to do; would you mind taking another look? – Tomas Aschan Nov 21 '19 at 21:28
  • https://hackage.haskell.org/package/stm-2.5.0.0/docs/Control-Concurrent-STM-TVar.html#v:readTVarIO this? – arrowd Nov 22 '19 at 03:38
  • Unfortunately that doesn't compile; it gives me a type mismatch, expecting a `WaiSession a b` (don't remeber the exact types of `a` and `b` now, but can check when I get home) but getting an `IO Text` – Tomas Aschan Nov 22 '19 at 10:00
  • `WaiSession` is an instance of `MonadIO`, so you can use `liftIO` to turn `IO` into `WaiSession`. – arrowd Nov 22 '19 at 10:53