-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Write end2end web application tests using webdriver and hspec
--   
--   For end to end testing of web applications from Haskell, the
--   <a>webdriver</a> package is a great tool but just contains the code to
--   communicate with the browser. This package integrates webdriver with
--   <a>hspec</a>.
@package hspec-webdriver
@version 1.2.0


-- | Write hspec tests that are webdriver tests, automatically managing the
--   webdriver sessions.
--   
--   This module re-exports functions from <a>Test.Hspec</a> and
--   <a>Test.WebDriver.Commands</a> and it is intended that you just import
--   <tt>Test.Hspec.WebDriver</tt>. If you need to import
--   <tt>Test.Hspec</tt> or <tt>Test.WebDriver</tt>, you should do so using
--   a qualified import.
--   
--   <pre>
--   {-# LANGUAGE OverloadedStrings #-}
--   module XKCD where
--   
--   import Test.Hspec.WebDriver
--   
--   allBrowsers :: [Capabilities]
--   allBrowsers = [firefoxCaps, chromeCaps, ieCaps]
--   
--   browsersExceptIE :: [Capabilities]
--   browsersExceptIE = [firefoxCaps, chromeCaps]
--   
--   main :: IO ()
--   main = hspec $
--       describe "XKCD Tests" $ do
--   
--           session "for 327" $ using allBrowsers $ do
--               it "opens the page" $ runWD $
--                   openPage "http://www.xkcd.com/327/"
--               it "checks hover text" $ runWD $ do
--                   e &lt;- findElem $ ByCSS "div#comic &gt; img"
--                   e `shouldBeTag` "img"
--                   e `shouldHaveAttr` ("title", "Her daughter is named Help I'm trapped in a driver's license factory.")
--   
--           parallel $ session "for 303" $ using browsersExceptIE $ do
--               it "opens the page" $ runWD $
--                   openPage "http://www.xkcd.com/303/"
--               it "checks the title" $ runWD $ do
--                   e &lt;- findElem $ ById "ctitle"
--                   e `shouldBeTag` "div"
--                   e `shouldHaveText` "Compiling"
--   </pre>
--   
--   The above code assumes selenium-server-standalone is running on
--   <tt>127.0.0.1:4444</tt> at path <tt>/wd/hub</tt> (this is the
--   default).
module Test.Hspec.WebDriver

-- | A webdriver example.
--   
--   The webdriver action of type <tt><a>WD</a> ()</tt> should interact
--   with the webpage using commands from <a>Test.WebDriver.Commands</a>
--   (which is re-exported from this module) and then use the
--   <a>expectations</a> in this module. It is possible to split up the
--   spec of a single page into multiple examples where later examples
--   start with the web browser state from the end of the previous example.
--   This is helpful to keep each individual example small and allows the
--   entire spec to be described at the beginning with pending examples.
--   
--   The way this works is that you combine examples into a session using
--   <a>session</a> or <a>sessionWith</a>. A webdriver session is then
--   threaded through all examples in a session so that a later example in
--   the session can rely on the webbrowser state as set up by the previous
--   example. The type system enforces that every webdriver example must be
--   located within a call to <a>session</a> or <a>sessionWith</a>. Indeed,
--   a <a>WdExample</a> produces a <tt><a>SpecWith</a>
--   (<a>WdTestSession</a> multi)</tt> which can only be converted to
--   <a>Spec</a> using <a>session</a> or <a>sessionWith</a>. The reason for
--   the <a>WdPending</a> constructor is so that a pending example can be
--   specified with type <tt><a>SpecWith</a> (<a>WdTestSession</a>
--   multi)</tt> so it can compose with the other webdriver examples.
--   
--   The type <tt>multi</tt> is used when testing multiple sessions at once
--   (e.g. to test multiple interacting users), otherwise it is
--   <tt>()</tt>. Values of this type are used to determine which browser
--   session the example should be executed against. A new session is
--   created every time a new value of type <tt>multi</tt> is seen. Note
--   that the type system enforces that every example within the session
--   has the same type <tt>multi</tt>.
data WdExample multi
WdExample :: multi -> WdOptions -> (WD ()) -> WdExample multi
WdPending :: (Maybe String) -> WdExample multi

-- | Optional options that can be passed to <a>runWDOptions</a>.
data WdOptions
WdOptions :: Bool -> WdOptions

-- | As soon as an example fails, skip all remaining tests in the session.
--   Defaults to True.
[skipRemainingTestsAfterFailure] :: WdOptions -> Bool

-- | A shorthand for constructing a <a>WdExample</a> from a webdriver
--   action when you are only testing a single browser session at once. See
--   the XKCD example at the top of the page.
runWD :: WD () -> WdExample ()

-- | A version of runWD that accepts some custom options
runWDOptions :: WdOptions -> WD () -> WdExample ()

-- | Create a webdriver example, specifying which of the multiple sessions
--   the example should be executed against. I suggest you create an
--   enumeration for multi, for example:
--   
--   <pre>
--   data TestUser = Gandolf | Bilbo | Legolas
--       deriving (Show, Eq, Enum, Bounded)
--   
--   runUser :: TestUser -&gt; WD () -&gt; WDExample TestUser
--   runUser = runWDWith
--   
--   spec :: Spec
--   spec = session "tests some page" $ using [firefoxCaps] $ do
--       it "does something with Gandolf" $ runUser Gandolf $ do
--           openPage ...
--       it "does something with Bilbo" $ runUser Bilbo $ do
--           openPage ...
--       it "goes back to the Gandolf session" $ runUser Gandolf $ do
--           e &lt;- findElem ....
--           ...
--   </pre>
--   
--   In the above code, two sessions are created and the examples will go
--   back and forth between the two sessions. Note that a session for
--   Legolas will only be created the first time he shows up in a call to
--   <tt>runUser</tt>, which might be never. To share information between
--   the sessions (e.g. some data that Gandolf creates that Bilbo should
--   expect), the best way I have found is to use IORefs created with
--   <a>runIO</a> (wrapped in a utility module).
runWDWith :: multi -> WD () -> WdExample multi

-- | A version of runWDWith that accepts some custom options
runWDWithOptions :: multi -> WdOptions -> WD () -> WdExample multi

-- | A pending example.
pending :: WdExample multi

-- | A pending example with a message.
pendingWith :: String -> WdExample multi

-- | A version of <a>example</a> which lifts an <tt>IO ()</tt> to a
--   webdriver example (so it can be composed with other webdriver
--   examples). In the case of multiple sessions, it doesn't really matter
--   which session the expectation is executed against, so a default value
--   is used. In the case of single sessions, the type is <tt>WdExample
--   ()</tt>.
example :: Default multi => Expectation -> WdExample multi

-- | Combine the examples nested inside this call into a webdriver session
--   or multiple sessions. For each of the capabilities in the list, the
--   examples are executed one at a time in depth-first order and so later
--   examples can rely on the browser state created by earlier examples.
--   These passes through the examples are independent for different
--   capabilities. Note that when using <a>parallel</a>, the examples
--   within a single pass still execute serially. Different passes through
--   the examples will be executed in parallel. The sessions are managed as
--   follows:
--   
--   <ul>
--   <li>In the simplest case when <tt>multi</tt> is <tt>()</tt>, before
--   the first example is executed a new webdriver session with the given
--   capabilities is created. The examples are then executed in depth-first
--   order, and the session is then closed when either an exception occurs
--   or the examples complete. (The session can be left open with
--   <a>inspectSession</a>).</li>
--   <li>More generally, as the examples are executed, each time a new
--   value of type <tt>multi</tt> is seen, a new webdriver session with the
--   capabilities is automatically created. Later examples will continue
--   with the session matching their value of <tt>multi</tt>.</li>
--   </ul>
--   
--   This function uses the default webdriver host (127.0.0.1), port
--   (4444), and basepath (<tt>/wd/hub</tt>).
session :: String -> ([Capabilities], SpecWith (WdTestSession multi)) -> Spec

-- | A variation of <a>session</a> which allows you to specify the
--   webdriver configuration. Note that the capabilities in the
--   <a>WDConfig</a> will be ignored, instead the capabilities will come
--   from the list of <a>Capabilities</a> passed to <a>sessionWith</a>.
--   
--   In addition, each capability is paired with a descriptive string which
--   is passed to hspec to describe the example. By default, <a>session</a>
--   uses the browser name as the description. <a>sessionWith</a> supports
--   a more detailed description so that in the hspec output you can
--   distinguish between capabilities that share the same browser but
--   differ in the details, for example capabilities with and without
--   javascript.
sessionWith :: WDConfig -> String -> ([(Capabilities, String)], SpecWith (WdTestSession multi)) -> Spec

-- | Abort the session without closing the session.
--   
--   Normally, <a>session</a> will automatically close the session either
--   when the tests complete without error or when any of the tests within
--   the session throws an error. When developing the test suite, this can
--   be annoying since closing the session causes the browser window to
--   close. Therefore, while developing the test suite, you can insert a
--   call to <a>inspectSession</a>. This will immedietly halt the session
--   (all later tests will fail) but will not close the session so that the
--   browser window stays open.
inspectSession :: WD ()

-- | A synonym for constructing pairs that allows the word <tt>using</tt>
--   to be used with <a>session</a> so that the session description reads
--   like a sentance.
--   
--   <pre>
--   allBrowsers :: [Capabilities]
--   allBrowsers = [firefoxCaps, chromeCaps, ieCaps]
--   
--   browsersExceptIE :: [Capabilities]
--   browsersExceptIE = [firefoxCaps, chromeCaps]
--   
--   mobileBrowsers :: [Capabilities]
--   mobileBrowsers = [iphoneCaps, ipadCaps, androidCaps]
--   
--   myspec :: Spec
--   myspec = do
--     session "for the home page" $ using allBrowsers $ do
--       it "loads the page" $ runWD $ do
--           ...
--       it "scrolls the carosel" $ runWD $ do
--           ...
--     session "for the users page" $ using browsersExceptIE $ do
--       ...
--   </pre>
using :: [caps] -> SpecWith (WdTestSession multi) -> ([caps], SpecWith (WdTestSession multi))

-- | Internal state for webdriver test sessions.
data WdTestSession multi

-- | Default capabilities which can be used in the list passed to
--   <a>using</a>. I suggest creating a top-level definition such as
--   <tt>allBrowsers</tt> and <tt>browsersWithoutIE</tt> such as in the
--   XKCD example at the top of the page, so that you do not specify the
--   browsers in the individual spec.
firefoxCaps :: Capabilities

-- | Default capabilities which can be used in the list passed to
--   <a>using</a>. I suggest creating a top-level definition such as
--   <tt>allBrowsers</tt> and <tt>browsersWithoutIE</tt> such as in the
--   XKCD example at the top of the page, so that you do not specify the
--   browsers in the individual spec.
chromeCaps :: Capabilities

-- | Default capabilities which can be used in the list passed to
--   <a>using</a>. I suggest creating a top-level definition such as
--   <tt>allBrowsers</tt> and <tt>browsersWithoutIE</tt> such as in the
--   XKCD example at the top of the page, so that you do not specify the
--   browsers in the individual spec.
ieCaps :: Capabilities

-- | Default capabilities which can be used in the list passed to
--   <a>using</a>. I suggest creating a top-level definition such as
--   <tt>allBrowsers</tt> and <tt>browsersWithoutIE</tt> such as in the
--   XKCD example at the top of the page, so that you do not specify the
--   browsers in the individual spec.
operaCaps :: Capabilities

-- | Default capabilities which can be used in the list passed to
--   <a>using</a>. I suggest creating a top-level definition such as
--   <tt>allBrowsers</tt> and <tt>browsersWithoutIE</tt> such as in the
--   XKCD example at the top of the page, so that you do not specify the
--   browsers in the individual spec.
iphoneCaps :: Capabilities

-- | Default capabilities which can be used in the list passed to
--   <a>using</a>. I suggest creating a top-level definition such as
--   <tt>allBrowsers</tt> and <tt>browsersWithoutIE</tt> such as in the
--   XKCD example at the top of the page, so that you do not specify the
--   browsers in the individual spec.
ipadCaps :: Capabilities

-- | Default capabilities which can be used in the list passed to
--   <a>using</a>. I suggest creating a top-level definition such as
--   <tt>allBrowsers</tt> and <tt>browsersWithoutIE</tt> such as in the
--   XKCD example at the top of the page, so that you do not specify the
--   browsers in the individual spec.
androidCaps :: Capabilities

-- | <a>shouldBe</a> lifted into the <a>WD</a> monad.
shouldBe :: (Show a, Eq a) => a -> a -> WD ()

-- | Asserts that the given element matches the given tag.
shouldBeTag :: Element -> Text -> WD ()

-- | Asserts that the given element has the given text.
shouldHaveText :: Element -> Text -> WD ()

-- | Asserts that the given elemnt has the attribute given by <tt>(attr
--   name, value)</tt>.
shouldHaveAttr :: Element -> (Text, Text) -> WD ()

-- | Asserts that the action returns the expected result.
shouldReturn :: (Show a, Eq a) => WD a -> a -> WD ()

-- | Asserts that the action throws an exception.
shouldThrow :: (Show e, Eq e, Exception e) => WD a -> e -> WD ()

-- | Run given spec and write a report to <a>stdout</a>. Exit with
--   <a>exitFailure</a> if at least one spec item fails.
hspec :: Spec -> IO ()
type Spec = SpecWith ()
type SpecWith a = SpecM a ()

-- | The <tt>describe</tt> function combines a list of specs into a larger
--   spec.
describe :: String -> SpecWith a -> SpecWith a

-- | <tt>context</tt> is an alias for <a>describe</a>.
context :: String -> SpecWith a -> SpecWith a

-- | The <tt>it</tt> function creates a spec item.
--   
--   A spec item consists of:
--   
--   <ul>
--   <li>a textual description of a desired behavior</li>
--   <li>an example for that behavior</li>
--   </ul>
--   
--   <pre>
--   describe "absolute" $ do
--     it "returns a positive number when given a negative number" $
--       absolute (-1) == 1
--   </pre>
it :: (HasCallStack, Example a) => String -> a -> SpecWith (Arg a)

-- | <tt>specify</tt> is an alias for <a>it</a>.
specify :: (HasCallStack, Example a) => String -> a -> SpecWith (Arg a)

-- | <a>parallel</a> marks all spec items of the given spec to be safe for
--   parallel evaluation.
parallel :: SpecWith a -> SpecWith a

-- | Run an IO action while constructing the spec tree.
--   
--   <a>SpecM</a> is a monad to construct a spec tree, without executing
--   any spec items. <tt>runIO</tt> allows you to run IO actions during
--   this construction phase. The IO action is always run when the spec
--   tree is constructed (e.g. even when <tt>--dry-run</tt> is specified).
--   If you do not need the result of the IO action to construct the spec
--   tree, <a>beforeAll</a> may be more suitable for your use case.
runIO :: IO r -> SpecM a r

-- | A state monad for WebDriver commands.
data WD a :: * -> *

-- | A structure describing the capabilities of a session. This record
--   serves dual roles.
--   
--   <ul>
--   <li>It's used to specify the desired capabilities for a session before
--   it's created. In this usage, fields that are set to Nothing indicate
--   that we have no preference for that capability.</li>
--   <li>When received from the server , it's used to describe the actual
--   capabilities given to us by the WebDriver server. Here a value of
--   Nothing indicates that the server doesn't support the capability.
--   Thus, for Maybe Bool fields, both Nothing and Just False indicate a
--   lack of support for the desired capability.</li>
--   </ul>
data Capabilities :: *
instance GHC.Show.Show Test.Hspec.WebDriver.AbortSession
instance Data.Default.Class.Default Test.Hspec.WebDriver.WdOptions
instance GHC.Exception.Exception Test.Hspec.WebDriver.AbortSession
instance GHC.Classes.Eq multi => Test.Hspec.Core.Example.Example (Test.Hspec.WebDriver.WdExample multi)
