如何结合WebDriver和Scotty monad

时间:2017-02-02 20:16:00

标签: selenium haskell selenium-webdriver scotty

我是初学者,所以请耐心等待。

我有以下代码:

{-# LANGUAGE OverloadedStrings #-}

module Lib where

import           Control.Monad.IO.Class
import           Control.Monad.Trans.Class
import           Data.Monoid               ((<>))
import qualified Data.Text                 as T
import qualified Data.Text.Lazy            as TL
import           Test.WebDriver
--import           Web.Scotty
import           Web.Scotty.Trans

firefoxConfig :: WDConfig
firefoxConfig = defaultConfig

startMyBrowser :: WD a -> IO a
startMyBrowser = runSession firefoxConfig

stopMyBrowser = closeSession

someFunc :: WD String
someFunc = do
  openPage "http://maslo.cz"
  captionElem <- findElem (ByCSS "h2")
  text <- getText captionElem
  return $ T.unpack text

helloAction :: ActionT TL.Text WD ()
helloAction = do
  a <- lift someFunc
  text $ "got this for you: " <> TL.pack a

routes :: ScottyT TL.Text WD ()
routes = get "/hello" helloAction

startServer = startMyBrowser $ do
  lift $ scottyT 3000 _ routes
  stopMyBrowser

我不确定即使那些填充的部分是否正确 - 它应该启动Selenium会话(startMyBrowser),启动Web服务器(scottyT部分)并在Web服务器停止之后它应该结束Selenium会话(stopMyBrowser)。

在摆弄类型后,我得到了上面的代码,似乎我只错过了一个 - 洞。

如果您使其正常工作,请尝试解释您的解决方案和/或添加一些指向更多材料的链接。我很想了解那些该死的变形金刚。

编辑1: 以下是错误:

  • Couldn't match type ‘t0 m0’ with ‘WD’
    Expected type: WD ()
      Actual type: t0 m0 ()
  • In a stmt of a 'do' block: lift $ scottyT 3000 _ routes
    In the second argument of ‘($)’, namely
      ‘do { lift $ scottyT 3000 _ routes;
            stopMyBrowser }’
    In the expression:
      startMyBrowser
      $ do { lift $ scottyT 3000 _ routes;
             stopMyBrowser }


  • Found hole:
      _ :: WD wai-3.2.1.1:Network.Wai.Internal.Response
           -> IO wai-3.2.1.1:Network.Wai.Internal.Response
  • In the second argument of ‘scottyT’, namely ‘_’
    In the second argument of ‘($)’, namely ‘scottyT 3000 _ routes’
    In a stmt of a 'do' block: lift $ scottyT 3000 _ routes
  • Relevant bindings include
      startServer :: IO () (bound at src/Lib.hs:37:1)

1 个答案:

答案 0 :(得分:0)

善良的人ForTheFunctionGod在reddit answered it上,现在是:

你的问题是:

lift $ scottyT 3000 _ routes

由于scottyT的返回类型是

MonadIO n => n

你不需要解除它 - 它可以适合任何可以执行IO动作的monad。 WD就是这样一个monad - 注意它的MonadIO个实例。如果返回类型为简单scottyT,则只需提升IO

类似MonadIOMonadState等类,主要是避免手动提升计算的需要。如果你想将IO Int中的函数嵌入StateT s IO Int,你需要解除一个函数,而你不需要解除MonadIO m => m a类型的函数,因为StateT s IO已经是MonadIO的实例,所以m可以实例化它。

至于洞:它必须是

WD Response -> IO Response

使这项工作的唯一方法是使用runSession或其中一位朋友。我不太了解Selenium,但是,据推测,你可以重新使用你已经开设的会话ID:

runWD :: WDSession -> WD a -> IO a

startServer = startMyBrowser $ do
   sessionID <- getSession
   scottyT 3000 (runWD sessionID) routes
   stopMyBrowser

我还没有尝试过这个,但类型应该检查出来。我希望它有所帮助!

确实如此:)。