haskellihp

How would I test IHP my CanRoute instance (parse route for beautiful URLs)?


If you want beautiful URLs in an IHP app you need to write your own CanRoute instance and parse the route string.

-- Web.Routes.hs

module Web.Routes where

import Generated.Types
import IHP.RouterPrelude
import Web.Types

instance CanRoute Co2ProducersController where
  parseRoute' = do
    string "/producers/"
    let co2ProducerById = do
          id <- parseId
          endOfInput
          pure ShowCo2ProducerAction {co2ProducerId = Just id, slug = Nothing}

        co2ProducerBySlug = do
          slug <- parseText
          pure ShowCo2ProducerAction {co2ProducerId = Nothing, slug = Just slug}

    co2ProducerBySlug <|> co2ProducerById

How would I go about testing this? I saw an example that seams to setup a whole test application here: https://github.com/digitallyinduced/ihp/blob/2422bbdfa6165231e89b44c2e7d1c68b65f6b3b4/Test/RouterSupportSpec.hs

But I only want to test if I parse the routes correctly and not send a request and test the response.

What would be a simple way to test the above code?


Solution

  • The parseRoute' function of the CanRoute we define for custom routes is basically just returning an attoparsec parser.

    We can use attoparsecs parseOnly to run the parser with a provided input string. Here's an example:

    module Test.Web.RoutesSpec where
    
    import Test.Hspec
    import IHP.ControllerPrelude
    import IHP.Test.Mocking
    import qualified Data.Attoparsec.ByteString as Attoparsec
    import Web.Types
    import Web.FrontController
    
    tests = beforeAll (mockContextNoDatabase WebApplication (pure ())) do
        describe "Web.Routes" do
            describe "DocumentationController" do
                it "should be available at /docs" $ withContext do
                    "/docs/api-reference/0bca60db-571e-4cdd-b02a-8d5b9e7e6295" `shouldRouteTo` DocumentationAction { projectId = "0bca60db-571e-4cdd-b02a-8d5b9e7e6295" }
    
    shouldRouteTo path action = (Attoparsec.parseOnly parseRoute' path) `shouldBe` (Right action)