使用Haskell webdriver包查找网页上的所有文本输入

时间:2014-07-09 10:08:46

标签: haskell selenium selenium-webdriver webdriver

这是我尝试在网页上查找“text”类型的所有输入。我已经发现我可以使用xpath,但我想知道如何使我尝试工作的方式。我最感兴趣的是如何将[Element]生成[WD Element]并使该程序有效。

然而,如果我的方法是错误的或单一的,请随意完全重写它。这是代码:

{-# LANGUAGE OverloadedStrings #-}

import           Control.Monad
import           Control.Monad.IO.Class
import           Test.WebDriver
import           Test.WebDriver.Classes       (WebDriver (..))
import           Test.WebDriver.Commands
import           Test.WebDriver.Commands.Wait

main = do
  runSession defaultSession capabilities $ do
      openPage "http://www.appnitro.com/demo/view.php?id=1"
      inputs <- findElems $ ByTag "input"
      textElems <- filterM (liftM $ ((==) "text" . (`attr` "type"))) inputs
      -- wait 20 seconds
      waitUntil 20 (getText <=< findElem $ ByCSS ".doesnotexist")
        `onTimeout` return ""
  liftIO $ putStrLn "done"
    where
      capabilities = allCaps { browser=firefox }

-- [1 of 1] Compiling Main             ( src/Main.hs, interpreted )

-- src/Main.hs:168:70:
--     Couldn't match type `Element' with `WD Element'
--     Expected type: [WD Element]
--       Actual type: [Element]
--     In the second argument of `filterM', namely `inputs'
--     In a stmt of a 'do' block:
--       textElems <- filterM
--                      (liftM $ ((==) "text" . (`attr` "type"))) inputs
--     In the second argument of `($)', namely
--       `do { openPage "http://www.appnitro.com/demo/view.php?id=1";
--             inputs <- findElems $ ByTag "input";
--             textElems <- filterM
--                            (liftM $ ((==) "text" . (`attr` "type"))) inputs;
--             waitUntil 20 (getText <=< findElem $ ByCSS ".doesnotexist")
--             `onTimeout` return "" }'
-- Failed, modules loaded: none.

3 个答案:

答案 0 :(得分:3)

这可能不是您正在寻找的答案,但我发现最好直接在定位器中对元素表达这些类型的约束,以免混淆haskell源。正如你所提到的,使用XPath是一种可能性:

textElems <- findElems $ ByXPath "//input[@type='text']"

但我经常更喜欢CSS选择器,它往往更简洁(有点不那么强大 - 例如你不能从给定元素遍历到它的父元素等)并且在这些简单的情况下也能正常工作

textElems <- findElems $ ByCSS "input[type='text']"

答案 1 :(得分:2)

用此文件替换您的文字元素过滤:

      textElems <- filterM textElem inputs

然后将其添加到:

      textElem e = (== Just "text") `fmap` (e `attr` "type")

但是你仍然会使用不能编译的waitUntil。这似乎是无关紧要的,因为它与过滤无关。

答案 2 :(得分:2)

您的代码中有两个错误:

attr会返回Maybe值,因此您必须与Just "text"进行比较。

鉴于attr已经在WD monad中返回了一个值,你只需要解除第一个函数(如果有的话,你提升了所有内容,包括{{1}功能):

attr

或者,由于textElems <- filterM (liftM ((==) (Just "text")) . (`attr` "type")) inputs 也是一个Functor(我实际上发现这更容易理解,你在WD返回的monad中应用了一个纯函数):

attr