on develop help sign in
Merge branch 'ts-hydration' of github.com:reflex-frp/reflex-dom into ts-hydration
commit69fc82c4104844dec371cdd428e61725e8a9d6b0 authorTom Smalley <tfsmalley@gmail.com> dateThu 13 Dec 2018, 14:18 (8 years ago) parentd6c69bd7be7466
3 files changed+62−28
reflex-dom-core/default.nix+18−15 reflex-dom-core/reflex-dom-core.cabal+2−1 reflex-dom-core/test/hydration.hs+42−12
reflex-dom-core/default.nix+18−15
@@ -1,13 +1,14 @@
1−{ mkDerivation, ghc, aeson, base, bifunctors, bimap, blaze-builder
2−, bytestring, constraints, containers, contravariant, data-default
3−, dependent-map, dependent-sum, dependent-sum-template, directory
4−, exception-transformers, exceptions, ghcjs-dom, hlint, hspec
5−, http-types, HUnit, jsaddle, jsaddle-warp, keycode, lens
6−, linux-namespaces, monad-control, mtl, network-uri, primitive
7−, process, random, ref-tf, reflex, semigroups, silently, stdenv
8−, stm, template-haskell, temporary, text, these, transformers, unix
9−, wai, wai-websockets, warp, webdriver, websockets, zenc
10−, iproute, chromium, hashable, selenium-server-standalone
1+{ mkDerivation, aeson, base, bifunctors, bimap, blaze-builder
2+, bytestring, constraints, constraints-extras, containers
3+, contravariant, data-default, dependent-map, dependent-sum
4+, dependent-sum-template, directory, exception-transformers
5+, exceptions, filepath, ghcjs-dom, hlint, hspec, http-types, HUnit
6+, jsaddle, jsaddle-warp, keycode, lens, linux-namespaces
7+, monad-control, mtl, network, network-uri, primitive, process
8+, random, ref-tf, reflex, semigroups, silently, stdenv, stm
9+, template-haskell, temporary, text, these, transformers, unix, wai
10+, wai-websockets, warp, webdriver, websockets, zenc
11+, ghc, iproute, chromium, hashable, selenium-server-standalone, which
1112}:
1213let addGcTestDepends = drv: if stdenv.system != "x86_64-linux" then drv else drv // {
1314 testHaskellDepends = (drv.testHaskellDepends or []) ++ [ temporary jsaddle-warp process linux-namespaces ];
@@ -39,12 +40,14 @@ in mkDerivation (addGcTestDepends {
3940 # Show some output while running tests, so we might notice what's wrong
4041 testTarget = "--show-details=streaming";
4142
42− testSystemDepends = [ selenium-server-standalone ];
43+ testSystemDepends = [ selenium-server-standalone which ];
4344 testHaskellDepends = [
44− aeson base bytestring containers exceptions ghcjs-dom hlint hspec
45− http-types HUnit jsaddle jsaddle-warp linux-namespaces process
46− random reflex silently temporary text unix wai wai-websockets warp
47− webdriver websockets
45+ aeson base bytestring constraints constraints-extras containers
46+ dependent-map dependent-sum dependent-sum-template directory
47+ exceptions filepath ghcjs-dom hlint hspec http-types HUnit jsaddle
48+ jsaddle-warp lens linux-namespaces network process random reflex
49+ silently temporary text unix wai wai-websockets warp webdriver
50+ websockets
4851 ];
4952 description = "Functional Reactive Web Apps with Reflex";
5053 license = stdenv.lib.licenses.bsd3;
reflex-dom-core/reflex-dom-core.cabal+2−1
@@ -171,8 +171,9 @@ test-suite hydration
171171 , jsaddle
172172 , jsaddle-warp
173173 , lens
174+ , network
174175 , random
175− , reflex == 0.5.*
176+ , reflex
176177 , reflex-dom-core
177178 , process
178179 , silently
reflex-dom-core/test/hydration.hs+42−12
@@ -34,6 +34,7 @@ import Data.Text (Text)
3434import Language.Javascript.JSaddle (syncPoint, liftJSM)
3535import Language.Javascript.JSaddle.Warp
3636import Network.HTTP.Types (status200)
37+import Network.Socket
3738import Network.Wai
3839import Network.WebSockets
3940import Reflex.Dom.Builder.Immediate (GhcjsDomSpace)
@@ -45,7 +46,7 @@ import System.IO.Temp
4546import System.Process
4647import System.Timeout
4748import Test.HUnit (assertEqual, assertFailure)
48−import Test.Hspec (hspec, it, describe, beforeAll, shouldBe)
49+import Test.Hspec (Spec, parallel, hspec, it, describe, shouldBe)
4950import Test.WebDriver (WD)
5051
5152import qualified Data.ByteString.Lazy as LBS
@@ -60,8 +61,8 @@ import qualified Test.WebDriver as WD
6061testTimeLimit :: Int
6162testTimeLimit = 5 * 1000 * 1000
6263
63−chromeConfig :: WD.WDConfig
64−chromeConfig = WD.useBrowser (WD.chrome { WD.chromeBinary = Just "/run/current-system/sw/bin/chromium", WD.chromeOptions = ["--headless"]}) WD.defaultConfig
64+chromeConfig :: Text -> WD.WDConfig
65+chromeConfig fp = WD.useBrowser (WD.chrome { WD.chromeBinary = Just $ T.unpack fp, WD.chromeOptions = ["--headless"] }) WD.defaultConfig
6566
6667keyMap :: DMap DKey Identity
6768keyMap = DMap.fromList
@@ -105,8 +106,11 @@ instance EqTag DKey Identity where
105106 eqTagged Key_Bool Key_Bool = (==)
106107
107108main :: IO ()
108−main = hspec $ beforeAll startSeleniumServer $ do
109+main = withSeleniumServer $ \selenium ->
110+ hspec (parallel (tests selenium)) `finally` _selenium_stopServer selenium
109111
112+tests :: Selenium -> Spec
113+tests _selenium = do
110114 describe "text" $ do
111115 it "works" $ do
112116 testWidgetStatic (checkBodyText "hello world") $ do
@@ -1003,15 +1007,29 @@ main = hspec $ beforeAll startSeleniumServer $ do
10031007 (dmap, _evt) <- traverseDMapWithKeyWithAdjust widget keyMap $ leftmost [postBuildPatch <$ pb, replace]
10041008 liftIO $ dmap `shouldBe` keyMap
10051009
1006−startSeleniumServer :: IO ()
1007−startSeleniumServer = do
1008− (_,_,_,ph) <- createProcess $ (proc "selenium-server" [])
1010+data Selenium = Selenium
1011+ { _selenium_portNumber :: PortNumber
1012+ , _selenium_stopServer :: IO ()
1013+ }
1014+
1015+startSeleniumServer :: PortNumber -> IO (IO ())
1016+startSeleniumServer port = do
1017+ (_,_,_,ph) <- createProcess $ (proc "selenium-server" ["-port", show port])
10091018 { std_in = NoStream
10101019 , std_out = NoStream
10111020 , std_err = NoStream
10121021 }
1013− _ <- forkIO $ print =<< waitForProcess ph
1022+ return $ terminateProcess ph
1023+
1024+withSeleniumServer :: (Selenium -> IO ()) -> IO ()
1025+withSeleniumServer f = do
1026+ let port = 4444 -- TODO port <- getFreePort
1027+ stopServer <- startSeleniumServer port
10141028 threadDelay $ 1000 * 1000 * 2 -- TODO poll or wait on a a signal to block on
1029+ f $ Selenium
1030+ { _selenium_portNumber = port
1031+ , _selenium_stopServer = stopServer
1032+ }
10151033
10161034triggerEventWithChan :: (Reflex t, TriggerEvent t m, Prerender t m) => Chan a -> m (Event t a)
10171035triggerEventWithChan chan = do
@@ -1088,13 +1106,14 @@ testWidget' beforeJS afterSwitchover bodyWidget = maybe (error "test timed out")
10881106 mainHydrationWidgetWithSwitchoverAction (putMVar waitUntilSwitchover ()) (pure ()) $ bodyWidget
10891107 syncPoint
10901108 application <- jsaddleOr defaultConnectionOptions entryPoint $ \_ sendResponse -> sendResponse $ responseLBS status200 [] $ "<!doctype html>\n" <> LBS.fromStrict html
1091− --port <- randomRIO (3000, 50000)
1092− let port = 3911 -- TODO
1093− let settings = Warp.setPort port Warp.defaultSettings
1109+ port <- getFreePort
1110+ let settings = Warp.setPort (fromIntegral $ toInteger port) Warp.defaultSettings
10941111 -- hSilence to get rid of ConnectionClosed logs
10951112 jsaddleWarp = forkIO $ hSilence [stderr] $ Warp.runSettings settings application
10961113 bracket jsaddleWarp killThread $ \_ -> do
1097− WD.runSession chromeConfig . WD.finallyClose $ do
1114+ browserPath <- T.strip . T.pack <$> readProcess "which" [ "chromium" ] ""
1115+ when (T.null browserPath) $ fail "No browser was found"
1116+ WD.runSession (chromeConfig browserPath) . WD.finallyClose $ do
10981117 WD.openPage $ "http://localhost:" <> show port
10991118 a <- beforeJS
11001119 liftIO $ putMVar waitBeforeJS ()
@@ -1102,6 +1121,17 @@ testWidget' beforeJS afterSwitchover bodyWidget = maybe (error "test timed out")
11021121 liftIO $ threadDelay 100000 -- wait a bit
11031122 afterSwitchover a
11041123
1124+-- TODO: Should this be part of more widely used module?
1125+getFreePort :: MonadIO m => m PortNumber
1126+getFreePort = liftIO $ withSocketsDo $ do
1127+ addr:_ <- getAddrInfo (Just defaultHints) (Just "127.0.0.1") (Just "0")
1128+ bracket (open addr) close socketPort
1129+ where
1130+ open addr = do
1131+ sock <- socket (addrFamily addr) (addrSocketType addr) (addrProtocol addr)
1132+ bind sock (addrAddress addr)
1133+ return sock
1134+
11051135testWidgetDebug :: (forall m js. TestWidget js (SpiderTimeline Global) m => m ()) -> IO ()
11061136testWidgetDebug bodyWidget = do
11071137 let staticApp = do