Yesod.Test is a pragmatic framework for testing web applications built using wai and persistent.
By pragmatic I may also mean
dirty. It's main goal is to encourage integration
and system testing of web applications by making everything easy to test.
Your tests are like browser sessions that keep track of cookies and the last visited page. You can perform assertions on the content of HTML responses, using css selectors to explore the document more easily.
You can also easily build requests using forms present in the current page.
This is very useful for testing web applications built in yesod for example,
were your forms may have field names generated by the framework or a randomly
Your database is also directly available so you can use runDBRunner to set up backend pre-conditions, or to assert that your session is having the desired effect.
- runTests :: Application -> Pool conn -> SpecsConn conn -> IO ()
- describe :: String -> SpecsConn conn -> SpecsConn conn
- it :: String -> OneSpec conn () -> SpecsConn conn
- type SpecsConn conn = StateT (SpecsData conn) IO ()
- type OneSpec conn = StateT (OneSpecData conn) IO
- post :: ByteString -> RequestBuilder () -> OneSpec conn ()
- post_ :: ByteString -> OneSpec conn ()
- get :: ByteString -> RequestBuilder () -> OneSpec conn ()
- get_ :: ByteString -> OneSpec conn ()
- doRequest :: Method -> ByteString -> RequestBuilder a -> OneSpec conn ()
- byName :: Text -> Text -> RequestBuilder ()
- fileByName :: Text -> FilePath -> Text -> RequestBuilder ()
- byLabel :: Text -> Text -> RequestBuilder ()
- fileByLabel :: Text -> FilePath -> Text -> RequestBuilder ()
- addNonce :: RequestBuilder ()
- addNonce_ :: Query -> RequestBuilder ()
- runDBRunner :: (MonadBaseControl IO m, MonadIO m) => (poolrunner m a -> Pool conn -> IO a) -> poolrunner m a -> OneSpec conn a
- assertEqual :: Eq a => String -> a -> a -> OneSpec conn ()
- assertHeader :: HoldsResponse a => CI ByteString -> ByteString -> StateT a IO ()
- assertNoHeader :: HoldsResponse a => CI ByteString -> StateT a IO ()
- statusIs :: HoldsResponse a => Int -> StateT a IO ()
- bodyEquals :: HoldsResponse a => String -> StateT a IO ()
- bodyContains :: HoldsResponse a => String -> StateT a IO ()
- htmlAllContain :: HoldsResponse a => Query -> String -> StateT a IO ()
- htmlCount :: HoldsResponse a => Query -> Int -> StateT a IO ()
- printBody :: HoldsResponse a => StateT a IO ()
- printMatches :: HoldsResponse a => Query -> StateT a IO ()
- htmlQuery :: HoldsResponse a => Query -> StateT a IO [Html]
- parseHTML :: Html -> Cursor
- withResponse :: HoldsResponse a => (SResponse -> StateT a IO b) -> StateT a IO b
Declaring and running your test suite
Runs your test suite, using you wai
ConnectionPool for performing
the database queries in your tests.
You application may already have your connection pool but you need to pass another one separately here.
Look at the examples directory on this package to get an idea of the (small) amount of boilerplate code you'll need to write before calling this.
Start describing a Tests suite keeping cookies and a reference to the tested
Describe a single test that keeps cookies, and a reference to the last response.
The specs state monad is where
parameterized by a database connection.
You should create type Specs = SpecsConn MyDBConnection
To make a request you need to point to an url and pass in some parameters.
To build your parameters you will use the RequestBuilder monad that lets you add values, add files, lookup fields by label and find the current nonce value and add it to your request too.
Perform a POST request to url, using params
Perform a GET request to url, using params
General interface to performing requests, letting you specify the request method and extra headers.
Add a file to be posted with the current request
Adding a file will automatically change your request content-type to be multipart/form-data
Yesod cat auto generate field ids, so you are never sure what the argument name should be for each one of your args when constructing your requests. What you do know is the label of the field. These functions let you add parameters to your request based on currently displayed label names.
Does the current form have a _nonce? Use any of these to add it to your request parameters.
For responses that display a single form, just lookup the only nonce available.
Lookup a _nonce form field and add it's value to the params. Receives a CSS selector that should resolve to the form element containing the nonce.
Running database queries
Run a persistent db query. For asserting on the results of performed actions or setting up pre-conditions. At the moment this part is still very raw.
It is intended that you parametize the first argument of this function for your backend runDB = runDBRunnder SqlPersist
Asserts that the two given values are equal.
Assert the given header key/value pair was returned.
Assert the given header was not included in the response.
Assert the last response status is as expected.
Assert the last response is exactly equal to the given text. This is useful for testing API responses.
Assert the last response has the given text. The check is performed using the response body in full text form.
Queries the html using a css selector, and all matched elements must contain the given string.
Performs a css query on the last response and asserts the matched elements are as many as expected.
Utils for debugging tests
Outputs the last response body to stderr (So it doesn't get captured by HSpec)
Performs a CSS query and print the matches to stderr.
Utils for building your own assertions
Please consider generalizing and contributing the assertions you write.
Query the last response using css selectors, returns a list of matched fragments
Use HXT to parse a value from an html tag. Check for usage examples in this module's source.