Compare commits
8 Commits
main
...
quickstrom
Author | SHA1 | Date |
---|---|---|
Brian Hicks | ed3b11f486 | |
Brian Hicks | a9ce8227c2 | |
Brian Hicks | bcc0963157 | |
Brian Hicks | 442a8f07b4 | |
Brian Hicks | 942e3c5923 | |
Brian Hicks | 678030bcac | |
Brian Hicks | 2617bba31a | |
Brian Hicks | a67bc14fb5 |
|
@ -1,2 +1,3 @@
|
|||
/dist
|
||||
/elm-stuff
|
||||
/logs
|
||||
|
|
|
@ -34,5 +34,17 @@
|
|||
"type": "tarball",
|
||||
"url": "https://github.com/NixOS/nixpkgs/archive/14006b724f3d1f25ecf38238ee723d38b0c2f4ce.tar.gz",
|
||||
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
|
||||
},
|
||||
"quickstrom": {
|
||||
"branch": "main",
|
||||
"description": "High-confidence browser testing",
|
||||
"homepage": "https://quickstrom.io",
|
||||
"owner": "quickstrom",
|
||||
"repo": "quickstrom",
|
||||
"rev": "c103cd337b5d26ba55fda98d5fa456b76c3a4cb4",
|
||||
"sha256": "08wkxvxg4mi2mc1r30j5qzczync33ch2wy0bg90jhgfgszjrvvwl",
|
||||
"type": "tarball",
|
||||
"url": "https://github.com/quickstrom/quickstrom/archive/c103cd337b5d26ba55fda98d5fa456b76c3a4cb4.tar.gz",
|
||||
"url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
mkdir -p logs
|
||||
|
||||
geckodriver > logs/geckodriver.log 2>&1 &
|
||||
GECKODRIVER_PID="$!"
|
||||
|
||||
modd > logs/modd.log 2>&1 &
|
||||
MODD_PID="$!"
|
||||
|
||||
sleep 1
|
||||
|
||||
finish() {
|
||||
set +e
|
||||
kill "$GECKODRIVER_PID" "$MODD_PID"
|
||||
}
|
||||
trap finish EXIT
|
||||
|
||||
quickstrom check tests/EloAnything.spec.purs http://localhost:8000
|
|
@ -5,6 +5,8 @@ let
|
|||
nixpkgs = import sources.nixpkgs { };
|
||||
|
||||
niv = import sources.niv { };
|
||||
|
||||
quickstrom = import sources.quickstrom { };
|
||||
in with nixpkgs;
|
||||
stdenv.mkDerivation {
|
||||
name = "elo-anything";
|
||||
|
@ -21,5 +23,9 @@ stdenv.mkDerivation {
|
|||
gnumake
|
||||
modd
|
||||
devd
|
||||
|
||||
# Testing with Quickstrom
|
||||
quickstrom.quickstrom
|
||||
geckodriver
|
||||
];
|
||||
}
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
module Button exposing (Attribute, button, color, safeForQuickstrom)
|
||||
|
||||
import Accessibility.Styled as Html exposing (Html)
|
||||
import Css
|
||||
import Html.Styled.Attributes as Attributes exposing (css)
|
||||
import Html.Styled.Events as Events
|
||||
|
||||
|
||||
type alias Options =
|
||||
{ color : Css.Color, safeForQuickstrom : Bool }
|
||||
|
||||
|
||||
type Attribute
|
||||
= Color Css.Color
|
||||
| SafeForQuickstrom Bool
|
||||
|
||||
|
||||
color : Css.Color -> Attribute
|
||||
color =
|
||||
Color
|
||||
|
||||
|
||||
safeForQuickstrom : Bool -> Attribute
|
||||
safeForQuickstrom =
|
||||
SafeForQuickstrom
|
||||
|
||||
|
||||
customize : Attribute -> Options -> Options
|
||||
customize attr options =
|
||||
case attr of
|
||||
Color color_ ->
|
||||
{ options | color = color_ }
|
||||
|
||||
SafeForQuickstrom safety ->
|
||||
{ options | safeForQuickstrom = safety }
|
||||
|
||||
|
||||
button : List Attribute -> String -> msg -> Html msg
|
||||
button attrs label msg =
|
||||
let
|
||||
config =
|
||||
List.foldl
|
||||
customize
|
||||
{ color = Css.hex "CCC"
|
||||
, safeForQuickstrom = True
|
||||
}
|
||||
attrs
|
||||
in
|
||||
Html.button
|
||||
[ css
|
||||
[ Css.paddingTop (Css.px 6)
|
||||
, Css.paddingBottom (Css.px 10)
|
||||
, Css.paddingLeft (Css.px 15)
|
||||
, Css.paddingRight (Css.px 15)
|
||||
, Css.minWidth (Css.px 100)
|
||||
, Css.backgroundColor config.color
|
||||
, Css.border Css.zero
|
||||
, Css.borderRadius (Css.px 4)
|
||||
, Css.boxShadow6 Css.inset Css.zero (Css.px -4) Css.zero Css.zero (Css.rgba 0 0 0 0.1)
|
||||
, Css.cursor Css.pointer
|
||||
|
||||
-- font
|
||||
, Css.fontSize (Css.px 14)
|
||||
, Css.fontWeight (Css.int 600)
|
||||
, Css.color (Css.hex "FFF")
|
||||
]
|
||||
, Events.onClick msg
|
||||
, if config.safeForQuickstrom then
|
||||
Attributes.class "quickstrom-safe"
|
||||
|
||||
else
|
||||
Attributes.class "quickstrom-unsafe"
|
||||
]
|
||||
[ Html.text label ]
|
|
@ -0,0 +1,18 @@
|
|||
module Colors exposing (blue, green, red)
|
||||
|
||||
import Css
|
||||
|
||||
|
||||
blue : Css.Color
|
||||
blue =
|
||||
Css.hex "0091FF"
|
||||
|
||||
|
||||
green : Css.Color
|
||||
green =
|
||||
Css.hex "6DD400"
|
||||
|
||||
|
||||
red : Css.Color
|
||||
red =
|
||||
Css.hex "E02020"
|
75
src/Main.elm
75
src/Main.elm
|
@ -2,6 +2,8 @@ module Main exposing (..)
|
|||
|
||||
import Accessibility.Styled as Html exposing (Html)
|
||||
import Browser exposing (Document)
|
||||
import Button exposing (button)
|
||||
import Colors
|
||||
import Css
|
||||
import Css.Reset
|
||||
import Dict exposing (Dict)
|
||||
|
@ -269,10 +271,20 @@ view model =
|
|||
]
|
||||
[ currentMatch model
|
||||
, rankings model
|
||||
, Html.section
|
||||
, Html.footer
|
||||
[ css [ Css.textAlign Css.center, Css.marginTop (Css.px 32) ] ]
|
||||
[ blueButton "Save Standings" KeeperWantsToSaveStandings
|
||||
, blueButton "Load Standings" KeeperWantsToLoadStandings
|
||||
[ button
|
||||
[ Button.color Colors.blue
|
||||
, Button.safeForQuickstrom False
|
||||
]
|
||||
"Save Standings"
|
||||
KeeperWantsToSaveStandings
|
||||
, button
|
||||
[ Button.color Colors.blue
|
||||
, Button.safeForQuickstrom False
|
||||
]
|
||||
"Load Standings"
|
||||
KeeperWantsToLoadStandings
|
||||
]
|
||||
]
|
||||
]
|
||||
|
@ -309,7 +321,12 @@ currentMatch model =
|
|||
]
|
||||
]
|
||||
[ Html.text "No current match. To get started, add at least two players!" ]
|
||||
, blueButton "Load Standings" KeeperWantsToLoadStandings
|
||||
, button
|
||||
[ Button.color Colors.blue
|
||||
, Button.safeForQuickstrom False
|
||||
]
|
||||
"Load Standings"
|
||||
KeeperWantsToLoadStandings
|
||||
]
|
||||
|
||||
Just ( playerA, playerB ) ->
|
||||
|
@ -368,57 +385,17 @@ currentMatch model =
|
|||
]
|
||||
[ Html.div
|
||||
[ css [ Css.width (Css.pct 40) ] ]
|
||||
[ blueButton "Winner!" (MatchFinished playerA Elo.WonAgainst playerB) ]
|
||||
[ button [ Button.color Colors.blue ] "Winner!" (MatchFinished playerA Elo.WonAgainst playerB) ]
|
||||
, Html.div
|
||||
[ css [ Css.width (Css.pct 20) ] ]
|
||||
[ blueButton "Tie!" (MatchFinished playerA Elo.DrewWith playerB) ]
|
||||
[ button [ Button.color Colors.blue ] "Tie!" (MatchFinished playerA Elo.DrewWith playerB) ]
|
||||
, Html.div
|
||||
[ css [ Css.width (Css.pct 40) ] ]
|
||||
[ blueButton "Winner!" (MatchFinished playerB Elo.WonAgainst playerA) ]
|
||||
[ button [ Button.color Colors.blue ] "Winner!" (MatchFinished playerB Elo.WonAgainst playerA) ]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
button : Css.Color -> String -> Msg -> Html Msg
|
||||
button baseColor label msg =
|
||||
Html.button
|
||||
[ css
|
||||
[ Css.paddingTop (Css.px 6)
|
||||
, Css.paddingBottom (Css.px 10)
|
||||
, Css.paddingLeft (Css.px 15)
|
||||
, Css.paddingRight (Css.px 15)
|
||||
, Css.minWidth (Css.px 100)
|
||||
, Css.backgroundColor baseColor
|
||||
, Css.border Css.zero
|
||||
, Css.borderRadius (Css.px 4)
|
||||
, Css.boxShadow6 Css.inset Css.zero (Css.px -4) Css.zero Css.zero (Css.rgba 0 0 0 0.1)
|
||||
, Css.cursor Css.pointer
|
||||
|
||||
-- font
|
||||
, Css.fontSize (Css.px 14)
|
||||
, Css.fontWeight (Css.int 600)
|
||||
, Css.color (Css.hex "FFF")
|
||||
]
|
||||
, Events.onClick msg
|
||||
]
|
||||
[ Html.text label ]
|
||||
|
||||
|
||||
blueButton : String -> Msg -> Html Msg
|
||||
blueButton =
|
||||
button (Css.hex "0091FF")
|
||||
|
||||
|
||||
greenButton : String -> Msg -> Html Msg
|
||||
greenButton =
|
||||
button (Css.hex "6DD400")
|
||||
|
||||
|
||||
redButton : String -> Msg -> Html Msg
|
||||
redButton =
|
||||
button (Css.hex "E02020")
|
||||
|
||||
|
||||
activePlayer : Player -> Html msg
|
||||
activePlayer player =
|
||||
Html.h2
|
||||
|
@ -529,7 +506,7 @@ rankings model =
|
|||
[ Html.text player.name ]
|
||||
, Html.td
|
||||
[ css [ textual, shrinkWidth, center ] ]
|
||||
[ redButton "Retire" (KeeperWantsToRetirePlayer player) ]
|
||||
[ button [ Button.color Colors.red ] "Retire" (KeeperWantsToRetirePlayer player) ]
|
||||
]
|
||||
)
|
||||
|> (::)
|
||||
|
@ -583,7 +560,7 @@ rankings model =
|
|||
]
|
||||
, Html.td
|
||||
[ css [ numeric, shrinkWidth, center ] ]
|
||||
[ greenButton "Add" KeeperWantsToAddNewPlayer ]
|
||||
[ button [ Button.color Colors.green ] "Add" KeeperWantsToAddNewPlayer ]
|
||||
]
|
||||
]
|
||||
)
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
module EloAnythingSpecification where
|
||||
|
||||
import Data.Array
|
||||
import Data.Tuple
|
||||
import Quickstrom
|
||||
|
||||
readyWhen :: Selector
|
||||
readyWhen = "button"
|
||||
|
||||
actions :: Actions
|
||||
actions =
|
||||
asciiKeyPresses <>
|
||||
[ Tuple 1 (Focus "input[type=text]")
|
||||
, Tuple 1 (Click "button.quickstrom-safe")
|
||||
]
|
||||
|
||||
proposition :: Boolean
|
||||
proposition = always (notElem "" headers)
|
||||
|
||||
headers = map _.textContent (queryAll "h2" { textContent })
|
Reference in New Issue