packages feed

marionette-1.0.0: src/Test/Marionette.hs

-- |
-- Module      : Test.Marionette
-- Copyright   : (c) 2026 Institute for Digital Autonomy
-- License     : EUPL-1.2
-- Maintainer  : IDA
--
-- <https://firefox-source-docs.mozilla.org/testing/marionette/ Marionette> is
-- Firefox's built-in remote-control protocol. It plays the same role as a
-- <https://www.w3.org/TR/webdriver/ WebDriver> server, letting a test suite
-- drive a real Firefox instance to navigate, find and interact with
-- elements, execute scripts, and so on. In addition to WebDriver functionality,
-- Marionette can also address Firefox's own chrome (its menus and toolbars)
-- rather than just the content of a web page, and speaks its own lightweight
-- length-prefixed JSON protocol directly over a TCP socket instead of
-- HTTP.
--
-- This library provides 'Marionette', a typeclass for sending commands to a
-- running Firefox process, as well as an implementation of every Marionette
-- and WebDriver command.
-- A concrete implementation can be found in 'MarionetteT'/'runMarionetteT'.
--
-- = How to use Marionette
--
-- == Starting Firefox and a session
--
-- Launch Firefox with the @--marionette@ flag so that it listens for
-- connections on port 2828.
--
-- Use 'runMarionetteT' to connect to it and run a client program.
-- Start a new session with 'newSession', and quit the session with 'quit':
--
-- > import System.Process.Typed
-- > import Test.Marionette
-- >
-- > main :: IO ()
-- > main =
-- >   withProcessTerm_ (proc "firefox" ["--marionette", "--headless"]) $ \_process ->
-- >       runMarionetteT $ do
-- >           newSession
-- >           -- More Marionette actions go here
-- >           quit
--
-- Most Marionette actions need to be performed in a session.
--
-- == Finding and interacting with elements
--
-- Find elements by calling 'findElement' with a 'Selector',
-- then pass the resulting 'Element' to other commands:
--
-- > submitForm :: (HasCallStack, Marionette m) => m ()
-- > submitForm = do
-- >   input <- findElement (ById "text-input")
-- >   elementSendKeys input "hello, world"
-- >   submit <- findElement (ByCSS "button[type=submit]")
-- >   elementClick submit
--
-- == Error handling
--
-- Catch command failures via 'MonadError',
-- for example to retry a command against a fallback element:
--
-- > import Control.Monad.Error.Class (catchError)
-- >
-- > clickFirstAvailable :: (HasCallStack, Marionette m) => m ()
-- > clickFirstAvailable =
-- >   (elementClick =<< findElement (ById "primary-button"))
-- >     `catchError` \_ -> elementClick =<< findElement (ById "fallback-button")
module Test.Marionette
    ( module Test.Marionette.Class
    , module Test.Marionette.Client
    , module Test.Marionette.Commands
    , module Test.Marionette.Cookie
    , module Test.Marionette.Context
    , module Test.Marionette.Frame
    , module Test.Marionette.Element
    , module Test.Marionette.Orientation
    , module Test.Marionette.Protocol
    , module Test.Marionette.Rect
    , module Test.Marionette.Registry
    , module Test.Marionette.Selector
    , module Test.Marionette.Timeouts
    , module Test.Marionette.WebAuthn
    , module Test.Marionette.Window
    )
where

import Test.Marionette.Class (Marionette)
import Test.Marionette.Client (MarionetteT, runMarionetteT)
import Test.Marionette.Commands
import Test.Marionette.Context (Context (..))
import Test.Marionette.Cookie (Cookie (Cookie))
import Test.Marionette.Element (Element, Shadow)
import Test.Marionette.Frame (Frame (..))
import Test.Marionette.Orientation (Orientation (..))
import Test.Marionette.Protocol (Error (Error))
import Test.Marionette.Rect (Rect (Rect))
import Test.Marionette.Registry (RegistryEntry (RegistryEntry))
import Test.Marionette.Selector
    ( Selector (..)
    , SelectorFrom (..)
    , SelectorFromShadowRoot (..)
    )
import Test.Marionette.Timeouts (Timeouts (Timeouts))
import Test.Marionette.WebAuthn
    ( AuthenticatorId
    , Credential (Credential)
    , CredentialId
    , VirtualAuthenticator (VirtualAuthenticator)
    )
import Test.Marionette.Window
    ( NewWindowResult (..)
    , WindowHandle
    , WindowType (..)
    )