diff --git a/app/ReplDemo.hs b/app/ReplDemo.hs index 26b4836..a77c139 100644 --- a/app/ReplDemo.hs +++ b/app/ReplDemo.hs @@ -16,6 +16,7 @@ The executable runs all the demos, although this is less useful. main :: IO () main = do withChromedriver normalChrome demoNewWindow + withChromedriver normalChrome demoGetElementShadowRoot withChromedriver normalChrome demoGetComputedRole withChromedriver normalChrome demoGetComputedLabel @@ -25,12 +26,21 @@ main = do +withGeckodriver :: WebDriverT IO () -> IO () +withGeckodriver acts = do + execWebDriverT firefoxConfig $ + runIsolated_ defaultFirefoxCapabilities acts + return () + withChromedriver :: Capabilities -> WebDriverT IO () -> IO () withChromedriver caps acts = do execWebDriverT chromeConfig $ runIsolated_ caps acts return () +firefoxConfig :: WebDriverConfig IO +firefoxConfig = defaultWebDriverConfig + chromeConfig :: WebDriverConfig IO chromeConfig = defaultWebDriverConfig { _environment = defaultWebDriverEnvironment @@ -72,6 +82,21 @@ demoNewWindow = do +-- It looks like neither chromedriver nor geckodriver support this yet. +demoGetElementShadowRoot :: WebDriverT IO () +demoGetElementShadowRoot = do + -- open google.com + navigateTo "https://www.google.com" + + -- get the shadow root of whatever element is active on page load + root <- getActiveElement >>= getElementShadowRoot + + comment $ "Shadow root ID is '" <> show root <> "'" + wait 5000000 + return () + + + demoGetComputedRole :: WebDriverT IO () demoGetComputedRole = do -- open google.com diff --git a/src/Web/Api/WebDriver/Endpoints.hs b/src/Web/Api/WebDriver/Endpoints.hs index d65ef93..28d7e32 100644 --- a/src/Web/Api/WebDriver/Endpoints.hs +++ b/src/Web/Api/WebDriver/Endpoints.hs @@ -85,6 +85,8 @@ module Web.Api.WebDriver.Endpoints ( , findElementsFromElement -- ** Get Active Element , getActiveElement + -- ** Get Element Shadow Root + , getElementShadowRoot -- * Element State -- ** Is Element Selected @@ -164,10 +166,11 @@ module Web.Api.WebDriver.Endpoints ( -- ** Print Page , printPage - -- Spec Constants + -- * Constants , _WEB_ELEMENT_ID , _WEB_WINDOW_ID , _WEB_FRAME_ID + , _SHADOW_ROOT_ID ) where import Control.Monad.Trans.Class @@ -200,6 +203,10 @@ _WEB_WINDOW_ID = "window-fcc6-11e5-b4f8-330a88ab9d7f" _WEB_FRAME_ID :: Text _WEB_FRAME_ID = "frame-075b-4da1-b6ba-e579c2d3230a" +-- | Spec-defined "shadow root identifier" string constant. See . +_SHADOW_ROOT_ID :: Text +_SHADOW_ROOT_ID = "shadow-6066-11e4-a52e-4f735466cecf" + @@ -759,6 +766,23 @@ getActiveElement = do >>= (return . ElementRef . unpack) +-- | See . +getElementShadowRoot + :: (Monad eff, Monad (t eff), MonadTrans t, HasElementRef a) + => a + -> WebDriverTT t eff ShadowRootRef +getElementShadowRoot element = do + baseUrl <- theRemoteUrlWithSession + let elementId = elementRefOf element + httpGet (baseUrl <> "/element/" <> show elementId <> "/shadow") + >>= (return . _responseBody) + >>= parseJson + >>= lookupKeyJson "value" + >>= lookupKeyJson _WEB_ELEMENT_ID + >>= constructFromJson + >>= (return . ShadowRootRef . unpack) + + -- | See . isElementSelected :: (Monad eff, Monad (t eff), MonadTrans t, HasElementRef a) diff --git a/src/Web/Api/WebDriver/Types.hs b/src/Web/Api/WebDriver/Types.hs index b3aa997..b162066 100644 --- a/src/Web/Api/WebDriver/Types.hs +++ b/src/Web/Api/WebDriver/Types.hs @@ -17,6 +17,7 @@ module Web.Api.WebDriver.Types ( -- * Stringy Types SessionId , ElementRef(..) + , ShadowRootRef(..) , ContextId(..) , ContextType(..) , Selector @@ -156,6 +157,17 @@ instance Show ElementRef where instance IsString ElementRef where fromString = ElementRef +-- | See +newtype ShadowRootRef = ShadowRootRef + { theShadowRootRef :: String + } deriving Eq + +instance Show ShadowRootRef where + show (ShadowRootRef str) = str + +instance IsString ShadowRootRef where + fromString = ShadowRootRef + -- | Identifier for a /browsing context/; see . newtype ContextId = ContextId { theContextId :: String