@@ -560,6 +560,140 @@ main = hspec $ do
560560 performEvent_ $ liftIO . writeIORef valueByUIRef <$> _textAreaElement_input e
561561 performEvent_ $ liftIO . writeIORef valueRef <$> updated (value e)
562562
563+ describe "selectElement" $ do
564+ let options :: DomBuilder t m => m ()
565+ options = do
566+ elAttr "option" ("value" =: "one" <> "id" =: "one") $ text "one"
567+ elAttr "option" ("value" =: "two" <> "id" =: "two") $ text "two"
568+ elAttr "option" ("value" =: "three" <> "id" =: "three") $ text "three"
569+ describe "hydration" $ do
570+ it "sets initial value correctly" $ do
571+ inputRef <- newIORef ""
572+ let setup = do
573+ e <- WD.findElem $ WD.ByTag "select"
574+ assertAttr e "value" (Just "three")
575+ WD.click <=< WD.findElem $ WD.ById "two"
576+ pure e
577+ check e = do
578+ assertAttr e "value" (Just "two")
579+ liftIO $ readIORef inputRef >>= (`shouldBe` "three")
580+ WD.click <=< WD.findElem $ WD.ByTag "button"
581+ assertAttr e "value" (Just "two")
582+ liftIO $ readIORef inputRef >>= (`shouldBe` "two")
583+ testWidget' setup check $ do
584+ (e, ()) <- selectElement (def { _selectElementConfig_initialValue = "three" }) options
585+ click <- button "save"
586+ liftIO . writeIORef inputRef <=< sample $ current $ _selectElement_value e
587+ performEvent_ $ liftIO . writeIORef inputRef <$> tag (current (_selectElement_value e)) click
588+ it "captures user input after switchover" $ do
589+ inputRef <- newIORef ""
590+ let checkValue = do
591+ e <- WD.findElem $ WD.ByTag "select"
592+ assertAttr e "value" (Just "one")
593+ WD.click <=< WD.findElem $ WD.ById "two"
594+ assertAttr e "value" (Just "two")
595+ WD.click <=< WD.findElem $ WD.ByTag "button"
596+ liftIO $ readIORef inputRef >>= (`shouldBe` "two")
597+ testWidget (pure ()) checkValue $ do
598+ (e, ()) <- selectElement def options
599+ click <- button "save"
600+ performEvent_ $ liftIO . writeIORef inputRef <$> tag (current (_selectElement_value e)) click
601+ it "sets focus appropriately" $ do
602+ focusRef <- newIORef False
603+ let checkValue = do
604+ liftIO $ readIORef focusRef >>= flip shouldBe False
605+ e <- WD.findElem $ WD.ByTag "select"
606+ WD.click e
607+ liftIO $ threadDelay 100000
608+ liftIO $ readIORef focusRef >>= flip shouldBe True
609+ testWidget (pure ()) checkValue $ do
610+ (e, ()) <- selectElement def options
611+ performEvent_ $ liftIO . writeIORef focusRef <$> updated (_selectElement_hasFocus e)
612+ it "sets focus when focus occurs before hydration" $ do
613+ focusRef <- newIORef False
614+ let setup = do
615+ e <- WD.findElem $ WD.ByTag "select"
616+ WD.click e
617+ hasFocus <- (== e) <$> WD.activeElem
618+ liftIO $ do
619+ hasFocus `shouldBe` True
620+ readIORef focusRef >>= flip shouldBe False
621+ check = liftIO $ readIORef focusRef >>= flip shouldBe True
622+ testWidget setup check $ do
623+ (e, ()) <- selectElement def options
624+ performEvent_ $ liftIO . writeIORef focusRef <$> updated (_selectElement_hasFocus e)
625+ it "sets value appropriately" $ do
626+ valueByUIRef <- newIORef ("" :: Text)
627+ valueRef <- newIORef ("" :: Text)
628+ setValueChan :: Chan Text <- newChan
629+ let checkValue = do
630+ e <- WD.findElem $ WD.ByTag "select"
631+ assertAttr e "value" (Just "one")
632+ liftIO $ readIORef valueByUIRef >>= flip shouldBe "one"
633+ liftIO $ readIORef valueRef >>= flip shouldBe "one"
634+ WD.click <=< WD.findElem $ WD.ById "two"
635+ liftIO $ do
636+ threadDelay 100000
637+ readIORef valueByUIRef >>= flip shouldBe "two"
638+ readIORef valueRef >>= flip shouldBe "two"
639+ writeChan setValueChan "three"
640+ threadDelay 100000
641+ readIORef valueByUIRef >>= flip shouldBe "two"
642+ readIORef valueRef >>= flip shouldBe "three"
643+ testWidget (pure ()) checkValue $ do
644+ (setValue', triggerSetValue) <- newTriggerEvent
645+ prerender (pure ()) $ liftIO $ void $ forkIO $ forever $ do
646+ triggerSetValue =<< readChan setValueChan
647+ (e, ()) <- selectElement def { _selectElementConfig_setValue = Just setValue' } options
648+ performEvent_ $ liftIO . writeIORef valueByUIRef <$> _selectElement_change e
649+ performEvent_ $ liftIO . writeIORef valueRef <$> updated (_selectElement_value e)
650+
651+ describe "hydration/immediate" $ do
652+ it "captures user input after switchover" $ do
653+ inputRef :: IORef Text <- newIORef ""
654+ let checkValue = do
655+ WD.click <=< WD.findElem $ WD.ById "two"
656+ WD.click <=< WD.findElem $ WD.ByTag "button"
657+ liftIO $ readIORef inputRef >>= flip shouldBe "two"
658+ testWidget (pure ()) checkValue $ prerender (pure ()) $ do
659+ (e, ()) <- selectElement def options
660+ click <- button "save"
661+ performEvent_ $ liftIO . writeIORef inputRef <$> tag (current (_selectElement_value e)) click
662+ it "sets focus appropriately" $ do
663+ focusRef <- newIORef False
664+ let checkValue = do
665+ liftIO $ readIORef focusRef >>= flip shouldBe False
666+ e <- WD.findElem $ WD.ByTag "select"
667+ WD.click e
668+ liftIO $ threadDelay 100000
669+ liftIO $ readIORef focusRef >>= flip shouldBe True
670+ testWidget (pure ()) checkValue $ prerender (pure ()) $ do
671+ (e, ()) <- selectElement def options
672+ performEvent_ $ liftIO . writeIORef focusRef <$> updated (_selectElement_hasFocus e)
673+ it "sets value appropriately" $ do
674+ valueByUIRef :: IORef Text <- newIORef ""
675+ valueRef :: IORef Text <- newIORef ""
676+ setValueChan :: Chan Text <- newChan
677+ let checkValue = do
678+ liftIO $ readIORef valueByUIRef >>= flip shouldBe "one"
679+ liftIO $ readIORef valueRef >>= flip shouldBe "one"
680+ WD.click <=< WD.findElem $ WD.ById "two"
681+ liftIO $ do
682+ threadDelay 100000
683+ readIORef valueByUIRef >>= flip shouldBe "two"
684+ readIORef valueRef >>= flip shouldBe "two"
685+ writeChan setValueChan "three"
686+ threadDelay 100000
687+ readIORef valueByUIRef >>= flip shouldBe "two"
688+ readIORef valueRef >>= flip shouldBe "three"
689+ testWidget (pure ()) checkValue $ prerender (pure ()) $ do
690+ (setValue', triggerSetValue) <- newTriggerEvent
691+ prerender (pure ()) $ liftIO $ void $ forkIO $ forever $ do
692+ triggerSetValue =<< readChan setValueChan
693+ (e, ()) <- selectElement def { _selectElementConfig_setValue = Just setValue' } options
694+ performEvent_ $ liftIO . writeIORef valueByUIRef <$> _selectElement_change e
695+ performEvent_ $ liftIO . writeIORef valueRef <$> updated (_selectElement_value e)
696+
563697 describe "prerender" $ do
564698 it "works in simple case" $ do
565699 testWidget (checkBodyText "One") (checkBodyText "Two") $ do