Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How is this used with yesod-test? #42

Open
jezen opened this issue Aug 9, 2024 · 3 comments
Open

How is this used with yesod-test? #42

jezen opened this issue Aug 9, 2024 · 3 comments

Comments

@jezen
Copy link
Contributor

jezen commented Aug 9, 2024

Given I have some typical yesod-test scaffolding like this

withApp :: SpecWith (TestApp App) -> Spec
withApp = around (bracket beforeEach afterEach) . aroundWith (. fst)
  where
  beforeEach :: IO (TestApp App, ())
  beforeEach = do
    app <- makeFoundation ":memory:"
    pure ((app, defaultMiddlewaresNoLogging), ())

  afterEach :: (TestApp App, ()) -> IO ()
  afterEach ((app, _), _) = shutdownApp app

…how do I run yesod tests with hspec-hedgehog?

I'd like to write something like this (which, of course, doesn't work).

spec :: Spec
spec = withApp $ do

  it "Displays the param" $ hedgehog $ do
    -- for any given number…
    xs <- forAll $ Gen.int (Range.linear 0 1000)
    -- navigate to some page with that number
    get $ SomeRouteR xs
    -- assert that the page renders the number
    htmlAnyContain "p" xs
@parsonsmatt
Copy link
Collaborator

I wrote Effectful Property Testing which has my approach for it - but that has the assumption that you're doing some (forall x. m x -> IO x) inside of the test.

You can use a lambda to get the TestApp App -

spec = withApp do
  it "gimme" \testAppApp -> do
    -- now i'm in IO
    arrange (runYesodExample testAppApp) do
      -- now i'm writing a property
      xs <- forAll $ Gen.wahtever
      act do
        get $ SomeRouteR xs 
        htmlAnyContain "p" xs
        assert do pure ()

But unfortunately with yesod-test the code to do runYesodExample isn't exposed - you'd need to vendor it.

You may be interested in hspec-yesod, which I wrote to be a little more friendly to hspec idioms. I actually don't expose a runYesodExample function either, but the instance Example (YesodExample site) is much simpler than the one in yesod-test, and I'd be happy to extract that to a top-level named function to make it easier. I designed it for an almost 1:1 API correspondence so we could migrate our test suite over.

@jezen
Copy link
Contributor Author

jezen commented Aug 9, 2024

Thank you for the prompt and detailed response!

But unfortunately with yesod-test the code to do runYesodExample isn't exposed

Are you referring to evalSIO?

Separately, I take it that the last line in your example isn't actually needed?

@parsonsmatt
Copy link
Collaborator

parsonsmatt commented Aug 10, 2024

evalSIO is the first part, but you also need to construct a YesodExampleData site from your TestApp site. It's not too hard to vendor the instance Example (SIO (YesodExampleData site) _) code to get a TestApp site -> YesodExample site a -> IO a function though.

If you have the more specific typed functions arrange and act then you do need to return a pure () (or other === assertions) - they're typed like PropertyT IO (YesodExample site (PropertyT IO ())).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants