Skip to content

Instantly share code, notes, and snippets.

@ghuntley
Created June 9, 2020 13:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ghuntley/2ae5f2a9d75b321ec3425289def87856 to your computer and use it in GitHub Desktop.
Save ghuntley/2ae5f2a9d75b321ec3425289def87856 to your computer and use it in GitHub Desktop.
PureScript implementation of WebCheck frontend language
module TodoMVC where
import DSL
import Data.Array (filter, head, last)
import Data.Array as Array
import Data.Foldable (length)
import Data.Maybe (Maybe(..))
import Data.Number as Number
import Data.String (Pattern(..), split)
spec :: String -> Spec
spec name =
{
origin : ("http://todomvc.com/examples/" <> name <> "/"),
readyWhen : ".todoapp",
proposition : initial && (always (enterText || addNew || changeFilter || toggleAll))
}
where
initial :: Boolean
initial =
(currentFilter == Nothing || currentFilter == Just "All")
&& (numItems == 0.0)
&& (pendingText == "")
enterText :: Boolean
enterText =
pendingText /= next pendingText
&& itemTexts == next itemTexts
&& currentFilter == next currentFilter
changeFilter :: Boolean
changeFilter =
currentFilter /= next currentFilter
&& (currentFilter == Just "All") ==> (numItems >= next numItems)
&& ( next
( (currentFilter == Just "Active")
==> ( numItemsLeft == Just numUnchecked
&& numItems == numUnchecked
)
)
)
-- NOTE: AngularJS && Mithril implementations are
-- inconsistent with the other JS implementations, in that
-- they clear the input field when the filter is changed.
&& not (name `Array.elem` ["angularjs", "mithril"]) ==> pendingText == next pendingText
addNew =
Just pendingText == next lastItemText
&& next (pendingText == "")
toggleAll =
Just pendingText == next lastItemText
&& currentFilter == next currentFilter
&& ( (currentFilter == Just "All")
==> numItems == next numItems && next (numItems == numChecked)
)
&& ( (currentFilter == Just "Active")
==> ( numItems > 0.0 ==> next numItems == 0.0
|| (numItems == 0.0) ==> next numItems > 0.0
)
)
currentFilter = do
f <- queryOne ".todoapp .filters .selected" { text: textContent }
pure f.text
items :: Array { text :: String }
items = queryAll ".todo-list li" { text: textContent }
itemTexts = map _.text items
lastItemText = last itemTexts
numItems :: Number
numItems = length items
checkboxes = queryAll ".todo-list li input[type=checkbox]" { checked: checked }
numUnchecked = length (filter _.checked checkboxes)
numChecked :: Number
numChecked = length (filter (not <<< _.checked) checkboxes)
pendingText :: String
pendingText = case queryOne ".new-todo" { text: textContent } of
Just el -> el.text
Nothing -> ""
numItemsLeft :: Maybe Number
numItemsLeft = do
strong <- queryOne ".todoapp .todo-count strong" { text: textContent }
first <- head (split (Pattern " ") strong.text)
Number.fromString first
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment