2

I have a site with a <select> that has more than 100 <option>s in it, one for every country in the world. My test needs to select one. My current solution - below - takes around 2.5 seconds. I'd like it to be much faster.

findChildrenByLabel :: (WD.WebDriver m, MonadIO m) =>
  Text -> Text -> m [WD.Element]
findChildrenByLabel label tagName = do
  parentEl <- findFieldByLabel label
  WD.findElemsFrom parentEl $ WD.ByTag tagName

findChildByLabelF :: (WD.WebDriver m, MonadIO m) =>
  Text -> Text -> (WD.Element -> m Bool) -> m WD.Element
findChildByLabelF label tagName f = do
  children <- findChildrenByLabel label tagName
  child <- filterM f children
  liftIO $ child `shouldSatisfy` ((==1) . length)
  return (headEx child)

selectDropdownByLabel :: (WD.WebDriver m, MonadIO m) => Text -> Text -> m ()
selectDropdownByLabel label optionName = do
  targetOption <- findChildByLabelF
    label "option" (\el -> (== optionName) <$> WD.getText el)
  WD.click targetOption

I found this SO answer in Java, but there doesn't seem to be anything like Selenium.Support or SelectByText for Haskell.

Community
  • 1
  • 1
Echo Nolan
  • 1,111
  • 1
  • 11
  • 23
  • 2
    Insted of extracting all the options in `WD.findElemsFrom`, perhaps targeting a specific option using a dynamically generated XPath expression like `"//option[contains(text(), 'SomeOption')]"` would be faster. It seems that it would save you multiple calls to `WD.getText`. – danidiaz Sep 14 '16 at 19:39

1 Answers1

0

Based on danidiaz's answer, I wrote this:

findFieldByLabel :: (WD.WebDriver m, MonadIO m) => Text -> m WD.Element
findFieldByLabel str = do
  labels :: [WD.Element] <- WD.findElems $ WD.ByXPath $
    "//label[text() = \"" <> str <> "\"]"
  els <- catMaybes <$> mapM (`WD.attr` "for") labels
  liftIO $ els `shouldSatisfy` ((==1) . length)
  WD.findElem $ WD.ById $ headEx els

selectDropdownByLabel :: (WD.WebDriver m, MonadIO m) => Text -> Text -> m ()
selectDropdownByLabel label optionName = do
  field <- findFieldByLabel label
  targetOptions <- WD.findElemsFrom field $ WD.ByXPath $
    "option[text() = \"" <> optionName <> "\"]"
  liftIO $ targetOptions `shouldSatisfy` ((==1) . length)
  WD.click $ headEx targetOptions

I use it like this:

selectDropdownByLabel "Country of residence" "United States"

The original solution took around 2.5 seconds, this is around 0.16. Big improvement, thanks danidiaz!

Echo Nolan
  • 1,111
  • 1
  • 11
  • 23