@@ -220,113 +220,217 @@ main = hspec $ parallel $ do
222 describe "inputElement" $ parallel $ do
222 describe "inputElement" $ parallel $ do
223+ describe "hydration" $ do
223− it "doesn't wipe user input when switching over" $ do
224+ it "doesn't wipe user input when switching over" $ do
224− inputRef <- newIORef ""
225+ inputRef <- newIORef ""
225− testWidget'
226+ testWidget'
227− e <- WD.findElem $ WD.ByTag "input"
228+ e <- WD.findElem $ WD.ByTag "input"
228− WD.sendKeys "hello world" e
229+ WD.sendKeys "hello world" e
230− (\e -> do
231+ (\e -> do
231− t <- WD.attr e "value"
232+ t <- WD.attr e "value"
232− liftIO $ t `shouldBe` Just "hello world"
233+ liftIO $ t `shouldBe` Just "hello world"
233− WD.click <=< WD.findElem $ WD.ByTag "button"
234− input <- liftIO $ readIORef inputRef
235− liftIO $ input `shouldBe` "hello world"
237− e <- inputElement def
238− click <- button "save"
239− performEvent_ $ liftIO . writeIORef inputRef <$> tag (current (value e)) click
240− it "captures user input after switchover" $ do
241− inputRef <- newIORef ""
243− WD.sendKeys "hello world" <=< WD.findElem $ WD.ByTag "input"
244 WD.click <=< WD.findElem $ WD.ByTag "button"
234 WD.click <=< WD.findElem $ WD.ByTag "button"
245 input <- liftIO $ readIORef inputRef
235 input <- liftIO $ readIORef inputRef
246 liftIO $ input `shouldBe` "hello world"
236 liftIO $ input `shouldBe` "hello world"
238+ e <- inputElement def
239+ click <- button "save"
240+ performEvent_ $ liftIO . writeIORef inputRef <$> tag (current (value e)) click
241+ it "captures user input after switchover" $ do
242+ inputRef <- newIORef ""
244+ WD.sendKeys "hello world" <=< WD.findElem $ WD.ByTag "input"
245+ WD.click <=< WD.findElem $ WD.ByTag "button"
246+ input <- liftIO $ readIORef inputRef
247+ liftIO $ input `shouldBe` "hello world"
248+ testWidget (pure ()) checkValue $ do
249+ e <- inputElement def
250+ click <- button "save"
251+ performEvent_ $ liftIO . writeIORef inputRef <$> tag (current (value e)) click
252+ it "sets focus appropriately" $ do
253+ focusRef <- newIORef False
255+ liftIO $ readIORef focusRef >>= flip shouldBe False
256+ e <- WD.findElem $ WD.ByTag "input"
258+ liftIO $ threadDelay 100000
259+ liftIO $ readIORef focusRef >>= flip shouldBe True
260+ testWidget (pure ()) checkValue $ do
261+ e <- inputElement def
262+ performEvent_ $ liftIO . writeIORef focusRef <$> updated (_inputElement_hasFocus e)
263+ it "sets focus when focus occurs before hydration" $ do
264+ focusRef <- newIORef False
266+ e <- WD.findElem $ WD.ByTag "input"
268+ hasFocus <- (== e) <$> WD.activeElem
270+ hasFocus `shouldBe` True
271+ readIORef focusRef >>= flip shouldBe False
272+ check = liftIO $ readIORef focusRef >>= flip shouldBe True
273+ testWidget setup check $ do
274+ e <- inputElement def
275+ performEvent_ $ liftIO . writeIORef focusRef <$> updated (_inputElement_hasFocus e)
276+ it "sets value appropriately" $ do
277+ valueByUIRef <- newIORef ""
278+ valueRef <- newIORef ""
279+ setValueChan :: Chan Text <- newChan
281+ liftIO $ readIORef valueByUIRef >>= flip shouldBe ""
282+ liftIO $ readIORef valueRef >>= flip shouldBe ""
283+ e <- WD.findElem $ WD.ByTag "input"
284+ WD.sendKeys "hello" e
287+ readIORef valueByUIRef >>= flip shouldBe "hello"
288+ readIORef valueRef >>= flip shouldBe "hello"
289+ writeChan setValueChan "world"
291+ readIORef valueByUIRef >>= flip shouldBe "hello"
292+ readIORef valueRef >>= flip shouldBe "world"
293+ testWidget (pure ()) checkValue $ do
294+ (setValue, triggerSetValue) <- newTriggerEvent
295+ prerender (pure ()) $ liftIO $ void $ forkIO $ forever $ do
296+ triggerSetValue =<< readChan setValueChan
297+ e <- inputElement $ def & inputElementConfig_setValue .~ setValue
298+ performEvent_ $ liftIO . writeIORef valueByUIRef <$> _inputElement_input e
299+ performEvent_ $ liftIO . writeIORef valueRef <$> updated (value e)
300+ it "sets checked appropriately" $ do
301+ checkedByUIRef <- newIORef False
302+ checkedRef <- newIORef False
303+ setCheckedChan <- newChan
305+ liftIO $ readIORef checkedByUIRef >>= flip shouldBe False
306+ liftIO $ readIORef checkedRef >>= flip shouldBe False
307+ e <- WD.findElem $ WD.ByTag "input"
312+ readIORef checkedByUIRef >>= flip shouldBe True
313+ readIORef checkedRef >>= flip shouldBe True
314+ writeChan setCheckedChan False
316+ readIORef checkedByUIRef >>= flip shouldBe True
317+ readIORef checkedRef >>= flip shouldBe False
318+ testWidget (pure ()) checkValue $ do
319+ (setChecked, triggerSetChecked) <- newTriggerEvent
320+ prerender (pure ()) $ liftIO $ void $ forkIO $ forever $ do
321+ triggerSetChecked =<< readChan setCheckedChan
322+ e <- inputElement $ def
323+ & initialAttributes .~ "type" =: "checkbox"
324+ & inputElementConfig_setChecked .~ setChecked
325+ performEvent_ $ liftIO . writeIORef checkedByUIRef <$> _inputElement_checkedChange e
326+ performEvent_ $ liftIO . writeIORef checkedRef <$> updated (_inputElement_checked e)
327+ it "captures file uploads" $ do
328+ filesRef :: IORef [Text] <- newIORef []
330+ e <- WD.findElem $ WD.ByTag "input"
331+ path <- liftIO $ writeSystemTempFile "testFile" "file contents"
332+ WD.sendKeys (T.pack path) e
333+ WD.click <=< WD.findElem $ WD.ByTag "button"
334+ liftIO $ removeFile path
335+ input <- liftIO $ readIORef filesRef
336+ liftIO $ input `shouldBe` [T.pack $ FilePath.takeFileName path]
337+ testWidget (pure ()) uploadFile $ do
338+ e <- inputElement $ def & initialAttributes .~ "type" =: "file"
339+ click <- button "save"
340+ prerender (pure ()) $ performEvent_ $ ffor (tag (current (_inputElement_files e)) click) $ \fs -> do
341+ names <- liftJSM $ traverse File.getName fs
342+ liftIO $ writeIORef filesRef names
344+ describe "hydration/immediate" $ do
345+ it "captures user input after switchover" $ do
346+ inputRef :: IORef Text <- newIORef ""
348+ WD.sendKeys "hello world" <=< WD.findElem $ WD.ByTag "input"
349+ WD.click <=< WD.findElem $ WD.ByTag "button"
350+ input <- liftIO $ readIORef inputRef
351+ liftIO $ input `shouldBe` "hello world"
247− testWidget (pure ()) checkValue $ do
352+ testWidget (pure ()) checkValue $ prerender (pure ()) $ do
248− e <- inputElement def
353+ e <- inputElement def
249− click <- button "save"
354+ click <- button "save"
250− performEvent_ $ liftIO . writeIORef inputRef <$> tag (current (value e)) click
355+ performEvent_ $ liftIO . writeIORef inputRef <$> tag (current (value e)) click
251− it "sets focus appropriately" $ do
356+ it "sets focus appropriately" $ do
252− focusRef <- newIORef False
357+ focusRef <- newIORef False
253− let checkValue = do
358+ let checkValue = do
254− liftIO $ readIORef focusRef >>= flip shouldBe False
359+ liftIO $ readIORef focusRef >>= flip shouldBe False
255− e <- WD.findElem $ WD.ByTag "input"
360+ e <- WD.findElem $ WD.ByTag "input"
257− WD.click e
361+ WD.click e
258− liftIO $ threadDelay 100000
362+ liftIO $ threadDelay 100000
259− liftIO $ readIORef focusRef >>= flip shouldBe True
363+ liftIO $ readIORef focusRef >>= flip shouldBe True
260− testWidget (pure ()) checkValue $ do
364+ testWidget (pure ()) checkValue $ prerender (pure ()) $ do
261− e <- inputElement def
365+ e <- inputElement def
262− performEvent_ $ liftIO . writeIORef focusRef <$> updated (_inputElement_hasFocus e)
366+ performEvent_ $ liftIO . writeIORef focusRef <$> updated (_inputElement_hasFocus e)
263− it "sets value appropriately" $ do
367+ it "sets value appropriately" $ do
264− valueByUIRef <- newIORef ""
368+ valueByUIRef :: IORef Text <- newIORef ""
265− valueRef <- newIORef ""
369+ valueRef :: IORef Text <- newIORef ""
266− setValueChan :: Chan Text <- newChan
370+ setValueChan :: Chan Text <- newChan
267− let checkValue = do
371+ let checkValue = do
268− liftIO $ readIORef valueByUIRef >>= flip shouldBe ""
372+ liftIO $ readIORef valueByUIRef >>= flip shouldBe ""
269− liftIO $ readIORef valueRef >>= flip shouldBe ""
373+ liftIO $ readIORef valueRef >>= flip shouldBe ""
270− e <- WD.findElem $ WD.ByTag "input"
374+ e <- WD.findElem $ WD.ByTag "input"
271− WD.sendKeys "hello" e
375+ WD.sendKeys "hello" e
272− liftIO $ do
376+ liftIO $ do
273− threadDelay 100000
377+ threadDelay 100000
274− readIORef valueByUIRef >>= flip shouldBe "hello"
378+ readIORef valueByUIRef >>= flip shouldBe "hello"
275− readIORef valueRef >>= flip shouldBe "hello"
379+ readIORef valueRef >>= flip shouldBe "hello"
276− writeChan setValueChan "world"
380+ writeChan setValueChan "world"
277− threadDelay 100000
381+ threadDelay 100000
278− readIORef valueByUIRef >>= flip shouldBe "hello"
382+ readIORef valueByUIRef >>= flip shouldBe "hello"
279− readIORef valueRef >>= flip shouldBe "world"
383+ readIORef valueRef >>= flip shouldBe "world"
280− testWidget (pure ()) checkValue $ do
384+ testWidget (pure ()) checkValue $ prerender (pure ()) $ do
281− (setValue, triggerSetValue) <- newTriggerEvent
385+ (setValue, triggerSetValue) <- newTriggerEvent
282− prerender (pure ()) $ liftIO $ void $ forkIO $ forever $ do
386+ prerender (pure ()) $ liftIO $ void $ forkIO $ forever $ do
283− triggerSetValue =<< readChan setValueChan
387+ triggerSetValue =<< readChan setValueChan
284− e <- inputElement $ def & inputElementConfig_setValue .~ setValue
388+ e <- inputElement $ def & inputElementConfig_setValue .~ setValue
285− performEvent_ $ liftIO . writeIORef valueByUIRef <$> _inputElement_input e
389+ performEvent_ $ liftIO . writeIORef valueByUIRef <$> _inputElement_input e
286− performEvent_ $ liftIO . writeIORef valueRef <$> updated (value e)
390+ performEvent_ $ liftIO . writeIORef valueRef <$> updated (value e)
287− it "sets checked appropriately" $ do
391+ it "sets checked appropriately" $ do
288− checkedByUIRef <- newIORef False
392+ checkedByUIRef <- newIORef False
289− checkedRef <- newIORef False
393+ checkedRef <- newIORef False
290− setCheckedChan <- newChan
394+ setCheckedChan <- newChan
291− let checkValue = do
395+ let checkValue = do
292− liftIO $ readIORef checkedByUIRef >>= flip shouldBe False
396+ liftIO $ readIORef checkedByUIRef >>= flip shouldBe False
293− liftIO $ readIORef checkedRef >>= flip shouldBe False
397+ liftIO $ readIORef checkedRef >>= flip shouldBe False
294− e <- WD.findElem $ WD.ByTag "input"
398+ e <- WD.findElem $ WD.ByTag "input"
295− WD.moveToCenter e
399+ WD.moveToCenter e
296− WD.click e
400+ WD.click e
297− liftIO $ do
401+ liftIO $ do
298− threadDelay 100000
402+ threadDelay 100000
299− readIORef checkedByUIRef >>= flip shouldBe True
403+ readIORef checkedByUIRef >>= flip shouldBe True
300− readIORef checkedRef >>= flip shouldBe True
404+ readIORef checkedRef >>= flip shouldBe True
301− writeChan setCheckedChan False
405+ writeChan setCheckedChan False
302− threadDelay 100000
406+ threadDelay 100000
303− readIORef checkedByUIRef >>= flip shouldBe True
407+ readIORef checkedByUIRef >>= flip shouldBe True
304− readIORef checkedRef >>= flip shouldBe False
408+ readIORef checkedRef >>= flip shouldBe False
305− testWidget (pure ()) checkValue $ do
409+ testWidget (pure ()) checkValue $ prerender (pure ()) $ do
306− (setChecked, triggerSetChecked) <- newTriggerEvent
410+ (setChecked, triggerSetChecked) <- newTriggerEvent
307− prerender (pure ()) $ liftIO $ void $ forkIO $ forever $ do
411+ prerender (pure ()) $ liftIO $ void $ forkIO $ forever $ do
308− triggerSetChecked =<< readChan setCheckedChan
412+ triggerSetChecked =<< readChan setCheckedChan
309− e <- inputElement $ def
413+ e <- inputElement $ def
310− & initialAttributes .~ "type" =: "checkbox"
414+ & initialAttributes .~ "type" =: "checkbox"
311− & inputElementConfig_setChecked .~ setChecked
415+ & inputElementConfig_setChecked .~ setChecked
312− performEvent_ $ liftIO . writeIORef checkedByUIRef <$> _inputElement_checkedChange e
416+ performEvent_ $ liftIO . writeIORef checkedByUIRef <$> _inputElement_checkedChange e
313− performEvent_ $ liftIO . writeIORef checkedRef <$> updated (_inputElement_checked e)
417+ performEvent_ $ liftIO . writeIORef checkedRef <$> updated (_inputElement_checked e)
314− it "captures file uploads" $ do
418+ it "captures file uploads" $ do
315− filesRef :: IORef [Text] <- newIORef []
419+ filesRef :: IORef [Text] <- newIORef []
316− let uploadFile = do
420+ let uploadFile = do
317− e <- WD.findElem $ WD.ByTag "input"
421+ e <- WD.findElem $ WD.ByTag "input"
318− path <- liftIO $ writeSystemTempFile "testFile" "file contents"
422+ path <- liftIO $ writeSystemTempFile "testFile" "file contents"
319− WD.sendKeys (T.pack path) e
423+ WD.sendKeys (T.pack path) e
320− WD.click <=< WD.findElem $ WD.ByTag "button"
424+ WD.click <=< WD.findElem $ WD.ByTag "button"
321− liftIO $ removeFile path
425+ liftIO $ removeFile path
322− input <- liftIO $ readIORef filesRef
426+ input <- liftIO $ readIORef filesRef
323− liftIO $ input `shouldBe` [T.pack $ FilePath.takeFileName path]
427+ liftIO $ input `shouldBe` [T.pack $ FilePath.takeFileName path]
324− testWidget (pure ()) uploadFile $ do
428+ testWidget (pure ()) uploadFile $ prerender (pure ()) $ do
325− e <- inputElement $ def & initialAttributes .~ "type" =: "file"
429+ e <- inputElement $ def & initialAttributes .~ "type" =: "file"
326− click <- button "save"
430+ click <- button "save"
327− prerender (pure ()) $ performEvent_ $ ffor (tag (current (_inputElement_files e)) click) $ \fs -> do
431+ prerender (pure ()) $ performEvent_ $ ffor (tag (current (_inputElement_files e)) click) $ \fs -> do
328− names <- liftJSM $ traverse File.getName fs
432+ names <- liftJSM $ traverse File.getName fs
329− liftIO $ writeIORef filesRef names
433+ liftIO $ writeIORef filesRef names
331 describe "prerender" $ parallel $ do
435 describe "prerender" $ parallel $ do
332 it "works in simple case" $ do
436 it "works in simple case" $ do
@@ -444,4 +548,5 @@ testWidget' beforeJS afterSwitchover bodyWidget = maybe (error "test timed out")
444 a <- beforeJS
548 a <- beforeJS
445 liftIO $ putMVar waitBeforeJS ()
549 liftIO $ putMVar waitBeforeJS ()
446 liftIO $ takeMVar waitUntilSwitchover
550 liftIO $ takeMVar waitUntilSwitchover
551+ liftIO $ threadDelay 100000 -- wait a bit
447 afterSwitchover a
552 afterSwitchover a