packages feed

webdriver-precore-0.0.0.2: test/ApiCoverageTest.hs

module ApiCoverageTest where

import Data.Set as S (Set, difference, fromList, null)
import Data.Text as T (Text, lines, null, pack, replace, strip, unwords, words, intercalate)
import GHC.Utils.Misc (filterOut)
import Test.Tasty.HUnit as HUnit ( assertBool, Assertion )
import Text.RawString.QQ (r)
import WebDriverPreCore
    ( SessionId(Session),
      ElementId(Element),
      Selector(CSS),
      WindowHandle(Handle),
      WindowRect(Rect),
      FrameReference(TopLevelFrame),
      Cookie(MkCookie),
      Actions(MkActions),
      Timeouts(..),
      W3Spec(description, Get, Post, PostEmpty, Delete, path),
      minFirefoxCapabilities,
      acceptAlert,
      addCookie,
      back,
      closeWindow,
      deleteAllCookies,
      deleteCookie,
      deleteSession,
      dismissAlert,
      elementClear,
      elementClick,
      elementSendKeys,
      executeScript,
      executeScriptAsync,
      findElement,
      findElementFromElement,
      findElementFromShadowRoot,
      findElements,
      findElementsFromElement,
      findElementsFromShadowRoot,
      forward,
      fullscreenWindow,
      getActiveElement,
      getAlertText,
      getAllCookies,
      getCurrentUrl,
      getElementAttribute,
      getElementComputedLabel,
      getElementComputedRole,
      getElementCssValue,
      getElementProperty,
      getElementRect,
      getElementShadowRoot,
      getElementTagName,
      getElementText,
      getNamedCookie,
      getPageSource,
      getTimeouts,
      getTitle,
      getWindowHandle,
      getWindowHandles,
      getWindowRect,
      isElementEnabled,
      isElementSelected,
      maximizeWindow,
      minimizeWindow,
      navigateTo,
      newSession,
      newWindow,
      performActions,
      printPage,
      refresh,
      releaseActions,
      sendAlertText,
      setTimeouts,
      setWindowRect,
      status,
      switchToFrame,
      switchToParentFrame,
      switchToWindow,
      takeElementScreenshot,
      takeScreenshot )
import GHC.Show (Show (..))
import Data.Eq (Eq)
import Data.Ord (Ord)
import Data.Function (($), (.))
import Data.Semigroup ((<>))
import Data.List ((!!), drop)
import Data.Functor ((<$>))
import Data.Maybe (Maybe(..))
import WebDriverPreCore (UrlPath(..))


{-- TODO use Haddock variable
 Covers Spec Version https://www.w3.org/TR/2025/WD-webdriver2-20250306 
 --}


{-
!! Replace this the endepoints from the spec with every release
https://www.w3.org/TR/2025/WD-webdriver2-20250306 - W3C Editor's Draft 10 February 2025
61 endpoints
Method 	URI Template 	Command
POST 	/session 	New Session
-}
endPointsCopiedFromSpc :: Text
endPointsCopiedFromSpc = pack 
  [r|POST 	/session 	New Session
DELETE 	/session/{session id} 	Delete Session
GET 	/status 	Status
GET 	/session/{session id}/timeouts 	Get Timeouts
POST 	/session/{session id}/timeouts 	Set Timeouts
POST 	/session/{session id}/url 	Navigate To
GET 	/session/{session id}/url 	Get Current URL
POST 	/session/{session id}/back 	Back
POST 	/session/{session id}/forward 	Forward
POST 	/session/{session id}/refresh 	Refresh
GET 	/session/{session id}/title 	Get Title
GET 	/session/{session id}/window 	Get Window Handle
DELETE 	/session/{session id}/window 	Close Window
POST 	/session/{session id}/window 	Switch To Window
GET 	/session/{session id}/window/handles 	Get Window Handles
POST 	/session/{session id}/window/new 	New Window
POST 	/session/{session id}/frame 	Switch To Frame
POST 	/session/{session id}/frame/parent 	Switch To Parent Frame
GET 	/session/{session id}/window/rect 	Get Window Rect
POST 	/session/{session id}/window/rect 	Set Window Rect
POST 	/session/{session id}/window/maximize 	Maximize Window
POST 	/session/{session id}/window/minimize 	Minimize Window
POST 	/session/{session id}/window/fullscreen 	Fullscreen Window
GET 	/session/{session id}/element/active 	Get Active Element
GET 	/session/{session id}/element/{element id}/shadow 	Get Element Shadow Root
POST 	/session/{session id}/element 	Find Element
POST 	/session/{session id}/elements 	Find Elements
POST 	/session/{session id}/element/{element id}/element 	Find Element From Element
POST 	/session/{session id}/element/{element id}/elements 	Find Elements From Element
POST 	/session/{session id}/shadow/{shadow id}/element 	Find Element From Shadow Root
POST 	/session/{session id}/shadow/{shadow id}/elements 	Find Elements From Shadow Root
GET 	/session/{session id}/element/{element id}/selected 	Is Element Selected
GET 	/session/{session id}/element/{element id}/attribute/{name} 	Get Element Attribute
GET 	/session/{session id}/element/{element id}/property/{name} 	Get Element Property
GET 	/session/{session id}/element/{element id}/css/{property name} 	Get Element CSS Value
GET 	/session/{session id}/element/{element id}/text 	Get Element Text
GET 	/session/{session id}/element/{element id}/name 	Get Element Tag Name
GET 	/session/{session id}/element/{element id}/rect 	Get Element Rect
GET 	/session/{session id}/element/{element id}/enabled 	Is Element Enabled
GET 	/session/{session id}/element/{element id}/computedrole 	Get Computed Role
GET 	/session/{session id}/element/{element id}/computedlabel 	Get Computed Label
POST 	/session/{session id}/element/{element id}/click 	Element Click
POST 	/session/{session id}/element/{element id}/clear 	Element Clear
POST 	/session/{session id}/element/{element id}/value 	Element Send Keys
GET 	/session/{session id}/source 	Get Page Source
POST 	/session/{session id}/execute/sync 	Execute Script
POST 	/session/{session id}/execute/async 	Execute Async Script
GET 	/session/{session id}/cookie 	Get All Cookies
GET 	/session/{session id}/cookie/{name} 	Get Named Cookie
POST 	/session/{session id}/cookie 	Add Cookie
DELETE 	/session/{session id}/cookie/{name} 	Delete Cookie
DELETE 	/session/{session id}/cookie 	Delete All Cookies
POST 	/session/{session id}/actions 	Perform Actions
DELETE 	/session/{session id}/actions 	Release Actions
POST 	/session/{session id}/alert/dismiss 	Dismiss Alert
POST 	/session/{session id}/alert/accept 	Accept Alert
GET 	/session/{session id}/alert/text 	Get Alert Text
POST 	/session/{session id}/alert/text 	Send Alert Text
GET 	/session/{session id}/screenshot 	Take Screenshot
GET 	/session/{session id}/element/{element id}/screenshot 	Take Element Screenshot
POST 	/session/{session id}/print   Print Page
|]

parseLine :: Text -> SpecLine
parseLine line = MkSpecLine method uriTemplate command
  where
    segments = filterOut T.null $ T.words $ replaceTemplateTxt line
    method = case segments of
      [] -> "PARSER ERROR NO METHOD IN LINE" <> line
      x : _ -> x
    uriTemplate = segments !! 1
    command = T.unwords $ drop 2 segments

specLinesFromSpec :: Set SpecLine
specLinesFromSpec = fromList $ parseLine <$> filterOut T.null (strip <$> T.lines endPointsCopiedFromSpc)

sessionId :: Text
sessionId = "session_id"

session :: SessionId
session = Session sessionId

elementId :: Text
elementId = "element_id"

element :: ElementId
element = Element elementId

windowHandle :: WindowHandle
windowHandle = Handle "window-handle"

selector :: Selector
selector = CSS "Blahh"

name :: Text
name = "name"

data SpecLine = MkSpecLine
  { method :: Text,
    uriTemplate :: Text,
    command :: Text
  }
  deriving (Show, Eq, Ord)

replaceTemplateTxt :: Text -> Text
replaceTemplateTxt =
  replace "{property name}" name
    . replace "{name}" name
    . replace "{session id}" sessionId
    . replace "{element id}" elementId
    . replace "{shadow id}" elementId

toSpecLine :: W3Spec a -> SpecLine
toSpecLine w3 = case w3 of
  Get {} -> MkSpecLine "GET" path command
  Post {} -> MkSpecLine "POST" path command
  PostEmpty {} -> MkSpecLine "POST" path command
  Delete {} -> MkSpecLine "DELETE" path command
  where
    command = w3.description
    path = replaceTemplateTxt $ "/" <> intercalate "/" w3.path.segments

allSpecsSample :: Set SpecLine
allSpecsSample =
  fromList
    [ toSpecLine $ newSession minFirefoxCapabilities,
      toSpecLine status,
      toSpecLine $ maximizeWindow session,
      toSpecLine $ minimizeWindow session,
      toSpecLine $ fullscreenWindow session,
      toSpecLine $ getTimeouts session,
      toSpecLine $ setTimeouts session $ MkTimeouts Nothing Nothing Nothing,
      toSpecLine $ switchToFrame session TopLevelFrame,
      toSpecLine $ getCurrentUrl session,
      toSpecLine $ findElementFromElement session element selector,
      toSpecLine $ findElementsFromElement session element selector,
      toSpecLine $ findElements session selector,
      toSpecLine $ getTitle session,
      toSpecLine $ getWindowHandle session,
      toSpecLine $ isElementSelected session element,
      toSpecLine $ closeWindow session,
      toSpecLine $ back session,
      toSpecLine $ forward session,
      toSpecLine $ refresh session,
      toSpecLine $ newSession minFirefoxCapabilities,
      toSpecLine $ deleteSession session,
      toSpecLine $ getActiveElement session,
      toSpecLine $ getWindowHandles session,
      toSpecLine $ newWindow session,
      toSpecLine $ switchToWindow session windowHandle,
      toSpecLine $ navigateTo session "url",
      toSpecLine $ findElement session selector,
      toSpecLine $ getWindowRect session,
      toSpecLine $ elementClick session element,
      toSpecLine $ getElementText session element,
      toSpecLine $ switchToParentFrame session,
      toSpecLine $ getElementProperty session element name,
      toSpecLine $ getElementAttribute session element name,
      toSpecLine $ getElementCssValue session element name,
      toSpecLine $ setWindowRect session (Rect 0 0 1280 720),
      toSpecLine $ findElementsFromShadowRoot session element selector,
      toSpecLine $ getElementShadowRoot session element,
      toSpecLine $ findElementFromShadowRoot session element selector,
      toSpecLine $ getElementTagName session element,
      toSpecLine $ getElementRect session element,
      toSpecLine $ isElementEnabled session element,
      toSpecLine $ getElementComputedRole session element,
      toSpecLine $ getElementComputedLabel session element,
      toSpecLine $ elementClear session element,
      toSpecLine $ elementSendKeys session element "Some keys",
      toSpecLine $ getPageSource session,
      toSpecLine $ takeScreenshot session,
      toSpecLine $ takeElementScreenshot session element,
      toSpecLine $ printPage session,
      toSpecLine $ executeScript session "console.log('test');" [],
      toSpecLine $ executeScriptAsync session "console.log('test');" [],
      toSpecLine $ getAllCookies session,
      toSpecLine $ getNamedCookie session name,
      toSpecLine $ addCookie session $ MkCookie "testCookie" "testValue" Nothing Nothing Nothing Nothing Nothing Nothing,
      toSpecLine $ deleteCookie session name,
      toSpecLine $ deleteAllCookies session,
      toSpecLine $ dismissAlert session,
      toSpecLine $ acceptAlert session,
      toSpecLine $ getAlertText session,
      toSpecLine $ sendAlertText session "Test alert",
      toSpecLine $ performActions session $ MkActions [],
      toSpecLine $ releaseActions session
    ]

-- >>> unit_test_all_endpoints_covered
unit_test_all_endpoints_covered :: Assertion
unit_test_all_endpoints_covered = do
  -- print allSpecsSample
  -- putStrLn ""
  assertBool ("Missing specs:\n " <> show missing) (S.null missing)
  assertBool ("Extra specs:\n " <> show extra) (S.null extra)
  where
    missing = specLinesFromSpec `difference` allSpecsSample
    extra = allSpecsSample `difference` specLinesFromSpec