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?
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)