@@ -1,13 +1,9 @@
1−{-# OPTIONS_GHC -fno-warn-orphans #-}
2{-# LANGUAGE BangPatterns #-}
1{-# LANGUAGE BangPatterns #-}
3−{-# LANGUAGE StandaloneDeriving #-}
4−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
5−{-# LANGUAGE UndecidableInstances #-}
6{-# LANGUAGE ConstraintKinds #-}
2{-# LANGUAGE ConstraintKinds #-}
8{-# LANGUAGE FlexibleContexts #-}
3{-# LANGUAGE FlexibleContexts #-}
9{-# LANGUAGE FlexibleInstances #-}
4{-# LANGUAGE FlexibleInstances #-}
10{-# LANGUAGE GADTs #-}
5{-# LANGUAGE GADTs #-}
6+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
11{-# LANGUAGE LambdaCase #-}
7{-# LANGUAGE LambdaCase #-}
12{-# LANGUAGE MultiParamTypeClasses #-}
8{-# LANGUAGE MultiParamTypeClasses #-}
13{-# LANGUAGE OverloadedStrings #-}
9{-# LANGUAGE OverloadedStrings #-}
@@ -15,13 +11,18 @@
15{-# LANGUAGE RankNTypes #-}
11{-# LANGUAGE RankNTypes #-}
16{-# LANGUAGE RecursiveDo #-}
12{-# LANGUAGE RecursiveDo #-}
17{-# LANGUAGE ScopedTypeVariables #-}
13{-# LANGUAGE ScopedTypeVariables #-}
14+{-# LANGUAGE StandaloneDeriving #-}
18{-# LANGUAGE TemplateHaskell #-}
15{-# LANGUAGE TemplateHaskell #-}
19{-# LANGUAGE TupleSections #-}
16{-# LANGUAGE TupleSections #-}
20{-# LANGUAGE TypeApplications #-}
17{-# LANGUAGE TypeApplications #-}
21{-# LANGUAGE TypeFamilies #-}
18{-# LANGUAGE TypeFamilies #-}
19+{-# LANGUAGE UndecidableInstances #-}
21+{-# OPTIONS_GHC -fno-warn-orphans #-}
23import Prelude hiding (fail)
23import Prelude hiding (fail)
24import Control.Concurrent
24import Control.Concurrent
25+import qualified Control.Concurrent.Async as Async
25import Control.Lens.Operators
26import Control.Lens.Operators
26import Control.Monad hiding (fail)
27import Control.Monad hiding (fail)
27import Control.Monad.Catch
28import Control.Monad.Catch
@@ -32,7 +33,7 @@ import Control.Monad.Ref
32import Data.Constraint.Extras
33import Data.Constraint.Extras
33import Data.Constraint.Extras.TH
34import Data.Constraint.Extras.TH
34import Data.Dependent.Map (DMap)
35import Data.Dependent.Map (DMap)
35−import Data.Dependent.Sum (DSum(..), (==>), EqTag(..), ShowTag(..))
36+import Data.Dependent.Sum (DSum(..), (==>))
36import Data.Functor.Identity
37import Data.Functor.Identity
37import Data.Functor.Misc
38import Data.Functor.Misc
38import Data.GADT.Compare.TH
39import Data.GADT.Compare.TH
@@ -63,7 +64,6 @@ import Test.Hspec (xit)
63import Test.Hspec.WebDriver hiding (runWD, click, uploadFile, WD)
64import Test.Hspec.WebDriver hiding (runWD, click, uploadFile, WD)
64import qualified Test.Hspec.WebDriver as WD
65import qualified Test.Hspec.WebDriver as WD
65import Test.WebDriver (WD(..))
66import Test.WebDriver (WD(..))
66−import Test.WebDriver.Exceptions (ServerError(..))
68import qualified Data.ByteString.Lazy as LBS
68import qualified Data.ByteString.Lazy as LBS
69import qualified Data.Dependent.Map as DMap
69import qualified Data.Dependent.Map as DMap
@@ -79,6 +79,9 @@ import qualified Test.WebDriver.Capabilities as WD
79import Test.Util.ChromeFlags
79import Test.Util.ChromeFlags
80import Test.Util.UnshareNetwork
80import Test.Util.UnshareNetwork
82+-- ORPHAN: https://github.com/kallisti-dev/hs-webdriver/pull/167
83+deriving instance MonadMask WD
82chromium :: FilePath
85chromium :: FilePath
83chromium = $(staticWhich "chromium")
86chromium = $(staticWhich "chromium")
@@ -924,6 +927,58 @@ tests withDebugging wdConfig caps _selenium = do
924 , el "span" . text <$> replace
927 , el "span" . text <$> replace
930+ let checkInnerHtml t x = findElemWithRetry (WD.ByTag t) >>= (`attr` "innerHTML") >>= (`shouldBe` Just x)
931+ it "removes bracketing comments" $ runWD $ do
932+ replaceChan :: Chan () <- liftIO newChan
934+ preSwitchover = checkInnerHtml "div" "before|<!--replace-start-0-->inner1<!--replace-end-0-->|after"
936+ liftIO $ writeChan replaceChan () -- trigger creation of p tag
937+ _ <- findElemWithRetry $ WD.ByTag "p" -- wait till p tag is created
938+ checkInnerHtml "div" "before|<p>inner2</p>|after"
939+ testWidget' preSwitchover check $ do
940+ replace <- triggerEventWithChan replaceChan
943+ _ <- runWithReplace (text "inner1") $ el "p" (text "inner2") <$ replace
945+ it "ignores extra ending bracketing comment" $ runWD $ do
946+ replaceChan :: Chan () <- liftIO newChan
948+ preSwitchover = checkInnerHtml "div" "before|<!--replace-start-0-->inner1<!--replace-end-0--><!--replace-end-0-->|after"
950+ liftIO $ writeChan replaceChan () -- trigger creation of p tag
951+ _ <- findElemWithRetry $ WD.ByTag "p" -- wait till p tag is created
952+ checkInnerHtml "div" "before|inner2|after"
953+ testWidget' preSwitchover check $ do
954+ replace <- triggerEventWithChan replaceChan
957+ _ <- runWithReplace (text "inner1" *> comment "replace-end-0") $ text "inner2" <$ replace
959+ void $ runWithReplace blank $ el "p" blank <$ replace -- Signal tag for end of test
960+ it "ignores missing ending bracketing comments" $ runWD $ do
961+ replaceChan :: Chan () <- liftIO newChan
964+ checkInnerHtml "div" "before|<!--replace-start-0-->inner1<!--replace-end-0-->|after"
965+ divEl <- findElemWithRetry (WD.ByTag "div")
966+ let wrongHtml = "<!--replace-start-0-->inner1"
967+ actualHtml :: String <- WD.executeJS
968+ [WD.JSArg divEl, WD.JSArg wrongHtml]
969+ "arguments[0].innerHTML = arguments[1]; return arguments[0].innerHTML"
970+ actualHtml `shouldBe` wrongHtml
972+ liftIO $ writeChan replaceChan () -- trigger creation of p tag
973+ _ <- findElemWithRetry $ WD.ByTag "p" -- wait till p tag is created
974+ checkInnerHtml "div" "before|<p>inner2</p>|after"
975+ testWidget' preSwitchover check $ do
976+ replace <- triggerEventWithChan replaceChan
979+ _ <- runWithReplace (text "inner1") $ el "p" (text "inner2") <$ replace
927 describe "traverseDMapWithKeyWithAdjust" $ session' $ do
982 describe "traverseDMapWithKeyWithAdjust" $ session' $ do
928 let widget :: DomBuilder t m => DKey a -> Identity a -> m (Identity a)
983 let widget :: DomBuilder t m => DKey a -> Identity a -> m (Identity a)
929 widget k (Identity v) = elAttr "li" ("id" =: textKey k) $ do
984 widget k (Identity v) = elAttr "li" ("id" =: textKey k) $ do
@@ -1315,8 +1370,8 @@ withRetry a = wait 300
1315 where wait :: Int -> WD a
1370 where wait :: Int -> WD a
1316 wait 0 = a
1371 wait 0 = a
1317 wait n = try a >>= \case
1372 wait n = try a >>= \case
1318− Left (_ :: SomeException) -> do
1373+ Left (e :: SomeException) -> do
1319− liftIO $ threadDelay 100000
1374+ liftIO $ putStrLn ("(retrying due to " <> show e <> ")") *> threadDelay 100000
1320 wait $ n - 1
1375 wait $ n - 1
1321 Right v -> return v
1376 Right v -> return v
@@ -1398,23 +1453,26 @@ testWidgetDebug' withDebugging beforeJS afterSwitchover bodyWidget = do
1399 -- hSilence to get rid of ConnectionClosed logs
1454 -- hSilence to get rid of ConnectionClosed logs
1400 silenceIfDebug = if withDebugging then id else hSilence [stderr]
1455 silenceIfDebug = if withDebugging then id else hSilence [stderr]
1401− jsaddleWarp = forkIO $ silenceIfDebug $ Warp.runSettings settings application
1456+ jsaddleWarp = silenceIfDebug $ Warp.runSettings settings application
1402− jsaddleTid <- liftIO jsaddleWarp
1457+ withAsync' jsaddleWarp $ do
1403− putStrLnDebug "taking waitJSaddle"
1458+ putStrLnDebug "taking waitJSaddle"
1404− liftIO $ takeMVar waitJSaddle
1459+ liftIO $ takeMVar waitJSaddle
1405− putStrLnDebug "opening page"
1460+ putStrLnDebug "opening page"
1406− WD.openPage $ "http://localhost:" <> show jsaddlePort
1461+ WD.openPage $ "http://localhost:" <> show jsaddlePort
1407− putStrLnDebug "running beforeJS"
1462+ putStrLnDebug "running beforeJS"
1408− a <- beforeJS
1463+ a <- beforeJS
1409− putStrLnDebug "putting waitBeforeJS"
1464+ putStrLnDebug "putting waitBeforeJS"
1410− liftIO $ putMVar waitBeforeJS ()
1465+ liftIO $ putMVar waitBeforeJS ()
1411− putStrLnDebug "taking waitUntilSwitchover"
1466+ putStrLnDebug "taking waitUntilSwitchover"
1412− liftIO $ takeMVar waitUntilSwitchover
1467+ liftIO $ takeMVar waitUntilSwitchover
1413− putStrLnDebug "running afterSwitchover"
1468+ putStrLnDebug "running afterSwitchover"
1414− b <- afterSwitchover a
1469+ afterSwitchover a
1415− putStrLnDebug "killing jsaddle thread"
1470+
1416− liftIO $ killThread jsaddleTid
1471+withAsync' :: (MonadIO m, MonadMask m) => IO a -> m b -> m b
1417− return b
1472+withAsync' f g = bracket
1473+ (liftIO $ Async.async f)
1474+ (liftIO . Async.uninterruptibleCancel)
1419data Key2 a where
1477data Key2 a where
1420 Key2_Int :: Int -> Key2 Int
1478 Key2_Int :: Int -> Key2 Int