I am trying to build an automated feature testing suite using webdriver
and polysemy
in Haskell. I've gotten as far as defining proper effects and interpreting them into a webdriver WD monad, but now I'm stuck.
I have a value of type Member BrowserMaster r => Sem r ()
where BrowserMaster
is my custom capability.
And this is the interpreter:
runBrowserMaster :: Members [Embed WD.WD, Embed IO] r => Sem (BrowserMaster ': r) a -> Sem r a
runBrowserMaster = interpret $ \case
ClickElement bmSelector ->
let action = (WD.findElem (bmSelectoToSelector bmSelector) >>= WD.click :: WD.WD ())
in embed action
{- ... -}
Now I'm wondering how to convert the Embed WD.WD
effect into Embed IO
, so that I end up with just one.
I tried to craft an interpreter:
runWebDriver :: Member (Embed IO) r => Sem (Embed WD.WD ': r) a -> Sem r a
runWebDriver = interpret $
\a -> embed $ runSession chromeConfig . finallyClose $ do
setImplicitWait 60000
setWindowSize (1024, 768)
unEmbed a
(Here runSession chromeConfig . finallyClose
is a WD a -> IO a
)
It does work, but it seems to fire up a new browser session for each of the commands instead of starting it just once, doing everything within and closing.
I have an intuition that it has to do something with resource acquisition and release, but I just cannot get my head around this to be able to put it all together.
Keep in mind that each interpreter will be executed each time an action of the
BrowserMaster
effect is executed. So every time it runs therunWebDriver
interpreter, which explains why it creates, runs and close the session.I think what you want to do is instead to create/delete the session once, and execute your whole code in this session. Also, since
WD
is already a wrapper aroundIO
, I think it's unnecessary to embed both effects.I am not familiar with your code nor the
webdriver
library, but I assume this would be something along the lines of:Note: If you need to run some
IO
code in the interpreter, useliftIO
to make it anWD
action instead, e.g.liftIO $ putStrLn "Hello world"
.PS: I recommend renaming the
runBrowserMaster
interpreter to something likebrowserMasterToWD
as it better represents what it does: interpret theBrowserMaster
effect in terms of anWD
action.