Add part9
This commit is contained in:
4
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/.gitignore
vendored
Normal file
4
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# elm-package generated files
|
||||
elm-stuff/
|
||||
# elm-repl generated files
|
||||
repl-temp-*
|
||||
31
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/.travis.yml
vendored
Normal file
31
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/.travis.yml
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
sudo: false
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- tests/elm-stuff/build-artifacts
|
||||
|
||||
os:
|
||||
- osx
|
||||
- linux
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- ELM_VERSION=0.18 TARGET_NODE_VERSION=node
|
||||
- ELM_VERSION=0.18 TARGET_NODE_VERSION=4.2
|
||||
|
||||
before_install:
|
||||
- if [ ${TRAVIS_OS_NAME} == "osx" ];
|
||||
then brew update; brew install nvm; mkdir ~/.nvm; export NVM_DIR=~/.nvm; source $(brew --prefix nvm)/nvm.sh;
|
||||
fi
|
||||
|
||||
install:
|
||||
- nvm install $TARGET_NODE_VERSION
|
||||
- nvm use $TARGET_NODE_VERSION
|
||||
- node --version
|
||||
- npm --version
|
||||
- npm install -g elm@$ELM_VERSION
|
||||
- npm install -g elm-test
|
||||
|
||||
|
||||
script:
|
||||
- elm-test
|
||||
29
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/LICENSE
vendored
Normal file
29
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/LICENSE
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2016, Noah
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
9
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/README.md
vendored
Normal file
9
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/README.md
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
# elm-html-in-elm
|
||||
|
||||
|
||||
A pure Elm represention of Elm Html. This module has been taken from [elm-server-side-renderer](https://github.com/eeue56/elm-server-side-renderer) and is a pure representation of the Html structure used by VirtualDom. It is designed to allow you to inspect Html nodes
|
||||
|
||||
This package is used to support testing with [elm-html-test](http://package.elm-lang.org/packages/eeue56/elm-html-test/latest).
|
||||
|
||||
This package is also used to support using Elm as to generate static files for
|
||||
your site with [elm-static-html](https://github.com/eeue56/elm-static-html)
|
||||
22
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/elm-package.json
vendored
Normal file
22
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/elm-package.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"version": "5.2.0",
|
||||
"summary": "A pure Elm representation of Elm Html",
|
||||
"repository": "https://github.com/eeue56/elm-html-in-elm.git",
|
||||
"license": "BSD3",
|
||||
"source-directories": [
|
||||
"src"
|
||||
],
|
||||
"exposed-modules": [
|
||||
"ElmHtml.Constants",
|
||||
"ElmHtml.InternalTypes",
|
||||
"ElmHtml.Markdown",
|
||||
"ElmHtml.ToString",
|
||||
"ElmHtml.ToElmString",
|
||||
"ElmHtml.ToHtml"
|
||||
],
|
||||
"dependencies": {
|
||||
"elm-lang/core": "5.0.0 <= v < 6.0.0",
|
||||
"elm-lang/html": "2.0.0 <= v < 3.0.0"
|
||||
},
|
||||
"elm-version": "0.18.0 <= v < 0.19.0"
|
||||
}
|
||||
43
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/src/ElmHtml/Constants.elm
vendored
Normal file
43
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/src/ElmHtml/Constants.elm
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
module ElmHtml.Constants exposing (..)
|
||||
|
||||
{-|
|
||||
Constants for representing internal keys for Elm's vdom implementation
|
||||
|
||||
@docs styleKey, eventKey, attributeKey, attributeNamespaceKey, knownKeys
|
||||
|
||||
-}
|
||||
|
||||
|
||||
{-| Internal key for style
|
||||
-}
|
||||
styleKey : String
|
||||
styleKey =
|
||||
"STYLE"
|
||||
|
||||
|
||||
{-| Internal key for style
|
||||
-}
|
||||
eventKey : String
|
||||
eventKey =
|
||||
"EVENT"
|
||||
|
||||
|
||||
{-| Internal key for style
|
||||
-}
|
||||
attributeKey : String
|
||||
attributeKey =
|
||||
"ATTR"
|
||||
|
||||
|
||||
{-| Internal key for style
|
||||
-}
|
||||
attributeNamespaceKey : String
|
||||
attributeNamespaceKey =
|
||||
"ATTR_NS"
|
||||
|
||||
|
||||
{-| Keys that we are aware of and should pay attention to
|
||||
-}
|
||||
knownKeys : List String
|
||||
knownKeys =
|
||||
[ styleKey, eventKey, attributeKey, attributeNamespaceKey ]
|
||||
17
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/src/ElmHtml/Helpers.elm
vendored
Normal file
17
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/src/ElmHtml/Helpers.elm
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
module ElmHtml.Helpers exposing (..)
|
||||
|
||||
{-|
|
||||
Internal helpers for ElmHtml
|
||||
|
||||
@docs filterKnownKeys
|
||||
-}
|
||||
|
||||
import Dict exposing (Dict)
|
||||
import ElmHtml.Constants exposing (..)
|
||||
|
||||
|
||||
{-| Filter out keys that we don't know
|
||||
-}
|
||||
filterKnownKeys : Dict String a -> Dict String a
|
||||
filterKnownKeys =
|
||||
Dict.filter (\key _ -> not (List.member key knownKeys))
|
||||
581
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/src/ElmHtml/InternalTypes.elm
vendored
Normal file
581
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/src/ElmHtml/InternalTypes.elm
vendored
Normal file
@@ -0,0 +1,581 @@
|
||||
module ElmHtml.InternalTypes
|
||||
exposing
|
||||
( Attribute(..)
|
||||
, AttributeRecord
|
||||
, CustomNodeRecord
|
||||
, ElementKind(..)
|
||||
, ElmHtml(..)
|
||||
, EventHandler
|
||||
, EventRecord
|
||||
, Facts
|
||||
, MarkdownNodeRecord
|
||||
, NamespacedAttributeRecord
|
||||
, NodeRecord
|
||||
, PropertyRecord
|
||||
, Tagger
|
||||
, TextTagRecord
|
||||
, decodeAttribute
|
||||
, decodeElmHtml
|
||||
, emptyFacts
|
||||
, toElementKind
|
||||
)
|
||||
|
||||
{-| Internal types used to represent Elm Html in pure Elm
|
||||
|
||||
@docs ElmHtml, TextTagRecord, NodeRecord, CustomNodeRecord, MarkdownNodeRecord
|
||||
|
||||
@docs Facts, Tagger, EventHandler, ElementKind
|
||||
|
||||
@docs Attribute, AttributeRecord, NamespacedAttributeRecord, PropertyRecord, EventRecord
|
||||
|
||||
@docs decodeElmHtml, emptyFacts, toElementKind, decodeAttribute
|
||||
|
||||
-}
|
||||
|
||||
import Dict exposing (Dict)
|
||||
import ElmHtml.Constants exposing (..)
|
||||
import ElmHtml.Helpers exposing (..)
|
||||
import ElmHtml.Markdown exposing (..)
|
||||
import Html.Events
|
||||
import Json.Decode exposing (field)
|
||||
import Json.Encode
|
||||
|
||||
|
||||
{-| Type tree for representing Elm's Html
|
||||
|
||||
- TextTag is just a plain old bit of text.
|
||||
- NodeEntry is an actual HTML node, e.g a div
|
||||
- CustomNode are nodes defined to work with the renderer in some way, e.g webgl/markdown
|
||||
- MarkdownNode is just a wrapper for CustomNode designed just for markdown
|
||||
|
||||
-}
|
||||
type ElmHtml msg
|
||||
= TextTag TextTagRecord
|
||||
| NodeEntry (NodeRecord msg)
|
||||
| CustomNode (CustomNodeRecord msg)
|
||||
| MarkdownNode (MarkdownNodeRecord msg)
|
||||
| NoOp
|
||||
|
||||
|
||||
{-| Text tags just contain text
|
||||
-}
|
||||
type alias TextTagRecord =
|
||||
{ text : String }
|
||||
|
||||
|
||||
{-| A node contains the `tag` as a string, the children, the facts (e.g attributes) and descendantsCount
|
||||
-}
|
||||
type alias NodeRecord msg =
|
||||
{ tag : String
|
||||
, children : List (ElmHtml msg)
|
||||
, facts :
|
||||
Facts msg
|
||||
|
||||
--, namespace : String
|
||||
, descendantsCount : Int
|
||||
}
|
||||
|
||||
|
||||
{-| A markdown node contains facts (e.g attributes) and the model used by markdown
|
||||
-}
|
||||
type alias MarkdownNodeRecord msg =
|
||||
{ facts : Facts msg
|
||||
, model : MarkdownModel
|
||||
}
|
||||
|
||||
|
||||
{-| Custom nodes contain facts (e.g attributes) and a json value for the model
|
||||
-}
|
||||
type alias CustomNodeRecord msg =
|
||||
{ facts : Facts msg
|
||||
, model : Json.Decode.Value
|
||||
}
|
||||
|
||||
|
||||
{-| Tagger holds the map function when Html.Map is used, the tagger
|
||||
should then be applied to events comming from descendant nodes, it
|
||||
is basically a javascript function.
|
||||
-}
|
||||
type alias Tagger =
|
||||
Json.Decode.Value
|
||||
|
||||
|
||||
{-| EventHandler holds the function that is called when an event is
|
||||
triggered, it is basically a javascript object like this:
|
||||
|
||||
{ decoder: [Function] }
|
||||
|
||||
-}
|
||||
type alias EventHandler =
|
||||
Json.Decode.Value
|
||||
|
||||
|
||||
{-| Facts contain various dictionaries and values for a node
|
||||
|
||||
- styles are a mapping of rules
|
||||
- events may be a json object containing event handlers
|
||||
- attributes are pulled out into stringAttributes and boolAttributes - things with string values go into
|
||||
stringAttributes, things with bool values go into boolAttributes
|
||||
|
||||
-}
|
||||
type alias Facts msg =
|
||||
{ styles : Dict String String
|
||||
, events : Dict String (Json.Decode.Decoder msg)
|
||||
, attributeNamespace : Maybe Json.Decode.Value
|
||||
, stringAttributes : Dict String String
|
||||
, boolAttributes : Dict String Bool
|
||||
}
|
||||
|
||||
|
||||
{-| Type for representing the five kinds of elements according to HTML 5
|
||||
[spec](https://html.spec.whatwg.org/multipage/syntax.html#elements-2).
|
||||
Used to handle different rendering behavior depending on the type of element.
|
||||
-}
|
||||
type ElementKind
|
||||
= VoidElements
|
||||
| RawTextElements
|
||||
| EscapableRawTextElements
|
||||
| ForeignElements
|
||||
| NormalElements
|
||||
|
||||
|
||||
type HtmlContext msg
|
||||
= HtmlContext (List Tagger) (List Tagger -> EventHandler -> Json.Decode.Decoder msg)
|
||||
|
||||
|
||||
{-| Type for representing Elm's Attributes
|
||||
|
||||
- Attribute is an HTML attribute, like `Html.Attributes.colspan`. These values
|
||||
are applied using `element.setAttribute(key, value)` during a patch.
|
||||
- NamespacedAttribute has an namespace, like `Svg.Attributes.xlinkHref`
|
||||
- Property assigns a value to a node like `Html.Attributes.class`, and can
|
||||
hold any encoded value. Unlike attributes, where `element.setAttribute()` is
|
||||
used during the patch, properties are applied directly as
|
||||
`element[key] = value`.
|
||||
- Styles hold a list of key value pairs to be applied to the node's style set
|
||||
- Event contains a decoder for a msg and the `Html.Event.Options` for the event
|
||||
|
||||
-}
|
||||
type Attribute
|
||||
= Attribute AttributeRecord
|
||||
| NamespacedAttribute NamespacedAttributeRecord
|
||||
| Property PropertyRecord
|
||||
| Styles (List ( String, String ))
|
||||
| Event EventRecord
|
||||
|
||||
|
||||
{-| Attribute contains a string key and a string value
|
||||
-}
|
||||
type alias AttributeRecord =
|
||||
{ key : String
|
||||
, value : String
|
||||
}
|
||||
|
||||
|
||||
{-| NamespacedAttribute contains a string key, string namespace and string value
|
||||
-}
|
||||
type alias NamespacedAttributeRecord =
|
||||
{ key : String
|
||||
, value : String
|
||||
, namespace : String
|
||||
}
|
||||
|
||||
|
||||
{-| Property contains a string key and a value with an arbitrary type
|
||||
-}
|
||||
type alias PropertyRecord =
|
||||
{ key : String
|
||||
, value : Json.Decode.Value
|
||||
}
|
||||
|
||||
|
||||
{-| Event contains a string key, a decoder for a msg and event options
|
||||
-}
|
||||
type alias EventRecord =
|
||||
{ key : String
|
||||
, decoder : Json.Decode.Value
|
||||
, options : Html.Events.Options
|
||||
}
|
||||
|
||||
|
||||
{-| decode a json object into ElmHtml, you have to pass a function that decodes
|
||||
events from Html Nodes. If you don't want to decode event msgs, you can ignore it:
|
||||
|
||||
decodeElmHtml (\_ _ -> ()) jsonHtml
|
||||
|
||||
if you do want to decode them, you will probably need to write some native code
|
||||
like elm-html-test does to extract the function inside those.
|
||||
|
||||
-}
|
||||
decodeElmHtml : (List Tagger -> EventHandler -> Json.Decode.Decoder msg) -> Json.Decode.Decoder (ElmHtml msg)
|
||||
decodeElmHtml eventDecoder =
|
||||
contextDecodeElmHtml (HtmlContext [] eventDecoder)
|
||||
|
||||
|
||||
contextDecodeElmHtml : HtmlContext msg -> Json.Decode.Decoder (ElmHtml msg)
|
||||
contextDecodeElmHtml context =
|
||||
field "type" Json.Decode.string
|
||||
|> Json.Decode.andThen
|
||||
(\typeString ->
|
||||
case typeString of
|
||||
"text" ->
|
||||
Json.Decode.map TextTag decodeTextTag
|
||||
|
||||
"keyed-node" ->
|
||||
Json.Decode.map NodeEntry (decodeKeyedNode context)
|
||||
|
||||
"node" ->
|
||||
Json.Decode.map NodeEntry (decodeNode context)
|
||||
|
||||
"custom" ->
|
||||
decodeCustomNode context
|
||||
|
||||
"tagger" ->
|
||||
decodeTagger context
|
||||
|
||||
"thunk" ->
|
||||
field "node" (contextDecodeElmHtml context)
|
||||
|
||||
_ ->
|
||||
Json.Decode.fail ("No such type as " ++ typeString)
|
||||
)
|
||||
|
||||
|
||||
{-| decode text tag
|
||||
-}
|
||||
decodeTextTag : Json.Decode.Decoder TextTagRecord
|
||||
decodeTextTag =
|
||||
field "text" (Json.Decode.andThen (\text -> Json.Decode.succeed { text = text }) Json.Decode.string)
|
||||
|
||||
|
||||
{-| encode text tag
|
||||
-}
|
||||
encodeTextTag : TextTagRecord -> Json.Encode.Value
|
||||
encodeTextTag { text } =
|
||||
Json.Encode.object [ ( "text", Json.Encode.string text ) ]
|
||||
|
||||
|
||||
{-| decode a tagger
|
||||
-}
|
||||
decodeTagger : HtmlContext msg -> Json.Decode.Decoder (ElmHtml msg)
|
||||
decodeTagger (HtmlContext taggers eventDecoder) =
|
||||
Json.Decode.field "tagger" Json.Decode.value
|
||||
|> Json.Decode.andThen
|
||||
(\tagger ->
|
||||
let
|
||||
nodeDecoder =
|
||||
contextDecodeElmHtml (HtmlContext (taggers ++ [ tagger ]) eventDecoder)
|
||||
in
|
||||
Json.Decode.oneOf
|
||||
[ Json.Decode.at [ "node" ] nodeDecoder
|
||||
, Json.Decode.at [ "text" ] nodeDecoder
|
||||
, Json.Decode.at [ "custom" ] nodeDecoder
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
decodeKeyedNode : HtmlContext msg -> Json.Decode.Decoder (NodeRecord msg)
|
||||
decodeKeyedNode context =
|
||||
let
|
||||
-- elm stores keyed nodes as tuples
|
||||
-- we only want to decode the html, in the second property
|
||||
decodeSecondNode =
|
||||
Json.Decode.field "_1" (contextDecodeElmHtml context)
|
||||
in
|
||||
Json.Decode.map4 NodeRecord
|
||||
(Json.Decode.field "tag" Json.Decode.string)
|
||||
(Json.Decode.field "children" (Json.Decode.list decodeSecondNode))
|
||||
(Json.Decode.field "facts" (decodeFacts context))
|
||||
(Json.Decode.field "descendantsCount" Json.Decode.int)
|
||||
|
||||
|
||||
{-| decode a node record
|
||||
-}
|
||||
decodeNode : HtmlContext msg -> Json.Decode.Decoder (NodeRecord msg)
|
||||
decodeNode context =
|
||||
Json.Decode.map4 NodeRecord
|
||||
(field "tag" Json.Decode.string)
|
||||
(field "children" (Json.Decode.list (contextDecodeElmHtml context)))
|
||||
(field "facts" (decodeFacts context))
|
||||
(field "descendantsCount" Json.Decode.int)
|
||||
|
||||
|
||||
{-| encode a node record: currently does not support facts or children
|
||||
-}
|
||||
encodeNodeRecord : NodeRecord msg -> Json.Encode.Value
|
||||
encodeNodeRecord record =
|
||||
Json.Encode.object
|
||||
[ ( "tag", Json.Encode.string record.tag )
|
||||
|
||||
--, ( "children", Json.Encode.list encodeElmHtml)
|
||||
--, ( "facts", encodeFacts)
|
||||
, ( "descendantsCount", Json.Encode.int record.descendantsCount )
|
||||
]
|
||||
|
||||
|
||||
{-| decode custom node into either markdown or custom
|
||||
-}
|
||||
decodeCustomNode : HtmlContext msg -> Json.Decode.Decoder (ElmHtml msg)
|
||||
decodeCustomNode context =
|
||||
Json.Decode.oneOf
|
||||
[ Json.Decode.map MarkdownNode (decodeMarkdownNodeRecord context)
|
||||
, Json.Decode.map CustomNode (decodeCustomNodeRecord context)
|
||||
]
|
||||
|
||||
|
||||
{-| decode custom node record
|
||||
-}
|
||||
decodeCustomNodeRecord : HtmlContext msg -> Json.Decode.Decoder (CustomNodeRecord msg)
|
||||
decodeCustomNodeRecord context =
|
||||
Json.Decode.map2 CustomNodeRecord
|
||||
(field "facts" (decodeFacts context))
|
||||
(field "model" Json.Decode.value)
|
||||
|
||||
|
||||
{-| decode markdown node record
|
||||
-}
|
||||
decodeMarkdownNodeRecord : HtmlContext msg -> Json.Decode.Decoder (MarkdownNodeRecord msg)
|
||||
decodeMarkdownNodeRecord context =
|
||||
Json.Decode.map2 MarkdownNodeRecord
|
||||
(field "facts" (decodeFacts context))
|
||||
(field "model" decodeMarkdownModel)
|
||||
|
||||
|
||||
{-| decode the styles
|
||||
-}
|
||||
decodeStyles : Json.Decode.Decoder (Dict String String)
|
||||
decodeStyles =
|
||||
Json.Decode.oneOf
|
||||
[ field styleKey (Json.Decode.dict Json.Decode.string)
|
||||
, Json.Decode.succeed Dict.empty
|
||||
]
|
||||
|
||||
|
||||
{-| encode styles
|
||||
-}
|
||||
encodeStyles : Dict String String -> Json.Encode.Value
|
||||
encodeStyles stylesDict =
|
||||
let
|
||||
encodedDict =
|
||||
stylesDict
|
||||
|> Dict.toList
|
||||
|> List.map (\( k, v ) -> ( k, Json.Encode.string v ))
|
||||
in
|
||||
Json.Encode.object [ ( styleKey, Json.Encode.object encodedDict ) ]
|
||||
|
||||
|
||||
{-| grab things from attributes via a decoder, then anything that isn't filtered on
|
||||
the object
|
||||
-}
|
||||
decodeOthers : Json.Decode.Decoder a -> Json.Decode.Decoder (Dict String a)
|
||||
decodeOthers otherDecoder =
|
||||
decodeAttributes otherDecoder
|
||||
|> Json.Decode.andThen
|
||||
(\attributes ->
|
||||
decodeDictFilterMap otherDecoder
|
||||
|> Json.Decode.map (filterKnownKeys >> Dict.union attributes)
|
||||
)
|
||||
|
||||
|
||||
{-| For a given decoder, keep the values from a dict that pass the decoder
|
||||
-}
|
||||
decodeDictFilterMap : Json.Decode.Decoder a -> Json.Decode.Decoder (Dict String a)
|
||||
decodeDictFilterMap decoder =
|
||||
Json.Decode.dict Json.Decode.value
|
||||
|> Json.Decode.map
|
||||
(Dict.toList
|
||||
>> List.filterMap
|
||||
(\( key, value ) ->
|
||||
case Json.Decode.decodeValue decoder value of
|
||||
Err _ ->
|
||||
Nothing
|
||||
|
||||
Ok v ->
|
||||
Just ( key, v )
|
||||
)
|
||||
>> Dict.fromList
|
||||
)
|
||||
|
||||
|
||||
decodeAttributes : Json.Decode.Decoder a -> Json.Decode.Decoder (Dict String a)
|
||||
decodeAttributes decoder =
|
||||
Json.Decode.oneOf
|
||||
[ Json.Decode.field attributeKey (decodeDictFilterMap decoder)
|
||||
, Json.Decode.succeed Dict.empty
|
||||
]
|
||||
|
||||
|
||||
decodeEvents : (EventHandler -> Json.Decode.Decoder msg) -> Json.Decode.Decoder (Dict String (Json.Decode.Decoder msg))
|
||||
decodeEvents taggedEventDecoder =
|
||||
Json.Decode.oneOf
|
||||
[ Json.Decode.field eventKey (Json.Decode.dict (Json.Decode.map taggedEventDecoder Json.Decode.value))
|
||||
, Json.Decode.succeed Dict.empty
|
||||
]
|
||||
|
||||
|
||||
{-| decode fact
|
||||
-}
|
||||
decodeFacts : HtmlContext msg -> Json.Decode.Decoder (Facts msg)
|
||||
decodeFacts (HtmlContext taggers eventDecoder) =
|
||||
Json.Decode.map5 Facts
|
||||
decodeStyles
|
||||
(decodeEvents (eventDecoder taggers))
|
||||
(Json.Decode.maybe (Json.Decode.field attributeNamespaceKey Json.Decode.value))
|
||||
(decodeOthers Json.Decode.string)
|
||||
(decodeOthers Json.Decode.bool)
|
||||
|
||||
|
||||
{-| Just empty facts
|
||||
-}
|
||||
emptyFacts : Facts msg
|
||||
emptyFacts =
|
||||
{ styles = Dict.empty
|
||||
, events = Dict.empty
|
||||
, attributeNamespace = Nothing
|
||||
, stringAttributes = Dict.empty
|
||||
, boolAttributes = Dict.empty
|
||||
}
|
||||
|
||||
|
||||
{-| Decode a JSON object into an Attribute. You have to pass a function that
|
||||
decodes events from event attributes. If you don't want to decode event msgs,
|
||||
you can ignore it:
|
||||
|
||||
decodeAttribute (\_ -> ()) jsonHtml
|
||||
|
||||
If you do want to decode them, you will probably need to write some native code
|
||||
like elm-html-test does to extract the function inside those.
|
||||
|
||||
-}
|
||||
decodeAttribute : Json.Decode.Decoder Attribute
|
||||
decodeAttribute =
|
||||
Json.Decode.field "key" Json.Decode.string
|
||||
|> Json.Decode.andThen
|
||||
(\key ->
|
||||
if key == attributeKey then
|
||||
Json.Decode.map2 AttributeRecord
|
||||
(Json.Decode.field "realKey" Json.Decode.string)
|
||||
(Json.Decode.field "value" Json.Decode.string)
|
||||
|> Json.Decode.map Attribute
|
||||
else if key == attributeNamespaceKey then
|
||||
Json.Decode.map3 NamespacedAttributeRecord
|
||||
(Json.Decode.field "realKey" Json.Decode.string)
|
||||
(Json.Decode.at [ "value", "value" ] Json.Decode.string)
|
||||
(Json.Decode.at [ "value", "namespace" ] Json.Decode.string)
|
||||
|> Json.Decode.map NamespacedAttribute
|
||||
else if key == styleKey then
|
||||
Json.Decode.map2 (,)
|
||||
(Json.Decode.field "_0" Json.Decode.string)
|
||||
(Json.Decode.field "_1" Json.Decode.string)
|
||||
|> elmListDecoder
|
||||
|> Json.Decode.field "value"
|
||||
|> Json.Decode.map Styles
|
||||
else if key == eventKey then
|
||||
Json.Decode.map3 EventRecord
|
||||
(Json.Decode.field "realKey" Json.Decode.string)
|
||||
(Json.Decode.at [ "value", "decoder" ] Json.Decode.value)
|
||||
(Json.Decode.at [ "value", "options" ] decodeOptions)
|
||||
|> Json.Decode.map Event
|
||||
else
|
||||
Json.Decode.field "value" Json.Decode.value
|
||||
|> Json.Decode.map (PropertyRecord key >> Property)
|
||||
)
|
||||
|
||||
|
||||
decodeOptions : Json.Decode.Decoder Html.Events.Options
|
||||
decodeOptions =
|
||||
Json.Decode.map2 Html.Events.Options
|
||||
(Json.Decode.field "stopPropagation" Json.Decode.bool)
|
||||
(Json.Decode.field "preventDefault" Json.Decode.bool)
|
||||
|
||||
|
||||
elmListDecoder : Json.Decode.Decoder a -> Json.Decode.Decoder (List a)
|
||||
elmListDecoder itemDecoder =
|
||||
elmListDecoderHelp itemDecoder []
|
||||
|> Json.Decode.map List.reverse
|
||||
|
||||
|
||||
elmListDecoderHelp : Json.Decode.Decoder a -> List a -> Json.Decode.Decoder (List a)
|
||||
elmListDecoderHelp itemDecoder items =
|
||||
Json.Decode.field "ctor" Json.Decode.string
|
||||
|> Json.Decode.andThen
|
||||
(\ctor ->
|
||||
case ctor of
|
||||
"[]" ->
|
||||
Json.Decode.succeed items
|
||||
|
||||
"::" ->
|
||||
Json.Decode.field "_0" itemDecoder
|
||||
|> Json.Decode.andThen
|
||||
(\value ->
|
||||
Json.Decode.field "_1" (elmListDecoderHelp itemDecoder (value :: items))
|
||||
)
|
||||
|
||||
_ ->
|
||||
Json.Decode.fail <| "Unrecognized constructor for an Elm List: " ++ ctor
|
||||
)
|
||||
|
||||
|
||||
{-| A list of Void elements as defined by the HTML5 specification. These
|
||||
elements must not have closing tags and most not be written as self closing
|
||||
either
|
||||
-}
|
||||
voidElements : List String
|
||||
voidElements =
|
||||
[ "area"
|
||||
, "base"
|
||||
, "br"
|
||||
, "col"
|
||||
, "embed"
|
||||
, "hr"
|
||||
, "img"
|
||||
, "input"
|
||||
, "link"
|
||||
, "meta"
|
||||
, "param"
|
||||
, "source"
|
||||
, "track"
|
||||
, "wbr"
|
||||
]
|
||||
|
||||
|
||||
{-| A list of all Raw Text Elements as defined by the HTML5 specification. They
|
||||
can contain only text and have restrictions on which characters can appear
|
||||
within its innerHTML
|
||||
-}
|
||||
rawTextElements : List String
|
||||
rawTextElements =
|
||||
[ "script", "style" ]
|
||||
|
||||
|
||||
{-| A list of all Escapable Raw Text Elements as defined by the HTML5
|
||||
specification. They can have text and character references, but the text must
|
||||
not contain an ambiguous ampersand along with addional restrictions:
|
||||
<https://html.spec.whatwg.org/multipage/syntax.html#cdata-rcdata-restrictions>
|
||||
-}
|
||||
escapableRawTextElements : List String
|
||||
escapableRawTextElements =
|
||||
[ "textarea", "title" ]
|
||||
|
||||
|
||||
|
||||
{- Foreign elements are elements from the MathML namespace and the
|
||||
SVG namespace. TODO: detect these nodes and handle them correctly. Right
|
||||
now they will just be treated as Normal elements.
|
||||
-}
|
||||
|
||||
|
||||
{-| Identify the kind of element. Helper to convert an tag name into a type for
|
||||
pattern matching.
|
||||
-}
|
||||
toElementKind : String -> ElementKind
|
||||
toElementKind element =
|
||||
if List.member element voidElements then
|
||||
VoidElements
|
||||
else if List.member element rawTextElements then
|
||||
RawTextElements
|
||||
else if List.member element escapableRawTextElements then
|
||||
EscapableRawTextElements
|
||||
else
|
||||
-- All other allowed HTML elements are normal elements
|
||||
NormalElements
|
||||
70
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/src/ElmHtml/Markdown.elm
vendored
Normal file
70
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/src/ElmHtml/Markdown.elm
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
module ElmHtml.Markdown exposing (..)
|
||||
|
||||
{-| Markdown helpers
|
||||
|
||||
@docs MarkdownOptions, MarkdownModel, baseMarkdownModel
|
||||
|
||||
@docs encodeOptions, encodeMarkdownModel, decodeMarkdownModel
|
||||
|
||||
-}
|
||||
|
||||
import Json.Encode
|
||||
import Json.Decode exposing (field)
|
||||
|
||||
|
||||
{-| Just a default markdown model
|
||||
-}
|
||||
baseMarkdownModel : MarkdownModel
|
||||
baseMarkdownModel =
|
||||
{ options =
|
||||
{ githubFlavored = Just { tables = False, breaks = False }
|
||||
, defaultHighlighting = Nothing
|
||||
, sanitize = False
|
||||
, smartypants = False
|
||||
}
|
||||
, markdown = ""
|
||||
}
|
||||
|
||||
|
||||
{-| options markdown expects
|
||||
-}
|
||||
type alias MarkdownOptions =
|
||||
{ githubFlavored : Maybe { tables : Bool, breaks : Bool }
|
||||
, defaultHighlighting : Maybe String
|
||||
, sanitize : Bool
|
||||
, smartypants : Bool
|
||||
}
|
||||
|
||||
|
||||
{-| An internal markdown model. Options are the things you give markdown, markdown is the string
|
||||
-}
|
||||
type alias MarkdownModel =
|
||||
{ options : MarkdownOptions
|
||||
, markdown : String
|
||||
}
|
||||
|
||||
|
||||
{-| We don't really care about encoding options right now
|
||||
TODO: we will if we want to represent things as we do for elm-html
|
||||
-}
|
||||
encodeOptions : MarkdownOptions -> Json.Decode.Value
|
||||
encodeOptions options =
|
||||
Json.Encode.null
|
||||
|
||||
|
||||
{-| encode markdown model
|
||||
-}
|
||||
encodeMarkdownModel : MarkdownModel -> Json.Decode.Value
|
||||
encodeMarkdownModel model =
|
||||
Json.Encode.object
|
||||
[ ( "options", encodeOptions model.options )
|
||||
, ( "markdown", Json.Encode.string model.markdown )
|
||||
]
|
||||
|
||||
|
||||
{-| decode a markdown model
|
||||
-}
|
||||
decodeMarkdownModel : Json.Decode.Decoder MarkdownModel
|
||||
decodeMarkdownModel =
|
||||
field "markdown" Json.Decode.string
|
||||
|> Json.Decode.map (MarkdownModel baseMarkdownModel.options)
|
||||
143
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/src/ElmHtml/ToElmString.elm
vendored
Normal file
143
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/src/ElmHtml/ToElmString.elm
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
module ElmHtml.ToElmString
|
||||
exposing
|
||||
( toElmString
|
||||
, nodeRecordToString
|
||||
, toElmStringWithOptions
|
||||
, FormatOptions
|
||||
, defaultFormatOptions
|
||||
)
|
||||
|
||||
{-| Convert ElmHtml to string of Elm code.
|
||||
|
||||
@docs nodeRecordToString, toElmString, toElmStringWithOptions
|
||||
|
||||
@docs FormatOptions, defaultFormatOptions
|
||||
|
||||
-}
|
||||
|
||||
import String
|
||||
import Dict exposing (Dict)
|
||||
import ElmHtml.InternalTypes exposing (..)
|
||||
|
||||
|
||||
{-| Formatting options to be used for converting to string
|
||||
-}
|
||||
type alias FormatOptions =
|
||||
{ indent : Int
|
||||
, newLines : Bool
|
||||
}
|
||||
|
||||
|
||||
{-| default formatting options
|
||||
-}
|
||||
defaultFormatOptions : FormatOptions
|
||||
defaultFormatOptions =
|
||||
{ indent = 0
|
||||
, newLines = False
|
||||
}
|
||||
|
||||
|
||||
nodeToLines : FormatOptions -> ElmHtml msg -> List String
|
||||
nodeToLines options nodeType =
|
||||
case nodeType of
|
||||
TextTag { text } ->
|
||||
[ "Html.text \"" ++ text ++ "\"" ]
|
||||
|
||||
NodeEntry record ->
|
||||
nodeRecordToString options record
|
||||
|
||||
CustomNode record ->
|
||||
[]
|
||||
|
||||
MarkdownNode record ->
|
||||
[ record.model.markdown ]
|
||||
|
||||
NoOp ->
|
||||
[]
|
||||
|
||||
|
||||
{-| Convert a given html node to a string based on the type
|
||||
-}
|
||||
toElmString : ElmHtml msg -> String
|
||||
toElmString =
|
||||
toElmStringWithOptions defaultFormatOptions
|
||||
|
||||
|
||||
{-| same as toElmString, but with options
|
||||
-}
|
||||
toElmStringWithOptions : FormatOptions -> ElmHtml msg -> String
|
||||
toElmStringWithOptions options =
|
||||
nodeToLines options
|
||||
>> String.join
|
||||
(if options.newLines then
|
||||
"\n"
|
||||
else
|
||||
""
|
||||
)
|
||||
|
||||
|
||||
{-| Convert a node record to a string. This basically takes the tag name, then
|
||||
pulls all the facts into tag declaration, then goes through the children and
|
||||
nests them under this one
|
||||
-}
|
||||
nodeRecordToString : FormatOptions -> NodeRecord msg -> List String
|
||||
nodeRecordToString options { tag, children, facts } =
|
||||
let
|
||||
openTag : List (Maybe String) -> String
|
||||
openTag extras =
|
||||
let
|
||||
trimmedExtras =
|
||||
List.filterMap (\x -> x) extras
|
||||
|> List.map String.trim
|
||||
|> List.filter ((/=) "")
|
||||
|
||||
filling =
|
||||
case trimmedExtras of
|
||||
[] ->
|
||||
""
|
||||
|
||||
more ->
|
||||
" " ++ (String.join " " more)
|
||||
in
|
||||
"Html." ++ tag ++ " [" ++ filling
|
||||
|
||||
childrenStrings =
|
||||
List.map (nodeToLines options) children
|
||||
|> List.concat
|
||||
|> List.map ((++) (String.repeat options.indent " "))
|
||||
|
||||
styles =
|
||||
case Dict.toList facts.styles of
|
||||
[] ->
|
||||
Nothing
|
||||
|
||||
styles ->
|
||||
styles
|
||||
|> List.map (\( key, value ) -> "(\"" ++ key ++ "\",\"" ++ value ++ "\")")
|
||||
|> String.join ", "
|
||||
|> (\styleString -> "Html.Attributes.style [" ++ styleString ++ "]")
|
||||
|> Just
|
||||
|
||||
classes =
|
||||
Dict.get "className" facts.stringAttributes
|
||||
|> Maybe.map (\name -> "Html.Attributes.class [\"" ++ name ++ "\"]")
|
||||
|
||||
stringAttributes =
|
||||
Dict.filter (\k v -> k /= "className") facts.stringAttributes
|
||||
|> Dict.toList
|
||||
|> List.map (\( k, v ) -> "Html.Attributes." ++ k ++ " \"" ++ v ++ "\"")
|
||||
|> String.join ", "
|
||||
|> Just
|
||||
|
||||
boolAttributes =
|
||||
Dict.toList facts.boolAttributes
|
||||
|> List.map (\( k, v ) -> "Html.Attributes.property \"" ++ k ++ "\" <| Json.Encode.bool " ++ toString v)
|
||||
|> String.join " "
|
||||
|> Just
|
||||
in
|
||||
[ openTag [ classes, styles, stringAttributes, boolAttributes ] ]
|
||||
++ [ " ] "
|
||||
, "[ "
|
||||
, String.join "" childrenStrings
|
||||
, "]"
|
||||
]
|
||||
82
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/src/ElmHtml/ToHtml.elm
vendored
Normal file
82
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/src/ElmHtml/ToHtml.elm
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
module ElmHtml.ToHtml exposing (toHtml, factsToAttributes)
|
||||
|
||||
{-| This module is particularly useful for putting parsed Html into Elm.Html at runtime.
|
||||
Estentially allowing the user to use tools like html-to-elm on their code.
|
||||
|
||||
@docs toHtml, factsToAttributes
|
||||
|
||||
-}
|
||||
|
||||
import String
|
||||
import Dict exposing (Dict)
|
||||
import ElmHtml.InternalTypes exposing (..)
|
||||
import Html
|
||||
import Html.Attributes
|
||||
import Html.Events
|
||||
import Json.Encode
|
||||
import Json.Decode
|
||||
|
||||
|
||||
{-| Turns ElmHtml into normal Elm Html
|
||||
-}
|
||||
toHtml : ElmHtml msg -> Html.Html msg
|
||||
toHtml elmHtml =
|
||||
case elmHtml of
|
||||
TextTag text ->
|
||||
Html.text text.text
|
||||
|
||||
NodeEntry { tag, children, facts } ->
|
||||
Html.node tag [] (List.map toHtml children)
|
||||
|
||||
CustomNode record ->
|
||||
let
|
||||
_ =
|
||||
Debug.log "Custom node is not supported" ""
|
||||
in
|
||||
Html.text ""
|
||||
|
||||
MarkdownNode record ->
|
||||
let
|
||||
_ =
|
||||
Debug.log "Markdown node is not supported" ""
|
||||
in
|
||||
Html.text ""
|
||||
|
||||
NoOp ->
|
||||
Html.text ""
|
||||
|
||||
|
||||
stylesToAttribute : Dict String String -> Html.Attribute msg
|
||||
stylesToAttribute =
|
||||
Dict.toList
|
||||
>> Html.Attributes.style
|
||||
|
||||
|
||||
eventsToAttributes : Dict String (Json.Decode.Decoder msg) -> List (Html.Attribute msg)
|
||||
eventsToAttributes =
|
||||
Dict.toList
|
||||
>> List.map (\( x, y ) -> Html.Events.on x y)
|
||||
|
||||
|
||||
stringAttributesToAttributes : Dict String String -> List (Html.Attribute msg)
|
||||
stringAttributesToAttributes =
|
||||
Dict.toList
|
||||
>> List.map (\( x, y ) -> Html.Attributes.attribute x y)
|
||||
|
||||
|
||||
boolAttributesToAttributes : Dict String Bool -> List (Html.Attribute msg)
|
||||
boolAttributesToAttributes =
|
||||
Dict.toList
|
||||
>> List.map (\( x, y ) -> Html.Attributes.property x (Json.Encode.bool y))
|
||||
|
||||
|
||||
{-| Turns a fact record into a list of attributes
|
||||
-}
|
||||
factsToAttributes : Facts msg -> List (Html.Attribute msg)
|
||||
factsToAttributes facts =
|
||||
List.concat
|
||||
[ [ stylesToAttribute facts.styles ]
|
||||
, eventsToAttributes facts.events
|
||||
, stringAttributesToAttributes facts.stringAttributes
|
||||
, boolAttributesToAttributes facts.boolAttributes
|
||||
]
|
||||
155
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/src/ElmHtml/ToString.elm
vendored
Normal file
155
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/src/ElmHtml/ToString.elm
vendored
Normal file
@@ -0,0 +1,155 @@
|
||||
module ElmHtml.ToString
|
||||
exposing
|
||||
( nodeToString
|
||||
, nodeRecordToString
|
||||
, nodeToStringWithOptions
|
||||
, FormatOptions
|
||||
, defaultFormatOptions
|
||||
)
|
||||
|
||||
{-| Convert ElmHtml to string.
|
||||
|
||||
@docs nodeRecordToString, nodeToString, nodeToStringWithOptions
|
||||
|
||||
@docs FormatOptions, defaultFormatOptions
|
||||
-}
|
||||
|
||||
import String
|
||||
import Dict exposing (Dict)
|
||||
import ElmHtml.InternalTypes exposing (..)
|
||||
|
||||
|
||||
{-| Formatting options to be used for converting to string
|
||||
-}
|
||||
type alias FormatOptions =
|
||||
{ indent : Int
|
||||
, newLines : Bool
|
||||
}
|
||||
|
||||
|
||||
{-| default formatting options
|
||||
-}
|
||||
defaultFormatOptions : FormatOptions
|
||||
defaultFormatOptions =
|
||||
{ indent = 0
|
||||
, newLines = False
|
||||
}
|
||||
|
||||
|
||||
nodeToLines : FormatOptions -> ElmHtml msg -> List String
|
||||
nodeToLines options nodeType =
|
||||
case nodeType of
|
||||
TextTag { text } ->
|
||||
[ text ]
|
||||
|
||||
NodeEntry record ->
|
||||
nodeRecordToString options record
|
||||
|
||||
CustomNode record ->
|
||||
[]
|
||||
|
||||
MarkdownNode record ->
|
||||
[ record.model.markdown ]
|
||||
|
||||
NoOp ->
|
||||
[]
|
||||
|
||||
|
||||
{-| Convert a given html node to a string based on the type
|
||||
-}
|
||||
nodeToString : ElmHtml msg -> String
|
||||
nodeToString =
|
||||
nodeToStringWithOptions defaultFormatOptions
|
||||
|
||||
|
||||
{-| same as nodeToString, but with options
|
||||
-}
|
||||
nodeToStringWithOptions : FormatOptions -> ElmHtml msg -> String
|
||||
nodeToStringWithOptions options =
|
||||
nodeToLines options
|
||||
>> String.join
|
||||
(if options.newLines then
|
||||
"\n"
|
||||
else
|
||||
""
|
||||
)
|
||||
|
||||
|
||||
{-| Convert a node record to a string. This basically takes the tag name, then
|
||||
pulls all the facts into tag declaration, then goes through the children and
|
||||
nests them under this one
|
||||
-}
|
||||
nodeRecordToString : FormatOptions -> NodeRecord msg -> List String
|
||||
nodeRecordToString options { tag, children, facts } =
|
||||
let
|
||||
openTag : List (Maybe String) -> String
|
||||
openTag extras =
|
||||
let
|
||||
trimmedExtras =
|
||||
List.filterMap (\x -> x) extras
|
||||
|> List.map String.trim
|
||||
|> List.filter ((/=) "")
|
||||
|
||||
filling =
|
||||
case trimmedExtras of
|
||||
[] ->
|
||||
""
|
||||
|
||||
more ->
|
||||
" " ++ (String.join " " more)
|
||||
in
|
||||
"<" ++ tag ++ filling ++ ">"
|
||||
|
||||
closeTag =
|
||||
"</" ++ tag ++ ">"
|
||||
|
||||
childrenStrings =
|
||||
List.map (nodeToLines options) children
|
||||
|> List.concat
|
||||
|> List.map ((++) (String.repeat options.indent " "))
|
||||
|
||||
styles =
|
||||
case Dict.toList facts.styles of
|
||||
[] ->
|
||||
Nothing
|
||||
|
||||
styles ->
|
||||
styles
|
||||
|> List.map (\( key, value ) -> key ++ ":" ++ value ++ ";")
|
||||
|> String.join ""
|
||||
|> (\styleString -> "style=\"" ++ styleString ++ "\"")
|
||||
|> Just
|
||||
|
||||
classes =
|
||||
Dict.get "className" facts.stringAttributes
|
||||
|> Maybe.map (\name -> "class=\"" ++ name ++ "\"")
|
||||
|
||||
stringAttributes =
|
||||
Dict.filter (\k v -> k /= "className") facts.stringAttributes
|
||||
|> Dict.toList
|
||||
|> List.map (\( k, v ) -> k ++ "=\"" ++ v ++ "\"")
|
||||
|> String.join " "
|
||||
|> Just
|
||||
|
||||
boolAttributes =
|
||||
Dict.toList facts.boolAttributes
|
||||
|> List.map (\( k, v ) -> k ++ "=" ++ (String.toLower <| toString v))
|
||||
|> String.join " "
|
||||
|> Just
|
||||
in
|
||||
case toElementKind tag of
|
||||
{- Void elements only have a start tag; end tags must not be
|
||||
specified for void elements.
|
||||
-}
|
||||
VoidElements ->
|
||||
[ openTag [ classes, styles, stringAttributes, boolAttributes ] ]
|
||||
|
||||
{- TODO: implement restrictions for RawTextElements,
|
||||
EscapableRawTextElements. Also handle ForeignElements correctly.
|
||||
For now just punt and use the previous behavior for all other
|
||||
element kinds.
|
||||
-}
|
||||
_ ->
|
||||
[ openTag [ classes, styles, stringAttributes, boolAttributes ] ]
|
||||
++ childrenStrings
|
||||
++ [ closeTag ]
|
||||
16
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/tests/Native/HtmlAsJson.js
vendored
Normal file
16
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/tests/Native/HtmlAsJson.js
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
var _eeue56$elm_html_in_elm$Native_HtmlAsJson = (function() {
|
||||
return {
|
||||
unsafeCoerce: function(a) {
|
||||
return a;
|
||||
},
|
||||
eventDecoder: function (event) {
|
||||
return event.decoder;
|
||||
},
|
||||
eventHandler: F2(function(eventName, html) {
|
||||
return html.facts.EVENT[eventName];
|
||||
}),
|
||||
taggerFunction: function(tagger) {
|
||||
return tagger;
|
||||
}
|
||||
};
|
||||
})();
|
||||
311
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/tests/Tests.elm
vendored
Normal file
311
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/tests/Tests.elm
vendored
Normal file
@@ -0,0 +1,311 @@
|
||||
module Tests exposing (..)
|
||||
|
||||
import Dict
|
||||
import ElmHtml.InternalTypes exposing (Attribute(..), ElmHtml(..), EventHandler, Facts, NodeRecord, Tagger, decodeAttribute, decodeElmHtml)
|
||||
import ElmHtml.ToHtml
|
||||
import ElmHtml.ToElmString exposing (toElmString)
|
||||
import Expect
|
||||
import Html exposing (Html, button, div, input, text)
|
||||
import Html.Attributes exposing (class, colspan, disabled, style, value)
|
||||
import Html.Events exposing (onCheck, onClick, onInput)
|
||||
import Json.Decode exposing (decodeValue)
|
||||
import Json.Encode
|
||||
import Native.HtmlAsJson
|
||||
import Svg.Attributes exposing (xlinkHref)
|
||||
import Test exposing (..)
|
||||
|
||||
|
||||
elmHtml : Test
|
||||
elmHtml =
|
||||
describe "ElmHtml parsing"
|
||||
[ test "parsing a node" <|
|
||||
\() ->
|
||||
div [] []
|
||||
|> fromHtml
|
||||
|> Expect.equal (Ok (NodeEntry decodedNode))
|
||||
, test "parsing a text" <|
|
||||
\() ->
|
||||
text "foo"
|
||||
|> fromHtml
|
||||
|> Expect.equal (Ok (TextTag { text = "foo" }))
|
||||
, test "parsing attributes" <|
|
||||
\() ->
|
||||
let
|
||||
facts =
|
||||
{ decodedFacts
|
||||
| stringAttributes = Dict.fromList [ ( "className", "foo" ), ( "value", "bar" ) ]
|
||||
, boolAttributes = Dict.fromList [ ( "disabled", True ) ]
|
||||
}
|
||||
|
||||
expected =
|
||||
{ decodedNode | tag = "button", facts = facts }
|
||||
in
|
||||
button [ class "foo", value "bar", disabled True ] []
|
||||
|> fromHtml
|
||||
|> Expect.equal (Ok (NodeEntry expected))
|
||||
, test "parsing children" <|
|
||||
\() ->
|
||||
let
|
||||
expected =
|
||||
{ decodedNode
|
||||
| children = [ NodeEntry decodedNode, TextTag { text = "foo" } ]
|
||||
, descendantsCount = 2
|
||||
}
|
||||
in
|
||||
div []
|
||||
[ div [] []
|
||||
, text "foo"
|
||||
]
|
||||
|> fromHtml
|
||||
|> Expect.equal (Ok (NodeEntry expected))
|
||||
, describe "parsing events"
|
||||
[ testParsingEvent "click" (onClick SomeMsg)
|
||||
, testParsingEvent "input" (onInput InputMsg)
|
||||
, testParsingEvent "change" (onCheck CheckMsg)
|
||||
]
|
||||
, describe "parsing Html.map"
|
||||
[ test "adds the correct tagger to a mapped button" <|
|
||||
\() ->
|
||||
let
|
||||
taggedNode =
|
||||
input [ onInput identity ] []
|
||||
|> Html.map (\msg -> msg ++ "bar")
|
||||
|> fromHtml
|
||||
in
|
||||
taggedNode
|
||||
|> Result.andThen (simulate "input" "{\"target\": {\"value\": \"foo\"}}")
|
||||
|> Expect.equal (Ok "foobar")
|
||||
, test "adds two taggers to a double mapped button with changing types" <|
|
||||
\() ->
|
||||
let
|
||||
taggedNode =
|
||||
input [ onInput identity ] []
|
||||
|> Html.map (\str -> [ str ] ++ [ "bar" ])
|
||||
|> Html.map (\list -> ( list, "baz" ))
|
||||
|> fromHtml
|
||||
in
|
||||
taggedNode
|
||||
|> Result.andThen (simulate "input" "{\"target\": {\"value\": \"foo\"}}")
|
||||
|> Expect.equal (Ok ( [ "foo", "bar" ], "baz" ))
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
elmHtmlToHtml : Test
|
||||
elmHtmlToHtml =
|
||||
describe "Turning the AST into Html"
|
||||
[ test "parsing a node" <|
|
||||
\() ->
|
||||
div [] []
|
||||
|> fromHtml
|
||||
|> Result.map ElmHtml.ToHtml.toHtml
|
||||
|> Expect.equal (Ok <| div [] [])
|
||||
, test "parsing a text" <|
|
||||
\() ->
|
||||
text "foo"
|
||||
|> fromHtml
|
||||
|> Result.map ElmHtml.ToHtml.toHtml
|
||||
|> Expect.equal (Ok <| text "foo")
|
||||
, test "parsing a text in a div" <|
|
||||
\() ->
|
||||
div [] [ text "foo" ]
|
||||
|> fromHtml
|
||||
|> Result.map ElmHtml.ToHtml.toHtml
|
||||
|> Expect.equal (Ok <| div [] [ text "foo" ])
|
||||
, test "parsing a text in a div in a div in a div " <|
|
||||
\() ->
|
||||
div [] [ div [] [ text "banana", div [] [ text "foo", text "bar" ] ] ]
|
||||
|> fromHtml
|
||||
|> Result.map ElmHtml.ToHtml.toHtml
|
||||
|> Expect.equal (Ok <| div [] [ div [] [ text "banana", div [] [ text "foo", text "bar" ] ] ])
|
||||
, test "parsing styles in a div" <|
|
||||
\() ->
|
||||
div [ Html.Attributes.style [ ( "background", "red" ) ] ] [ text "foo" ]
|
||||
|> fromHtml
|
||||
|> Result.map ElmHtml.ToHtml.toHtml
|
||||
|> Expect.equal (Ok <| div [ Html.Attributes.style [ ( "background", "red" ) ] ] [ text "foo" ])
|
||||
, test "parsing attributes a div" <|
|
||||
\() ->
|
||||
div [ Html.Attributes.name "fish", Html.Attributes.checked True ] [ text "foo" ]
|
||||
|> fromHtml
|
||||
|> Result.map ElmHtml.ToHtml.toHtml
|
||||
|> Expect.equal (Ok <| div [ Html.Attributes.name "fish", Html.Attributes.checked True ] [ text "foo" ])
|
||||
, test "parsing attributes in a nested div" <|
|
||||
\() ->
|
||||
div [ Html.Attributes.name "fish", Html.Attributes.checked True ] [ Html.li [ Html.Attributes.type_ "hello" ] [ text "foo" ] ]
|
||||
|> fromHtml
|
||||
|> Result.map ElmHtml.ToHtml.toHtml
|
||||
|> Expect.equal (Ok <| div [ Html.Attributes.name "fish", Html.Attributes.checked True ] [ Html.li [ Html.Attributes.type_ "hello" ] [ text "foo" ] ])
|
||||
, test "parsing events in a div" <|
|
||||
\() ->
|
||||
div [ Html.Events.onClick True ] []
|
||||
|> fromHtml
|
||||
|> Result.map ElmHtml.ToHtml.toHtml
|
||||
|> Expect.equal (Ok <| div [ Html.Events.onClick True ] [])
|
||||
]
|
||||
|
||||
|
||||
elmHtmlToElmString : Test
|
||||
elmHtmlToElmString =
|
||||
describe "Turning the AST into Elm, but as a string"
|
||||
[ test "parsing a node" <|
|
||||
\() ->
|
||||
div [] []
|
||||
|> fromHtml
|
||||
|> Result.map toElmString
|
||||
|> Expect.equal (Ok <| "Html.div [ ] [ ]")
|
||||
, test "parsing a text" <|
|
||||
\() ->
|
||||
text "foo"
|
||||
|> fromHtml
|
||||
|> Result.map toElmString
|
||||
|> Expect.equal (Ok <| "Html.text \"foo\"")
|
||||
, test "parsing a nested node" <|
|
||||
\() ->
|
||||
div [] [ div [] [ text "hello" ] ]
|
||||
|> fromHtml
|
||||
|> Result.map toElmString
|
||||
|> Expect.equal (Ok <| "Html.div [ ] [ Html.div [ ] [ Html.text \"hello\"]]")
|
||||
, test "parsing an attribute" <|
|
||||
\() ->
|
||||
div [ Html.Attributes.checked True ] [ text "hello" ]
|
||||
|> fromHtml
|
||||
|> Result.map toElmString
|
||||
|> Expect.equal (Ok <| "Html.div [ Html.Attributes.property \"checked\" <| Json.Encode.bool True ] [ Html.text \"hello\"]")
|
||||
]
|
||||
|
||||
|
||||
attributes : Test
|
||||
attributes =
|
||||
describe "Attribute parsing"
|
||||
[ test "parsing Attribute" <|
|
||||
\() ->
|
||||
colspan 1
|
||||
|> fromAttribute
|
||||
|> Expect.equal (Ok (Attribute { key = "colspan", value = "1" }))
|
||||
, test "parsing NamespacedAttribute" <|
|
||||
\() ->
|
||||
xlinkHref "#id"
|
||||
|> fromAttribute
|
||||
|> Expect.equal
|
||||
(Ok (NamespacedAttribute { key = "xlink:href", value = "#id", namespace = "http://www.w3.org/1999/xlink" }))
|
||||
, test "parsing Property" <|
|
||||
\() ->
|
||||
disabled True
|
||||
|> fromAttribute
|
||||
|> Expect.equal (Ok (Property { key = "disabled", value = Json.Encode.bool True }))
|
||||
, test "parsing Event" <|
|
||||
\() ->
|
||||
onClick ()
|
||||
|> fromAttribute
|
||||
|> Expect.equal
|
||||
(Ok (Event { key = "click", decoder = toJson (Json.Decode.succeed ()), options = Html.Events.defaultOptions }))
|
||||
, test "parsing Styles" <|
|
||||
\() ->
|
||||
style [ ( "margin", "0" ) ]
|
||||
|> fromAttribute
|
||||
|> Expect.equal (Ok (Styles [ ( "margin", "0" ) ]))
|
||||
]
|
||||
|
||||
|
||||
type Msg
|
||||
= SomeMsg
|
||||
| InputMsg String
|
||||
| CheckMsg Bool
|
||||
|
||||
|
||||
toJson : a -> Json.Decode.Value
|
||||
toJson =
|
||||
Native.HtmlAsJson.unsafeCoerce
|
||||
|
||||
|
||||
eventDecoder : EventHandler -> Json.Decode.Decoder msg
|
||||
eventDecoder eventHandler =
|
||||
Native.HtmlAsJson.eventDecoder eventHandler
|
||||
|
||||
|
||||
eventHandler : String -> Html a -> Json.Decode.Value
|
||||
eventHandler eventName node =
|
||||
Native.HtmlAsJson.eventHandler eventName node
|
||||
|
||||
|
||||
taggerFunction : Tagger -> (a -> msg)
|
||||
taggerFunction tagger =
|
||||
Native.HtmlAsJson.taggerFunction tagger
|
||||
|
||||
|
||||
taggedEventDecoder : List Tagger -> EventHandler -> Json.Decode.Decoder msg
|
||||
taggedEventDecoder taggers eventHandler =
|
||||
case taggers of
|
||||
[] ->
|
||||
eventDecoder eventHandler
|
||||
|
||||
[ tagger ] ->
|
||||
Json.Decode.map (taggerFunction tagger) (eventDecoder eventHandler)
|
||||
|
||||
tagger :: taggers ->
|
||||
Json.Decode.map (taggerFunction tagger) (taggedEventDecoder taggers eventHandler)
|
||||
|
||||
|
||||
fromAttribute : Html.Attribute a -> Result String Attribute
|
||||
fromAttribute attribute =
|
||||
toJson attribute
|
||||
|> decodeValue decodeAttribute
|
||||
|
||||
|
||||
decodedNode : NodeRecord msg
|
||||
decodedNode =
|
||||
{ tag = "div"
|
||||
, children = []
|
||||
, facts = decodedFacts
|
||||
, descendantsCount = 0
|
||||
}
|
||||
|
||||
|
||||
decodedFacts : Facts msg
|
||||
decodedFacts =
|
||||
{ styles = Dict.fromList []
|
||||
, events = Dict.fromList []
|
||||
, attributeNamespace = Nothing
|
||||
, stringAttributes = Dict.fromList []
|
||||
, boolAttributes = Dict.fromList []
|
||||
}
|
||||
|
||||
|
||||
fromHtml : Html a -> Result String (ElmHtml msg)
|
||||
fromHtml html =
|
||||
toJson html
|
||||
|> decodeValue (decodeElmHtml taggedEventDecoder)
|
||||
|
||||
|
||||
simulate : String -> String -> ElmHtml msg -> Result String msg
|
||||
simulate eventName event parsedHtml =
|
||||
case parsedHtml of
|
||||
NodeEntry node ->
|
||||
Dict.get eventName node.facts.events
|
||||
|> Result.fromMaybe "Tried to trigger event on something other than a NodeEntry"
|
||||
|> Result.andThen (\eventDecoder -> Json.Decode.decodeString eventDecoder event)
|
||||
|
||||
_ ->
|
||||
Err "Tried to trigger event on something other than a NodeEntry"
|
||||
|
||||
|
||||
testParsingEvent : String -> Html.Attribute a -> Test
|
||||
testParsingEvent eventName eventAttribute =
|
||||
test ("parsing " ++ eventName) <|
|
||||
\() ->
|
||||
let
|
||||
node =
|
||||
button [ eventAttribute ] []
|
||||
|
||||
facts =
|
||||
{ decodedFacts
|
||||
| events = Dict.fromList [ ( eventName, eventDecoder (eventHandler eventName node) ) ]
|
||||
}
|
||||
|
||||
expected =
|
||||
{ decodedNode | tag = "button", facts = facts }
|
||||
in
|
||||
node
|
||||
|> fromHtml
|
||||
|> Expect.equal (Ok (NodeEntry expected))
|
||||
19
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/tests/elm-package.json
vendored
Normal file
19
part9/tests/elm-stuff/packages/eeue56/elm-html-in-elm/5.2.0/tests/elm-package.json
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"summary": "Test Suites",
|
||||
"repository": "https://github.com/eeue56/elm-html-in-elm.git",
|
||||
"license": "BSD3",
|
||||
"source-directories": [
|
||||
"../src",
|
||||
"."
|
||||
],
|
||||
"exposed-modules": [],
|
||||
"native-modules": true,
|
||||
"dependencies": {
|
||||
"elm-community/elm-test": "4.0.0 <= v < 5.0.0",
|
||||
"elm-lang/core": "5.0.0 <= v < 6.0.0",
|
||||
"elm-lang/html": "2.0.0 <= v < 3.0.0",
|
||||
"elm-lang/svg": "2.0.0 <= v < 3.0.0"
|
||||
},
|
||||
"elm-version": "0.18.0 <= v < 0.19.0"
|
||||
}
|
||||
4
part9/tests/elm-stuff/packages/eeue56/elm-html-query/3.0.0/.gitignore
vendored
Normal file
4
part9/tests/elm-stuff/packages/eeue56/elm-html-query/3.0.0/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# elm-package generated files
|
||||
elm-stuff/
|
||||
# elm-repl generated files
|
||||
repl-temp-*
|
||||
29
part9/tests/elm-stuff/packages/eeue56/elm-html-query/3.0.0/LICENSE
vendored
Normal file
29
part9/tests/elm-stuff/packages/eeue56/elm-html-query/3.0.0/LICENSE
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2016, Noah
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
3
part9/tests/elm-stuff/packages/eeue56/elm-html-query/3.0.0/README.md
vendored
Normal file
3
part9/tests/elm-stuff/packages/eeue56/elm-html-query/3.0.0/README.md
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# elm-html-query
|
||||
|
||||
Query things using a [ElmHtml](http://package.elm-lang.org/packages/eeue56/elm-html-in-elm/latest) representation. This project is used alongside [elm-html-test](http://package.elm-lang.org/packages/eeue56/elm-html-test/latest) to implement Html-based tests in Elm.
|
||||
18
part9/tests/elm-stuff/packages/eeue56/elm-html-query/3.0.0/elm-package.json
vendored
Normal file
18
part9/tests/elm-stuff/packages/eeue56/elm-html-query/3.0.0/elm-package.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"version": "3.0.0",
|
||||
"summary": "Query for things inside ElmHtml",
|
||||
"repository": "https://github.com/eeue56/elm-html-query.git",
|
||||
"license": "BSD3",
|
||||
"source-directories": [
|
||||
"src"
|
||||
],
|
||||
"exposed-modules": [
|
||||
"ElmHtml.Query"
|
||||
],
|
||||
"dependencies": {
|
||||
"eeue56/elm-html-in-elm": "5.0.0 <= v < 6.0.0",
|
||||
"elm-lang/core": "5.0.0 <= v < 6.0.0",
|
||||
"elm-lang/html": "2.0.0 <= v < 3.0.0"
|
||||
},
|
||||
"elm-version": "0.18.0 <= v < 0.19.0"
|
||||
}
|
||||
350
part9/tests/elm-stuff/packages/eeue56/elm-html-query/3.0.0/src/ElmHtml/Query.elm
vendored
Normal file
350
part9/tests/elm-stuff/packages/eeue56/elm-html-query/3.0.0/src/ElmHtml/Query.elm
vendored
Normal file
@@ -0,0 +1,350 @@
|
||||
module ElmHtml.Query
|
||||
exposing
|
||||
( Selector(..)
|
||||
, query
|
||||
, queryAll
|
||||
, queryInNode
|
||||
, queryChildren
|
||||
, queryChildrenAll
|
||||
, queryById
|
||||
, queryByClassName
|
||||
, queryByClassList
|
||||
, queryByStyle
|
||||
, queryByTagName
|
||||
, queryByAttribute
|
||||
, queryByBoolAttribute
|
||||
, getChildren
|
||||
)
|
||||
|
||||
{-|
|
||||
Query things using ElmHtml
|
||||
|
||||
@docs Selector
|
||||
@docs query, queryAll, queryChildren, queryChildrenAll, queryInNode
|
||||
@docs queryById, queryByClassName, queryByClassList, queryByStyle, queryByTagName, queryByAttribute, queryByBoolAttribute
|
||||
@docs getChildren
|
||||
-}
|
||||
|
||||
import Dict
|
||||
import String
|
||||
import ElmHtml.InternalTypes exposing (..)
|
||||
|
||||
|
||||
{-| Selectors to query a Html element
|
||||
- Id, classname, classlist, tag are all what you'd expect
|
||||
- Attribute and bool attribute are attributes
|
||||
- ConainsText just searches inside for the given text
|
||||
-}
|
||||
type Selector
|
||||
= Id String
|
||||
| ClassName String
|
||||
| ClassList (List String)
|
||||
| Tag String
|
||||
| Attribute String String
|
||||
| BoolAttribute String Bool
|
||||
| Style (List ( String, String ))
|
||||
| ContainsText String
|
||||
| Multiple (List Selector)
|
||||
|
||||
|
||||
{-| Query for a node with a given tag in a Html element
|
||||
-}
|
||||
queryByTagName : String -> ElmHtml msg -> List (ElmHtml msg)
|
||||
queryByTagName tagname =
|
||||
query (Tag tagname)
|
||||
|
||||
|
||||
{-| Query for a node with a given id in a Html element
|
||||
-}
|
||||
queryById : String -> ElmHtml msg -> List (ElmHtml msg)
|
||||
queryById id =
|
||||
query (Id id)
|
||||
|
||||
|
||||
{-| Query for a node with a given classname in a Html element
|
||||
-}
|
||||
queryByClassName : String -> ElmHtml msg -> List (ElmHtml msg)
|
||||
queryByClassName classname =
|
||||
query (ClassName classname)
|
||||
|
||||
|
||||
{-| Query for a node with all the given classnames in a Html element
|
||||
-}
|
||||
queryByClassList : List String -> ElmHtml msg -> List (ElmHtml msg)
|
||||
queryByClassList classList =
|
||||
query (ClassList classList)
|
||||
|
||||
|
||||
{-| Query for a node with the given style in a Html element
|
||||
-}
|
||||
queryByStyle : List ( String, String ) -> ElmHtml msg -> List (ElmHtml msg)
|
||||
queryByStyle style =
|
||||
query (Style style)
|
||||
|
||||
|
||||
{-| Query for a node with a given attribute in a Html element
|
||||
-}
|
||||
queryByAttribute : String -> String -> ElmHtml msg -> List (ElmHtml msg)
|
||||
queryByAttribute key value =
|
||||
query (Attribute key value)
|
||||
|
||||
|
||||
{-| Query for a node with a given attribute in a Html element
|
||||
-}
|
||||
queryByBoolAttribute : String -> Bool -> ElmHtml msg -> List (ElmHtml msg)
|
||||
queryByBoolAttribute key value =
|
||||
query (BoolAttribute key value)
|
||||
|
||||
|
||||
{-| Query an ElmHtml element using a selector, searching all children.
|
||||
-}
|
||||
query : Selector -> ElmHtml msg -> List (ElmHtml msg)
|
||||
query selector =
|
||||
queryInNode selector
|
||||
|
||||
|
||||
{-| Query an ElmHtml node using multiple selectors, considering both the node itself
|
||||
as well as all of its descendants.
|
||||
-}
|
||||
queryAll : List Selector -> ElmHtml msg -> List (ElmHtml msg)
|
||||
queryAll selectors =
|
||||
query (Multiple selectors)
|
||||
|
||||
|
||||
{-| Query an ElmHtml node using a selector, considering both the node itself
|
||||
as well as all of its descendants.
|
||||
-}
|
||||
queryInNode : Selector -> ElmHtml msg -> List (ElmHtml msg)
|
||||
queryInNode =
|
||||
queryInNodeHelp Nothing
|
||||
|
||||
|
||||
{-| Query an ElmHtml node using a selector, considering both the node itself
|
||||
as well as all of its descendants.
|
||||
-}
|
||||
queryChildren : Selector -> ElmHtml msg -> List (ElmHtml msg)
|
||||
queryChildren =
|
||||
queryInNodeHelp (Just 1)
|
||||
|
||||
|
||||
{-| Returns just the immediate children of an ElmHtml node
|
||||
-}
|
||||
getChildren : ElmHtml msg -> List (ElmHtml msg)
|
||||
getChildren elmHtml =
|
||||
case elmHtml of
|
||||
NodeEntry { children } ->
|
||||
children
|
||||
|
||||
_ ->
|
||||
[]
|
||||
|
||||
|
||||
{-| Query to ensure an ElmHtml node has all selectors given, without considering
|
||||
any descendants lower than its immediate children.
|
||||
-}
|
||||
queryChildrenAll : List Selector -> ElmHtml msg -> List (ElmHtml msg)
|
||||
queryChildrenAll selectors =
|
||||
queryInNodeHelp (Just 1) (Multiple selectors)
|
||||
|
||||
|
||||
queryInNodeHelp : Maybe Int -> Selector -> ElmHtml msg -> List (ElmHtml msg)
|
||||
queryInNodeHelp maxDescendantDepth selector node =
|
||||
case node of
|
||||
NodeEntry record ->
|
||||
let
|
||||
childEntries =
|
||||
descendInQuery maxDescendantDepth selector record.children
|
||||
in
|
||||
if predicateFromSelector selector node then
|
||||
node :: childEntries
|
||||
else
|
||||
childEntries
|
||||
|
||||
TextTag { text } ->
|
||||
case selector of
|
||||
ContainsText innerText ->
|
||||
if String.contains innerText text then
|
||||
[ node ]
|
||||
else
|
||||
[]
|
||||
|
||||
_ ->
|
||||
[]
|
||||
|
||||
MarkdownNode { facts, model } ->
|
||||
if predicateFromSelector selector node then
|
||||
[ node ]
|
||||
else
|
||||
[]
|
||||
|
||||
_ ->
|
||||
[]
|
||||
|
||||
|
||||
descendInQuery : Maybe Int -> Selector -> List (ElmHtml msg) -> List (ElmHtml msg)
|
||||
descendInQuery maxDescendantDepth selector children =
|
||||
case maxDescendantDepth of
|
||||
Nothing ->
|
||||
-- No maximum, so continue.
|
||||
List.concatMap
|
||||
(queryInNodeHelp Nothing selector)
|
||||
children
|
||||
|
||||
Just depth ->
|
||||
if depth > 0 then
|
||||
-- Continue with maximum depth reduced by 1.
|
||||
List.concatMap
|
||||
(queryInNodeHelp (Just (depth - 1)) selector)
|
||||
children
|
||||
else
|
||||
[]
|
||||
|
||||
|
||||
predicateFromSelector : Selector -> ElmHtml msg -> Bool
|
||||
predicateFromSelector selector html =
|
||||
case html of
|
||||
NodeEntry record ->
|
||||
record
|
||||
|> nodeRecordPredicate selector
|
||||
|
||||
MarkdownNode markdownModel ->
|
||||
markdownModel
|
||||
|> markdownPredicate selector
|
||||
|
||||
_ ->
|
||||
False
|
||||
|
||||
|
||||
hasAllSelectors : List Selector -> ElmHtml msg -> Bool
|
||||
hasAllSelectors selectors record =
|
||||
List.map predicateFromSelector selectors
|
||||
|> List.map (\selector -> selector record)
|
||||
|> List.all identity
|
||||
|
||||
|
||||
hasAttribute : String -> String -> Facts msg -> Bool
|
||||
hasAttribute attribute query facts =
|
||||
case Dict.get attribute facts.stringAttributes of
|
||||
Just id ->
|
||||
id == query
|
||||
|
||||
Nothing ->
|
||||
False
|
||||
|
||||
|
||||
hasBoolAttribute : String -> Bool -> Facts msg -> Bool
|
||||
hasBoolAttribute attribute value facts =
|
||||
case Dict.get attribute facts.boolAttributes of
|
||||
Just id ->
|
||||
id == value
|
||||
|
||||
Nothing ->
|
||||
False
|
||||
|
||||
|
||||
hasClass : String -> Facts msg -> Bool
|
||||
hasClass query facts =
|
||||
List.member query (classnames facts)
|
||||
|
||||
|
||||
hasClasses : List String -> Facts msg -> Bool
|
||||
hasClasses classList facts =
|
||||
containsAll classList (classnames facts)
|
||||
|
||||
|
||||
hasStyle : List ( String, String ) -> Facts msg -> Bool
|
||||
hasStyle style facts =
|
||||
containsAll style (Dict.toList facts.styles)
|
||||
|
||||
|
||||
classnames : Facts msg -> List String
|
||||
classnames facts =
|
||||
Dict.get "className" facts.stringAttributes
|
||||
|> Maybe.withDefault ""
|
||||
|> String.split " "
|
||||
|
||||
|
||||
containsAll : List a -> List a -> Bool
|
||||
containsAll a b =
|
||||
b
|
||||
|> List.foldl (\i acc -> List.filter ((/=) i) acc) a
|
||||
|> List.isEmpty
|
||||
|
||||
|
||||
nodeRecordPredicate : Selector -> (NodeRecord msg -> Bool)
|
||||
nodeRecordPredicate selector =
|
||||
case selector of
|
||||
Id id ->
|
||||
.facts
|
||||
>> hasAttribute "id" id
|
||||
|
||||
ClassName classname ->
|
||||
.facts
|
||||
>> hasClass classname
|
||||
|
||||
ClassList classList ->
|
||||
.facts
|
||||
>> hasClasses classList
|
||||
|
||||
Tag tag ->
|
||||
.tag
|
||||
>> (==) tag
|
||||
|
||||
Attribute key value ->
|
||||
.facts
|
||||
>> hasAttribute key value
|
||||
|
||||
BoolAttribute key value ->
|
||||
.facts
|
||||
>> hasBoolAttribute key value
|
||||
|
||||
Style style ->
|
||||
.facts
|
||||
>> hasStyle style
|
||||
|
||||
ContainsText text ->
|
||||
always False
|
||||
|
||||
Multiple selectors ->
|
||||
NodeEntry
|
||||
>> hasAllSelectors selectors
|
||||
|
||||
|
||||
markdownPredicate : Selector -> (MarkdownNodeRecord msg -> Bool)
|
||||
markdownPredicate selector =
|
||||
case selector of
|
||||
Id id ->
|
||||
.facts
|
||||
>> hasAttribute "id" id
|
||||
|
||||
ClassName classname ->
|
||||
.facts
|
||||
>> hasClass classname
|
||||
|
||||
ClassList classList ->
|
||||
.facts
|
||||
>> hasClasses classList
|
||||
|
||||
Tag tag ->
|
||||
always False
|
||||
|
||||
Attribute key value ->
|
||||
.facts
|
||||
>> hasAttribute key value
|
||||
|
||||
BoolAttribute key value ->
|
||||
.facts
|
||||
>> hasBoolAttribute key value
|
||||
|
||||
Style style ->
|
||||
.facts
|
||||
>> hasStyle style
|
||||
|
||||
ContainsText text ->
|
||||
.model
|
||||
>> .markdown
|
||||
>> String.contains text
|
||||
|
||||
Multiple selectors ->
|
||||
MarkdownNode
|
||||
>> hasAllSelectors selectors
|
||||
4
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/.gitignore
vendored
Normal file
4
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# elm-package generated files
|
||||
elm-stuff/
|
||||
# elm-repl generated files
|
||||
repl-temp-*
|
||||
31
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/.travis.yml
vendored
Normal file
31
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/.travis.yml
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
sudo: false
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- tests/elm-stuff/build-artifacts
|
||||
|
||||
os:
|
||||
- osx
|
||||
- linux
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- ELM_VERSION=0.18 TARGET_NODE_VERSION=node
|
||||
- ELM_VERSION=0.18 TARGET_NODE_VERSION=4.2
|
||||
|
||||
before_install:
|
||||
- if [ ${TRAVIS_OS_NAME} == "osx" ];
|
||||
then brew update; brew install nvm; mkdir ~/.nvm; export NVM_DIR=~/.nvm; source $(brew --prefix nvm)/nvm.sh;
|
||||
fi
|
||||
|
||||
install:
|
||||
- nvm install $TARGET_NODE_VERSION
|
||||
- nvm use $TARGET_NODE_VERSION
|
||||
- node --version
|
||||
- npm --version
|
||||
- npm install -g elm@$ELM_VERSION
|
||||
- npm install -g elm-test@beta
|
||||
|
||||
|
||||
script:
|
||||
- elm-test
|
||||
29
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/LICENSE
vendored
Normal file
29
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/LICENSE
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2016, Noah Hall, Richard Feldman
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
131
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/README.md
vendored
Normal file
131
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/README.md
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
# elm-html-test
|
||||
|
||||
Test views by writing expectations about `Html` values. [](https://travis-ci.org/eeue56/elm-html-test)
|
||||
|
||||
```elm
|
||||
import Html
|
||||
import Html.Attributes exposing (class)
|
||||
import Test exposing (test)
|
||||
import Test.Html.Query as Query
|
||||
import Test.Html.Selector exposing (text, tag)
|
||||
|
||||
|
||||
test "Button has the expected text" <|
|
||||
\() ->
|
||||
Html.div [ class "container" ]
|
||||
[ Html.button [] [ Html.text "I'm a button!" ] ]
|
||||
|> Query.fromHtml
|
||||
|> Query.find [ tag "button" ]
|
||||
|> Query.has [ text "I'm a button!" ]
|
||||
```
|
||||
|
||||
These tests are designed to be written in a pipeline like this:
|
||||
|
||||
1. Call [`Query.fromHtml`](http://package.elm-lang.org/packages/eeue56/elm-html-test/latest/Test-Html-Query#fromHtml) on your [`Html`](http://package.elm-lang.org/packages/elm-lang/html/latest/Html#Html) to begin querying it.
|
||||
2. Use queries like [`Query.find`](http://package.elm-lang.org/packages/eeue56/elm-html-test/latest/Test-Html-Query#find), [`Query.findAll`](http://package.elm-lang.org/packages/eeue56/elm-html-test/latest/Test-Html-Query#findAll), and [`Query.children`](http://package.elm-lang.org/packages/eeue56/elm-html-test/latest/Test-Html-Query#children) to find the elements to test.
|
||||
3. Create expectations using things like [`Query.has`](http://package.elm-lang.org/packages/eeue56/elm-html-test/latest/Test-Html-Query#has) and [`Query.count`](http://package.elm-lang.org/packages/eeue56/elm-html-test/latest/Test-Html-Query#count).
|
||||
|
||||
These are normal expectations, so you can use them with [`fuzz`](http://package.elm-lang.org/packages/elm-community/elm-test/latest/Test#fuzz) just as easily as with [`test`](http://package.elm-lang.org/packages/elm-community/elm-test/3.1.0/Test#test)!
|
||||
|
||||
## Querying
|
||||
|
||||
Queries come in two flavors: [`Single`](http://package.elm-lang.org/packages/eeue56/elm-html-test/latest/Test-Html-Query#Single) and [`Multiple`](http://package.elm-lang.org/packages/eeue56/elm-html-test/latest/Test-Html-Query#Multiple).
|
||||
|
||||
This is because some queries are expected to return a single result, whereas
|
||||
others may return multiple results.
|
||||
|
||||
If a `Single` query finds exactly one result, it will succeed and continue with
|
||||
any further querying or expectations. If it finds zero results, or more than one,
|
||||
the test will fail.
|
||||
|
||||
Since other querying and expectation functions are written in terms of `Single`
|
||||
and `Multiple`, the compiler can help make sure queries are connected as
|
||||
expected. For example, [`count`](http://package.elm-lang.org/packages/eeue56/elm-html-test/latest/Test-Html-Query#count) accepts a `Multiple`, because counting a single element does not make much sense!
|
||||
|
||||
If you have a `Multiple` and want to use an expectation that works on a `Single`,
|
||||
such as [`Query.has`](http://package.elm-lang.org/packages/eeue56/elm-html-test/latest/Test-Html-Query#has), you can use [`Query.each`](http://package.elm-lang.org/packages/eeue56/elm-html-test/latest/Test-Html-Query#each) to run the expectation on each of the elements in the `Multiple`.
|
||||
|
||||
## Selecting elements by `Html.Attribute msg`
|
||||
|
||||
Ordinary `Html.Attribute msg` values can be used to select elements using
|
||||
`Test.Html.Selector.attribute`. It is important when using this selector to
|
||||
understand its behavior.
|
||||
|
||||
- `Html.Attributes.class` and `Html.Attributes.classList` will work the same as
|
||||
[`Test.Html.Selector.classes`](http://package.elm-lang.org/packages/eeue56/elm-html-test/latest/Test-Html-Selector#classes),
|
||||
matching any element with at least the given classes. This behavior echoes
|
||||
that of `element.querySelectorAll('.my-class')` from JavaScript, where any
|
||||
element with at least `.my-class` will match the query.
|
||||
|
||||
- `Html.Attributes.style` will work the same way as
|
||||
[`Test.Html.Selector.styles`](http://package.elm-lang.org/packages/eeue56/elm-html-test/latest/Test-Html-Selector#styles),
|
||||
matching any element with at least the given style properties.
|
||||
|
||||
- Any other `String` attributes and properties like `title`, or `Bool`
|
||||
attributes like `disabled` will match elements with the exact value for those
|
||||
attributes.
|
||||
|
||||
- Any attributes from `Html.Events`, or attributes with values that have types
|
||||
other than `String` or `Bool` will not match anything.
|
||||
|
||||
The example below demonstrates usage
|
||||
|
||||
```elm
|
||||
import Html
|
||||
import Html.Attributes as Attr
|
||||
import Test exposing (test, describe)
|
||||
import Test.Html.Query as Query
|
||||
import Test.Html.Selector exposing (attribute, text)
|
||||
|
||||
tests =
|
||||
describe "attributes"
|
||||
[ test "the welcome <h1> says hello!" <|
|
||||
\() ->
|
||||
Html.div [] [ Html.h1 [ Attr.title "greeting" ] [ Html.text "Hello!" ] ]
|
||||
|> Query.fromHtml
|
||||
|> Query.find [ attribute <| Attr.title "greeting" ]
|
||||
|> Query.has [ text "Hello!" ]
|
||||
, test "the .Hello.World div has the class Hello" <|
|
||||
\() ->
|
||||
Html.div
|
||||
[ Attr.classList
|
||||
[ ( True, "Hello" )
|
||||
, ( True, "World" )
|
||||
]
|
||||
]
|
||||
|> Query.fromHtml
|
||||
|> Query.find
|
||||
[ attribute <|
|
||||
Attr.classList [ ( True, Hello ) ]
|
||||
]
|
||||
, test "the header is red" <|
|
||||
\() ->
|
||||
Html.header
|
||||
[ Attr.style
|
||||
[ ( "backround-color", "red" )
|
||||
, ( "color", "yellow" )
|
||||
]
|
||||
]
|
||||
|> Query.fromHtml
|
||||
|> Query.find
|
||||
[ attribute <|
|
||||
Attr.style [ ( "backround-color", "red" ) ]
|
||||
]
|
||||
]
|
||||
```
|
||||
|
||||
|
||||
## Releases
|
||||
| Version | Notes |
|
||||
| ------- | ----- |
|
||||
| [**5.1.2**](https://github.com/eeue56/elm-html-test/tree/5.1.2) | Fix bug with mapped and lazy views
|
||||
| [**5.1.1**](https://github.com/eeue56/elm-html-test/tree/5.1.1) | Fix children
|
||||
| [**5.1.0**](https://github.com/eeue56/elm-html-test/tree/5.1.0) | Add filtermap
|
||||
| [**5.0.1**](https://github.com/eeue56/elm-html-test/tree/5.0.1) | Fix bug with lazy views
|
||||
| [**5.0.0**](https://github.com/eeue56/elm-html-test/tree/5.0.0) | Allow querying by attributes
|
||||
| [**4.1.0**](https://github.com/eeue56/elm-html-test/tree/4.1.0) | Query styles
|
||||
| [**4.0.0**](https://github.com/eeue56/elm-html-test/tree/4.0.0) | Allow custom events
|
||||
| [**3.0.0**](https://github.com/eeue56/elm-html-test/tree/3.0.0) | Allow events to be testable
|
||||
| [**2.0.0**](https://github.com/eeue56/elm-html-test/tree/2.0.0) | Better support for events by @rogeriochaves
|
||||
| [**1.1.0**](https://github.com/eeue56/elm-html-test/tree/1.1.0) | Support for events by @rogeriochaves
|
||||
| [**1.0.0**](https://github.com/eeue56/elm-html-test/tree/1.0.0) | Initial release
|
||||
23
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/elm-package.json
vendored
Normal file
23
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/elm-package.json
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"version": "5.1.2",
|
||||
"summary": "Write tests for your Html.",
|
||||
"repository": "https://github.com/eeue56/elm-html-test.git",
|
||||
"license": "BSD3",
|
||||
"source-directories": [
|
||||
"src"
|
||||
],
|
||||
"exposed-modules": [
|
||||
"Test.Html.Selector",
|
||||
"Test.Html.Query",
|
||||
"Test.Html.Event"
|
||||
],
|
||||
"native-modules": true,
|
||||
"dependencies": {
|
||||
"eeue56/elm-html-in-elm": "5.1.0 <= v < 6.0.0",
|
||||
"eeue56/elm-html-query": "3.0.0 <= v < 4.0.0",
|
||||
"elm-community/elm-test": "4.0.0 <= v < 5.0.0",
|
||||
"elm-lang/core": "5.0.0 <= v < 6.0.0",
|
||||
"elm-lang/html": "2.0.0 <= v < 3.0.0"
|
||||
},
|
||||
"elm-version": "0.18.0 <= v < 0.19.0"
|
||||
}
|
||||
46
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/examples/.travis.yml
vendored
Normal file
46
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/examples/.travis.yml
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
sudo: false
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- test/elm-stuff/build-artifacts
|
||||
- sysconfcpus
|
||||
|
||||
os:
|
||||
- osx
|
||||
- linux
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- ELM_VERSION=0.18.0 TARGET_NODE_VERSION=node
|
||||
- ELM_VERSION=0.18.0 TARGET_NODE_VERSION=4.0
|
||||
|
||||
before_install:
|
||||
- if [ ${TRAVIS_OS_NAME} == "osx" ];
|
||||
then brew update; brew install nvm; mkdir ~/.nvm; export NVM_DIR=~/.nvm; source $(brew --prefix nvm)/nvm.sh;
|
||||
fi
|
||||
- echo -e "Host github.com\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
|
||||
- | # epic build time improvement - see https://github.com/elm-lang/elm-compiler/issues/1473#issuecomment-245704142
|
||||
if [ ! -d sysconfcpus/bin ];
|
||||
then
|
||||
git clone https://github.com/obmarg/libsysconfcpus.git;
|
||||
cd libsysconfcpus;
|
||||
./configure --prefix=$TRAVIS_BUILD_DIR/sysconfcpus;
|
||||
make && make install;
|
||||
cd ..;
|
||||
fi
|
||||
|
||||
install:
|
||||
- nvm install $TARGET_NODE_VERSION
|
||||
- nvm use $TARGET_NODE_VERSION
|
||||
- node --version
|
||||
- npm --version
|
||||
- cd tests
|
||||
- npm install -g elm@$ELM_VERSION elm-test
|
||||
- mv $(npm config get prefix)/bin/elm-make $(npm config get prefix)/bin/elm-make-old
|
||||
- printf '%s\n\n' '#!/bin/bash' 'echo "Running elm-make with sysconfcpus -n 2"' '$TRAVIS_BUILD_DIR/sysconfcpus/bin/sysconfcpus -n 2 elm-make-old "$@"' > $(npm config get prefix)/bin/elm-make
|
||||
- chmod +x $(npm config get prefix)/bin/elm-make
|
||||
- npm install
|
||||
- elm package install --yes
|
||||
|
||||
script:
|
||||
- elm-test
|
||||
57
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/examples/ExampleApp.elm
vendored
Normal file
57
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/examples/ExampleApp.elm
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
module ExampleApp exposing (..)
|
||||
|
||||
import Html exposing (..)
|
||||
import Html.Attributes exposing (..)
|
||||
import Html.Events exposing (onClick)
|
||||
import Html.Keyed as Keyed
|
||||
import Html.Lazy as Lazy
|
||||
|
||||
|
||||
type alias Model =
|
||||
()
|
||||
|
||||
|
||||
exampleModel : Model
|
||||
exampleModel =
|
||||
()
|
||||
|
||||
|
||||
type Msg
|
||||
= GoToHome
|
||||
| GoToExamples
|
||||
|
||||
|
||||
view : Model -> Html Msg
|
||||
view model =
|
||||
div [ class "container" ]
|
||||
[ header [ class "funky themed", id "heading" ]
|
||||
[ a [ href "http://elm-lang.org", onClick GoToHome ] [ text "home" ]
|
||||
, a [ href "http://elm-lang.org/examples", onClick GoToExamples ] [ text "examples" ]
|
||||
, a [ href "http://elm-lang.org/docs" ] [ text "docs" ]
|
||||
]
|
||||
, section [ class "funky themed", id "section" ]
|
||||
[ someList ]
|
||||
, footer [] [ text "this is the footer" ]
|
||||
]
|
||||
|
||||
|
||||
someList : Html Msg
|
||||
someList =
|
||||
Keyed.ul [ class "some-list" ]
|
||||
[ ( "1"
|
||||
, Lazy.lazy (\_ -> li [ class "list-item themed" ] [ text "first item" ])
|
||||
Nothing
|
||||
)
|
||||
, ( "2"
|
||||
, Lazy.lazy (\_ -> li [ class "list-item themed" ] [ text "second item" ])
|
||||
Nothing
|
||||
)
|
||||
, ( "3"
|
||||
, Lazy.lazy (\_ -> li [ class "list-item themed selected" ] [ text "third item" ])
|
||||
Nothing
|
||||
)
|
||||
, ( "4"
|
||||
, Lazy.lazy (\_ -> li [ class "list-item themed" ] [ text "fourth item" ])
|
||||
Nothing
|
||||
)
|
||||
]
|
||||
117
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/examples/FailingTests.elm
vendored
Normal file
117
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/examples/FailingTests.elm
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
port module Main exposing (..)
|
||||
|
||||
import ExampleApp exposing (Msg(..), exampleModel, view)
|
||||
import Expect
|
||||
import Json.Encode exposing (Value)
|
||||
import Test exposing (..)
|
||||
import Test.Html.Event as Event
|
||||
import Test.Html.Query as Query
|
||||
import Test.Html.Selector exposing (..)
|
||||
import Test.Runner.Node exposing (TestProgram, run)
|
||||
|
||||
|
||||
main : TestProgram
|
||||
main =
|
||||
[ testView
|
||||
]
|
||||
|> Test.concat
|
||||
|> run emit
|
||||
|
||||
|
||||
port emit : ( String, Value ) -> Cmd msg
|
||||
|
||||
|
||||
testView : Test
|
||||
testView =
|
||||
let
|
||||
output =
|
||||
view exampleModel
|
||||
|> Query.fromHtml
|
||||
in
|
||||
describe "view exampleModel"
|
||||
[ test "expect 4x <li> somewhere on the page" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.findAll [ tag "li" ]
|
||||
|> Query.count (Expect.equal 4)
|
||||
, test "expect 4x <li> inside a <ul>" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.find [ tag "ul" ]
|
||||
|> Query.findAll [ tag "li" ]
|
||||
|> Query.count (Expect.equal 4)
|
||||
, test "(this should fail) expect header to have 4 links in it, even though it has 3" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.find [ id "heading" ]
|
||||
|> Query.findAll [ tag "a" ]
|
||||
|> Query.count (Expect.equal 4)
|
||||
, test "(this should fail) expect header to have one link in it, even though it has 3" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.find [ id "heading" ]
|
||||
|> Query.find [ tag "a" ]
|
||||
|> Query.has [ tag "a" ]
|
||||
, test "(this should fail) expect header to have one <img> in it, even though it has none" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.find [ id "heading" ]
|
||||
|> Query.find [ tag "img" ]
|
||||
|> Query.has [ tag "img" ]
|
||||
, test "(this should fail) expect footer to have a child" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.find [ tag "footer" ]
|
||||
|> Query.children []
|
||||
|> Query.each (Query.has [ tag "catapult" ])
|
||||
, test "(this should fail) expect footer's nonexistant child to be a catapult" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.find [ tag "footer" ]
|
||||
|> Query.children []
|
||||
|> Query.first
|
||||
|> Query.has [ tag "catapult" ]
|
||||
, test "expect footer to have footer text" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.find [ tag "footer" ]
|
||||
|> Query.has [ tag "footer", text "this is the footer" ]
|
||||
, test "(this should fail) expect footer to have text it doesn't have" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.find [ tag "footer" ]
|
||||
|> Query.has [ tag "footer", text "this is SPARTA!!!" ]
|
||||
, test "expect each <li> to have classes list-item and themed" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.find [ tag "ul" ]
|
||||
|> Query.findAll [ tag "li" ]
|
||||
|> Query.each (Query.has [ classes [ "list-item", "themed" ] ])
|
||||
, test "expect first a to send GoToHome onClick" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.findAll [ tag "a" ]
|
||||
|> Query.first
|
||||
|> Events.simulate Click
|
||||
|> Expect.equal (Ok GoToHome)
|
||||
, test "(this should fail) expect first a to return GoToExamples on click, even though it returns GoToHome" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.findAll [ tag "a" ]
|
||||
|> Query.first
|
||||
|> Events.simulate Click
|
||||
|> Expect.equal (Ok GoToExamples)
|
||||
, test "(this should fail) expect first a to return a msg for a blur event, even though it doesn't have one" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.findAll [ tag "a" ]
|
||||
|> Query.first
|
||||
|> Events.simulate Blur
|
||||
|> Expect.equal (Ok GoToHome)
|
||||
, test "(this should fail) expect text to return a msg for click, even though it is a text" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.find [ text "home" ]
|
||||
|> Events.simulate Click
|
||||
|> Expect.equal (Ok GoToHome)
|
||||
]
|
||||
22
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/examples/elm-package.json
vendored
Normal file
22
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/examples/elm-package.json
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"summary": "helpful summary of your project, less than 80 characters",
|
||||
"repository": "https://github.com/eeue56/elm-html-test.git",
|
||||
"license": "BSD3",
|
||||
"source-directories": [
|
||||
".",
|
||||
"../src"
|
||||
],
|
||||
"exposed-modules": [],
|
||||
"native-modules": true,
|
||||
"dependencies": {
|
||||
"eeue56/elm-html-in-elm": "3.0.0 <= v < 4.0.0",
|
||||
"eeue56/elm-html-query": "1.1.0 <= v < 2.0.0",
|
||||
"elm-community/elm-test": "3.1.0 <= v < 4.0.0",
|
||||
"elm-lang/core": "5.0.0 <= v < 6.0.0",
|
||||
"elm-lang/html": "2.0.0 <= v < 3.0.0",
|
||||
"rtfeldman/html-test-runner": "2.0.0 <= v < 3.0.0",
|
||||
"rtfeldman/node-test-runner": "3.0.0 <= v < 4.0.0"
|
||||
},
|
||||
"elm-version": "0.18.0 <= v < 0.19.0"
|
||||
}
|
||||
89
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/src/Html/Inert.elm
vendored
Normal file
89
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/src/Html/Inert.elm
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
module Html.Inert exposing (Node, parseAttribute, fromElmHtml, fromHtml, toElmHtml)
|
||||
|
||||
{-| Inert Html - that is, can't do anything with events.
|
||||
-}
|
||||
|
||||
import ElmHtml.InternalTypes exposing (ElmHtml(..), EventHandler, Facts, Tagger, decodeElmHtml, decodeAttribute)
|
||||
import Html exposing (Html)
|
||||
import Json.Decode
|
||||
import Native.HtmlAsJson
|
||||
|
||||
|
||||
type Node msg
|
||||
= Node (ElmHtml msg)
|
||||
|
||||
|
||||
fromHtml : Html msg -> Node msg
|
||||
fromHtml html =
|
||||
case Json.Decode.decodeValue (decodeElmHtml taggedEventDecoder) (toJson html) of
|
||||
Ok elmHtml ->
|
||||
Node elmHtml
|
||||
|
||||
Err str ->
|
||||
Debug.crash ("Error internally processing HTML for testing - please report this error message as a bug: " ++ str)
|
||||
|
||||
|
||||
fromElmHtml : ElmHtml msg -> Node msg
|
||||
fromElmHtml =
|
||||
Node
|
||||
|
||||
|
||||
{-| Convert a Html node to a Json string
|
||||
-}
|
||||
toJson : Html a -> Json.Decode.Value
|
||||
toJson node =
|
||||
Native.HtmlAsJson.toJson node
|
||||
|
||||
|
||||
toElmHtml : Node msg -> ElmHtml msg
|
||||
toElmHtml (Node elmHtml) =
|
||||
elmHtml
|
||||
|
||||
|
||||
impossibleMessage : String
|
||||
impossibleMessage =
|
||||
"An Inert Node fired an event handler. This should never happen! Please report this bug."
|
||||
|
||||
|
||||
attributeToJson : Html.Attribute a -> Json.Decode.Value
|
||||
attributeToJson attribute =
|
||||
Native.HtmlAsJson.attributeToJson attribute
|
||||
|
||||
|
||||
parseAttribute : Html.Attribute a -> ElmHtml.InternalTypes.Attribute
|
||||
parseAttribute attr =
|
||||
case Json.Decode.decodeValue decodeAttribute (attributeToJson attr) of
|
||||
Ok parsedAttribute ->
|
||||
parsedAttribute
|
||||
|
||||
Err str ->
|
||||
Debug.crash ("Error internally processing Attribute for testing - please report this error message as a bug: " ++ str)
|
||||
|
||||
|
||||
{-| Gets the function out of a tagger
|
||||
-}
|
||||
taggerFunction : Tagger -> (a -> msg)
|
||||
taggerFunction tagger =
|
||||
Native.HtmlAsJson.taggerFunction tagger
|
||||
|
||||
|
||||
{-| Gets the decoder out of an EventHandler
|
||||
-}
|
||||
eventDecoder : EventHandler -> Json.Decode.Decoder msg
|
||||
eventDecoder eventHandler =
|
||||
Native.HtmlAsJson.eventDecoder eventHandler
|
||||
|
||||
|
||||
{-| Applies the taggers over the event handlers to have the complete event decoder
|
||||
-}
|
||||
taggedEventDecoder : List Tagger -> EventHandler -> Json.Decode.Decoder msg
|
||||
taggedEventDecoder taggers eventHandler =
|
||||
case taggers of
|
||||
[] ->
|
||||
eventDecoder eventHandler
|
||||
|
||||
[ tagger ] ->
|
||||
Json.Decode.map (taggerFunction tagger) (eventDecoder eventHandler)
|
||||
|
||||
tagger :: taggers ->
|
||||
Json.Decode.map (taggerFunction tagger) (taggedEventDecoder taggers eventHandler)
|
||||
32
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/src/Native/HtmlAsJson.js
vendored
Normal file
32
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/src/Native/HtmlAsJson.js
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
var _eeue56$elm_html_test$Native_HtmlAsJson = (function() {
|
||||
function forceThunks(vNode) {
|
||||
if (typeof vNode !== "undefined" && vNode.ctor === "_Tuple2" && !vNode.node) {
|
||||
vNode._1 = forceThunks(vNode._1);
|
||||
}
|
||||
if (typeof vNode !== 'undefined' && vNode.type === 'thunk' && !vNode.node) {
|
||||
vNode.node = vNode.thunk.apply(vNode.thunk, vNode.args);
|
||||
}
|
||||
if (typeof vNode !== 'undefined' && vNode.type === 'tagger') {
|
||||
vNode.node = forceThunks(vNode.node);
|
||||
}
|
||||
if (typeof vNode !== 'undefined' && typeof vNode.children !== 'undefined') {
|
||||
vNode.children = vNode.children.map(forceThunks);
|
||||
}
|
||||
return vNode;
|
||||
}
|
||||
|
||||
return {
|
||||
toJson: function(html) {
|
||||
return forceThunks(html);
|
||||
},
|
||||
eventDecoder: function (event) {
|
||||
return event.decoder;
|
||||
},
|
||||
taggerFunction: function (tagger) {
|
||||
return tagger;
|
||||
},
|
||||
attributeToJson: function(attribute) {
|
||||
return attribute;
|
||||
}
|
||||
};
|
||||
})();
|
||||
30
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/src/Test/Html/Descendant.elm
vendored
Normal file
30
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/src/Test/Html/Descendant.elm
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
module Test.Html.Descendant exposing (isDescendant)
|
||||
|
||||
import Html exposing (Html)
|
||||
import ElmHtml.InternalTypes exposing (ElmHtml(..))
|
||||
import Html.Inert exposing (fromHtml, toElmHtml)
|
||||
|
||||
|
||||
isDescendant : List (ElmHtml msg) -> ElmHtml msg -> Bool
|
||||
isDescendant html potentialDescendant =
|
||||
case html of
|
||||
[] ->
|
||||
False
|
||||
|
||||
current :: rest ->
|
||||
if current == potentialDescendant then
|
||||
True
|
||||
else
|
||||
isDescendant
|
||||
(prependChildren current rest)
|
||||
potentialDescendant
|
||||
|
||||
|
||||
prependChildren : ElmHtml msg -> List (ElmHtml msg) -> List (ElmHtml msg)
|
||||
prependChildren parentNode nodeList =
|
||||
case parentNode of
|
||||
NodeEntry { children } ->
|
||||
(List.concat [ children, nodeList ])
|
||||
|
||||
_ ->
|
||||
nodeList
|
||||
314
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/src/Test/Html/Event.elm
vendored
Normal file
314
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/src/Test/Html/Event.elm
vendored
Normal file
@@ -0,0 +1,314 @@
|
||||
module Test.Html.Event
|
||||
exposing
|
||||
( Event
|
||||
, simulate
|
||||
, expect
|
||||
, toResult
|
||||
, click
|
||||
, doubleClick
|
||||
, mouseDown
|
||||
, mouseUp
|
||||
, mouseEnter
|
||||
, mouseLeave
|
||||
, mouseOver
|
||||
, mouseOut
|
||||
, input
|
||||
, check
|
||||
, submit
|
||||
, blur
|
||||
, focus
|
||||
, custom
|
||||
)
|
||||
|
||||
{-| This module lets you simulate events on `Html` values and expect that
|
||||
they result in certain `Msg` values being sent to `update`.
|
||||
|
||||
|
||||
## Simulating Events
|
||||
|
||||
@docs Event, simulate, expect, toResult
|
||||
|
||||
|
||||
## Event Builders
|
||||
|
||||
@docs custom, click, doubleClick, mouseDown, mouseUp, mouseEnter, mouseLeave, mouseOver, mouseOut, input, check, submit, blur, focus
|
||||
|
||||
-}
|
||||
|
||||
import Dict
|
||||
import ElmHtml.InternalTypes exposing (ElmHtml, ElmHtml(..), Tagger)
|
||||
import Json.Decode as Decode exposing (Decoder)
|
||||
import Json.Encode as Encode exposing (Value)
|
||||
import Test.Html.Query as Query
|
||||
import Test.Html.Query.Internal as QueryInternal
|
||||
import Expect exposing (Expectation)
|
||||
|
||||
|
||||
{-| A simulated event.
|
||||
|
||||
See [`simulate`](#simulate).
|
||||
|
||||
-}
|
||||
type Event msg
|
||||
= Event ( String, Value ) (QueryInternal.Single msg)
|
||||
|
||||
|
||||
{-| Simulate an event on a node.
|
||||
|
||||
import Test.Html.Event as Event
|
||||
|
||||
type Msg
|
||||
= Change String
|
||||
|
||||
|
||||
test "Input produces expected Msg" <|
|
||||
\() ->
|
||||
Html.input [ onInput Change ] [ ]
|
||||
|> Query.fromHtml
|
||||
|> Event.simulate (Event.input "cats")
|
||||
|> Event.expect (Change "cats")
|
||||
|
||||
-}
|
||||
simulate : ( String, Value ) -> Query.Single msg -> Event msg
|
||||
simulate =
|
||||
Event
|
||||
|
||||
|
||||
{-| Passes if the given message is triggered by the simulated event.
|
||||
|
||||
import Test.Html.Event as Event
|
||||
|
||||
type Msg
|
||||
= Change String
|
||||
|
||||
|
||||
test "Input produces expected Msg" <|
|
||||
\() ->
|
||||
Html.input [ onInput Change ] [ ]
|
||||
|> Query.fromHtml
|
||||
|> Event.simulate (Event.input "cats")
|
||||
|> Event.expect (Change "cats")
|
||||
|
||||
-}
|
||||
expect : msg -> Event msg -> Expectation
|
||||
expect msg (Event event (QueryInternal.Single showTrace query)) =
|
||||
case toResult (Event event (QueryInternal.Single showTrace query)) of
|
||||
Err noEvent ->
|
||||
Expect.fail noEvent
|
||||
|> QueryInternal.failWithQuery showTrace "" query
|
||||
|
||||
Ok foundMsg ->
|
||||
foundMsg
|
||||
|> Expect.equal msg
|
||||
|> QueryInternal.failWithQuery showTrace ("Event.expectEvent: Expected the msg \x1B[32m" ++ toString msg ++ "\x1B[39m from the event \x1B[31m" ++ toString event ++ "\x1B[39m but could not find the event.") query
|
||||
|
||||
|
||||
{-| Returns a Result with the Msg produced by the event simulated on a node.
|
||||
Note that Event.expect gives nicer messages; this is generally more useful
|
||||
when testing that an event handler is *not* present.
|
||||
|
||||
import Test.Html.Event as Event
|
||||
|
||||
|
||||
test "Input produces expected Msg" <|
|
||||
\() ->
|
||||
Html.input [ onInput Change ] [ ]
|
||||
|> Query.fromHtml
|
||||
|> Event.simulate (Event.input "cats")
|
||||
|> Event.toResult
|
||||
|> Expect.equal (Ok (Change "cats"))
|
||||
|
||||
-}
|
||||
toResult : Event msg -> Result String msg
|
||||
toResult (Event ( eventName, jsEvent ) (QueryInternal.Single showTrace query)) =
|
||||
let
|
||||
node =
|
||||
QueryInternal.traverse query
|
||||
|> Result.andThen (QueryInternal.verifySingle eventName)
|
||||
|> Result.mapError (QueryInternal.queryErrorToString query)
|
||||
in
|
||||
case node of
|
||||
Err msg ->
|
||||
Err msg
|
||||
|
||||
Ok single ->
|
||||
findEvent eventName single
|
||||
|> Result.andThen (\foundEvent -> Decode.decodeValue foundEvent jsEvent)
|
||||
|
||||
|
||||
|
||||
-- EVENTS --
|
||||
|
||||
|
||||
{-| A [`click`](https://developer.mozilla.org/en-US/docs/Web/Events/click) event.
|
||||
-}
|
||||
click : ( String, Value )
|
||||
click =
|
||||
( "click", emptyObject )
|
||||
|
||||
|
||||
{-| A [`dblclick`](https://developer.mozilla.org/en-US/docs/Web/Events/dblclick) event.
|
||||
-}
|
||||
doubleClick : ( String, Value )
|
||||
doubleClick =
|
||||
( "dblclick", emptyObject )
|
||||
|
||||
|
||||
{-| A [`mousedown`](https://developer.mozilla.org/en-US/docs/Web/Events/mousedown) event.
|
||||
-}
|
||||
mouseDown : ( String, Value )
|
||||
mouseDown =
|
||||
( "mousedown", emptyObject )
|
||||
|
||||
|
||||
{-| A [`mouseup`](https://developer.mozilla.org/en-US/docs/Web/Events/mouseup) event.
|
||||
-}
|
||||
mouseUp : ( String, Value )
|
||||
mouseUp =
|
||||
( "mouseup", emptyObject )
|
||||
|
||||
|
||||
{-| A [`mouseenter`](https://developer.mozilla.org/en-US/docs/Web/Events/mouseenter) event.
|
||||
-}
|
||||
mouseEnter : ( String, Value )
|
||||
mouseEnter =
|
||||
( "mouseenter", emptyObject )
|
||||
|
||||
|
||||
{-| A [`mouseleave`](https://developer.mozilla.org/en-US/docs/Web/Events/mouseleave) event.
|
||||
-}
|
||||
mouseLeave : ( String, Value )
|
||||
mouseLeave =
|
||||
( "mouseleave", emptyObject )
|
||||
|
||||
|
||||
{-| A [`mouseover`](https://developer.mozilla.org/en-US/docs/Web/Events/mouseover) event.
|
||||
-}
|
||||
mouseOver : ( String, Value )
|
||||
mouseOver =
|
||||
( "mouseover", emptyObject )
|
||||
|
||||
|
||||
{-| A [`mouseout`](https://developer.mozilla.org/en-US/docs/Web/Events/mouseout) event.
|
||||
-}
|
||||
mouseOut : ( String, Value )
|
||||
mouseOut =
|
||||
( "mouseout", emptyObject )
|
||||
|
||||
|
||||
{-| An [`input`](https://developer.mozilla.org/en-US/docs/Web/Events/input) event.
|
||||
-}
|
||||
input : String -> ( String, Value )
|
||||
input value =
|
||||
( "input"
|
||||
, Encode.object
|
||||
[ ( "target"
|
||||
, Encode.object [ ( "value", Encode.string value ) ]
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
{-| A [`change`](https://developer.mozilla.org/en-US/docs/Web/Events/change) event
|
||||
where `event.target.checked` is set to the given `Bool` value.
|
||||
-}
|
||||
check : Bool -> ( String, Value )
|
||||
check checked =
|
||||
( "change"
|
||||
, Encode.object
|
||||
[ ( "target"
|
||||
, Encode.object [ ( "checked", Encode.bool checked ) ]
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
{-| A [`submit`](https://developer.mozilla.org/en-US/docs/Web/Events/submit) event.
|
||||
-}
|
||||
submit : ( String, Value )
|
||||
submit =
|
||||
( "submit", emptyObject )
|
||||
|
||||
|
||||
{-| A [`blur`](https://developer.mozilla.org/en-US/docs/Web/Events/blur) event.
|
||||
-}
|
||||
blur : ( String, Value )
|
||||
blur =
|
||||
( "blur", emptyObject )
|
||||
|
||||
|
||||
{-| A [`focus`](https://developer.mozilla.org/en-US/docs/Web/Events/focus) event.
|
||||
-}
|
||||
focus : ( String, Value )
|
||||
focus =
|
||||
( "focus", emptyObject )
|
||||
|
||||
|
||||
{-| Simulate a custom event. The `String` is the event name, and the `Value` is the event object
|
||||
the browser would send to the event listener callback.
|
||||
|
||||
import Test.Html.Event as Event
|
||||
import Json.Encode as Encode exposing (Value)
|
||||
|
||||
|
||||
type Msg
|
||||
= Change String
|
||||
|
||||
|
||||
test "Input produces expected Msg" <|
|
||||
\() ->
|
||||
let
|
||||
simulatedEventObject : Value
|
||||
simulatedEventObject =
|
||||
Encode.object
|
||||
[ ( "target"
|
||||
, Encode.object [ ( "value", Encode.string "cats" ) ]
|
||||
)
|
||||
]
|
||||
in
|
||||
Html.input [ onInput Change ] [ ]
|
||||
|> Query.fromHtml
|
||||
|> Event.simulate (Event.custom "input" simulatedEventObject)
|
||||
|> Event.expect (Change "cats")
|
||||
|
||||
-}
|
||||
custom : String -> Value -> ( String, Value )
|
||||
custom =
|
||||
(,)
|
||||
|
||||
|
||||
|
||||
-- INTERNAL --
|
||||
|
||||
|
||||
emptyObject : Value
|
||||
emptyObject =
|
||||
Encode.object []
|
||||
|
||||
|
||||
findEvent : String -> ElmHtml msg -> Result String (Decoder msg)
|
||||
findEvent eventName element =
|
||||
let
|
||||
elementOutput =
|
||||
QueryInternal.prettyPrint element
|
||||
|
||||
eventDecoder node =
|
||||
node.facts.events
|
||||
|> Dict.get eventName
|
||||
|> Result.fromMaybe ("Event.expectEvent: The event " ++ eventName ++ " does not exist on the found node.\n\n" ++ elementOutput)
|
||||
in
|
||||
case element of
|
||||
TextTag _ ->
|
||||
Err ("Found element is a text, which does not produce events, therefore could not simulate " ++ eventName ++ " on it. Text found: " ++ elementOutput)
|
||||
|
||||
NodeEntry node ->
|
||||
eventDecoder node
|
||||
|
||||
CustomNode node ->
|
||||
eventDecoder node
|
||||
|
||||
MarkdownNode node ->
|
||||
eventDecoder node
|
||||
|
||||
NoOp ->
|
||||
Err ("Unknown element found. Could not simulate " ++ eventName ++ " on it.")
|
||||
471
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/src/Test/Html/Query.elm
vendored
Normal file
471
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/src/Test/Html/Query.elm
vendored
Normal file
@@ -0,0 +1,471 @@
|
||||
module Test.Html.Query
|
||||
exposing
|
||||
( Multiple
|
||||
, Single
|
||||
, children
|
||||
, contains
|
||||
, count
|
||||
, each
|
||||
, find
|
||||
, findAll
|
||||
, first
|
||||
, fromHtml
|
||||
, has
|
||||
, hasNot
|
||||
, index
|
||||
, keep
|
||||
)
|
||||
|
||||
{-| Querying HTML structure.
|
||||
|
||||
@docs Single, Multiple, fromHtml
|
||||
|
||||
|
||||
## Querying
|
||||
|
||||
@docs find, findAll, children, first, index, keep
|
||||
|
||||
|
||||
## Expecting
|
||||
|
||||
@docs count, contains, has, hasNot, each
|
||||
|
||||
-}
|
||||
|
||||
import ElmHtml.InternalTypes exposing (ElmHtml)
|
||||
import Expect exposing (Expectation)
|
||||
import Html exposing (Html)
|
||||
import Html.Inert as Inert
|
||||
import Test.Html.Query.Internal as Internal exposing (QueryError(..), failWithQuery)
|
||||
import Test.Html.Selector.Internal as Selector exposing (Selector, selectorToString)
|
||||
|
||||
|
||||
{- DESIGN NOTES:
|
||||
|
||||
The reason for having `Query.index` and `Query.first` instead of doing them as
|
||||
selectors (which would let you do e.g. `Query.find [ first ]` to get the
|
||||
first child, instead of `Query.children [] |> Query.first` like you have to
|
||||
do now) is that it's not immediately obvious what a query like this would do:
|
||||
|
||||
Query.findAll [ first, tag "li" ]
|
||||
|
||||
Is that getting the first descendant, and then checking whether it's an <li>?
|
||||
Or is it finding the first <li> descendant? (Yes.) Also this is a findAll
|
||||
but it's only ever returning a single result despite being typed as a Multiple.
|
||||
|
||||
Arguably `id` could be treated the same way - since you *should* only have
|
||||
one id, *should* only ever return one result. However, in that case, it's
|
||||
possible that you have multiple IDs - and in that case you actually want the
|
||||
test to fail so you find out about the mistake!
|
||||
-}
|
||||
|
||||
|
||||
{-| A query that expects to find exactly one element.
|
||||
|
||||
Contrast with [`Multiple`](#Multiple).
|
||||
|
||||
-}
|
||||
type alias Single msg =
|
||||
Internal.Single msg
|
||||
|
||||
|
||||
{-| A query that may find any number of elements, including zero.
|
||||
|
||||
Contrast with [`Single`](#Single).
|
||||
|
||||
-}
|
||||
type alias Multiple msg =
|
||||
Internal.Multiple msg
|
||||
|
||||
|
||||
{-| Translate a `Html` value into a `Single` query. This is how queries
|
||||
typically begin.
|
||||
|
||||
import Html
|
||||
import Test.Html.Query as Query
|
||||
import Test exposing (test)
|
||||
import Test.Html.Selector exposing (text)
|
||||
|
||||
|
||||
test "Button has the expected text" <|
|
||||
\() ->
|
||||
Html.button [] [ Html.text "I'm a button!" ]
|
||||
|> Query.fromHtml
|
||||
|> Query.has [ text "I'm a button!" ]
|
||||
|
||||
-}
|
||||
fromHtml : Html msg -> Single msg
|
||||
fromHtml html =
|
||||
Internal.Query (Inert.fromHtml html) []
|
||||
|> Internal.Single True
|
||||
|
||||
|
||||
|
||||
-- TRAVERSAL --
|
||||
|
||||
|
||||
{-| Find the descendant elements which match all the given selectors.
|
||||
|
||||
import Html exposing (div, ul, li)
|
||||
import Html.Attributes exposing (class)
|
||||
import Test.Html.Query as Query
|
||||
import Test exposing (test)
|
||||
import Test.Html.Selector exposing (tag)
|
||||
import Expect
|
||||
|
||||
|
||||
test "The list has three items" <|
|
||||
\() ->
|
||||
div []
|
||||
[ ul [ class "items active" ]
|
||||
[ li [] [ text "first item" ]
|
||||
, li [] [ text "second item" ]
|
||||
, li [] [ text "third item" ]
|
||||
]
|
||||
]
|
||||
|> Query.fromHtml
|
||||
|> Query.findAll [ tag "li" ]
|
||||
|> Query.count (Expect.equal 3)
|
||||
|
||||
-}
|
||||
findAll : List Selector -> Single msg -> Multiple msg
|
||||
findAll selectors (Internal.Single showTrace query) =
|
||||
Internal.FindAll selectors
|
||||
|> Internal.prependSelector query
|
||||
|> Internal.Multiple showTrace
|
||||
|
||||
|
||||
{-| Find the descendant elements of the result of `findAll` which match all the given selectors.
|
||||
|
||||
import Html exposing (div, ul, li)
|
||||
import Html.Attributes exposing (class)
|
||||
import Test.Html.Query as Query
|
||||
import Test exposing (test)
|
||||
import Test.Html.Selector exposing (tag)
|
||||
import Expect
|
||||
|
||||
|
||||
test "The list has three items" <|
|
||||
\() ->
|
||||
div []
|
||||
[ ul [ class "items active" ]
|
||||
[ li [] [ a [] [ text "first item" ]]
|
||||
, li [] [ a [] [ text "second item" ]]
|
||||
, li [] [ a [] [ text "third item" ]]
|
||||
, li [] [ button [] [ text "button" ]]
|
||||
]
|
||||
]
|
||||
|> Query.fromHtml
|
||||
|> Query.findAll [ tag "li" ]
|
||||
|> Query.keep ( tag "a" )
|
||||
|> Expect.all
|
||||
[ Query.each (Query.has [ tag "a" ])
|
||||
, Query.first >> Query.has [ text "first item" ]
|
||||
]
|
||||
|
||||
-}
|
||||
keep : Selector -> Multiple msg -> Multiple msg
|
||||
keep selector (Internal.Multiple showTrace query) =
|
||||
Internal.FindAll [ selector ]
|
||||
|> Internal.prependSelector query
|
||||
|> Internal.Multiple showTrace
|
||||
|
||||
|
||||
{-| Return the matched element's immediate child elements.
|
||||
|
||||
import Html exposing (div, ul, li)
|
||||
import Html.Attributes exposing (class)
|
||||
import Test.Html.Query as Query
|
||||
import Test exposing (test)
|
||||
import Test.Html.Selector exposing (tag, classes)
|
||||
|
||||
|
||||
test "The <ul> only has <li> children" <|
|
||||
\() ->
|
||||
div []
|
||||
[ ul [ class "items active" ]
|
||||
[ li [ class "item"] [ text "first item" ]
|
||||
, li [ class "item selected"] [ text "second item" ]
|
||||
, li [ class "item"] [ text "third item" ]
|
||||
]
|
||||
]
|
||||
|> Query.fromHtml
|
||||
|> Query.find [ class "items" ]
|
||||
|> Query.children [ class "selected" ]
|
||||
|> Query.count (Expect.equal 1)
|
||||
|
||||
-}
|
||||
children : List Selector -> Single msg -> Multiple msg
|
||||
children selectors (Internal.Single showTrace query) =
|
||||
Internal.Children selectors
|
||||
|> Internal.prependSelector query
|
||||
|> Internal.Multiple showTrace
|
||||
|
||||
|
||||
{-| Find exactly one descendant element which matches all the given selectors.
|
||||
If no descendants match, or if more than one matches, the test will fail.
|
||||
|
||||
import Html exposing (div, ul, li)
|
||||
import Html.Attributes exposing (class)
|
||||
import Test.Html.Query as Query
|
||||
import Test exposing (test)
|
||||
import Test.Html.Selector exposing (tag, classes)
|
||||
|
||||
|
||||
test "The list has both the classes 'items' and 'active'" <|
|
||||
\() ->
|
||||
div []
|
||||
[ ul [ class "items active" ]
|
||||
[ li [] [ text "first item" ]
|
||||
, li [] [ text "second item" ]
|
||||
, li [] [ text "third item" ]
|
||||
]
|
||||
]
|
||||
|> Query.fromHtml
|
||||
|> Query.find [ tag "ul" ]
|
||||
|> Query.has [ classes [ "items", "active" ] ]
|
||||
|
||||
-}
|
||||
find : List Selector -> Single msg -> Single msg
|
||||
find selectors (Internal.Single showTrace query) =
|
||||
Internal.Find selectors
|
||||
|> Internal.prependSelector query
|
||||
|> Internal.Single showTrace
|
||||
|
||||
|
||||
{-| Return the first element in a match. If there were no matches, the test
|
||||
will fail.
|
||||
|
||||
`Query.first` is a shorthand for `Query.index 0` - they do the same thing.
|
||||
|
||||
import Html exposing (div, ul, li)
|
||||
import Html.Attributes exposing (class)
|
||||
import Test.Html.Query as Query
|
||||
import Test exposing (test)
|
||||
import Test.Html.Selector exposing (tag, classes)
|
||||
|
||||
|
||||
test "The first <li> is called 'first item'" <|
|
||||
\() ->
|
||||
div []
|
||||
[ ul [ class "items active" ]
|
||||
[ li [] [ text "first item" ]
|
||||
, li [] [ text "second item" ]
|
||||
, li [] [ text "third item" ]
|
||||
]
|
||||
]
|
||||
|> Query.fromHtml
|
||||
|> Query.findAll [ tag "li" ]
|
||||
|> Query.first
|
||||
|> Query.has [ text "first item" ]
|
||||
|
||||
-}
|
||||
first : Multiple msg -> Single msg
|
||||
first (Internal.Multiple showTrace query) =
|
||||
Internal.First
|
||||
|> Internal.prependSelector query
|
||||
|> Internal.Single showTrace
|
||||
|
||||
|
||||
{-| Return the element in a match at the given index. For example,
|
||||
`Query.index 0` would match the first element, and `Query.index 1` would match
|
||||
the second element.
|
||||
|
||||
You can pass negative numbers to "wrap around" - for example, `Query.index -1`
|
||||
will match the last element, and `Query.index -2` will match the second-to-last.
|
||||
|
||||
If the index falls outside the bounds of the match, the test will fail.
|
||||
|
||||
import Html exposing (div, ul, li)
|
||||
import Html.Attributes exposing (class)
|
||||
import Test.Html.Query as Query
|
||||
import Test exposing (test)
|
||||
import Test.Html.Selector exposing (tag, classes)
|
||||
|
||||
|
||||
test "The second <li> is called 'second item'" <|
|
||||
\() ->
|
||||
div []
|
||||
[ ul [ class "items active" ]
|
||||
[ li [] [ text "first item" ]
|
||||
, li [] [ text "second item" ]
|
||||
, li [] [ text "third item" ]
|
||||
]
|
||||
]
|
||||
|> Query.fromHtml
|
||||
|> Query.findAll [ tag "li" ]
|
||||
|> Query.index 1
|
||||
|> Query.has [ text "second item" ]
|
||||
|
||||
-}
|
||||
index : Int -> Multiple msg -> Single msg
|
||||
index position (Internal.Multiple showTrace query) =
|
||||
Internal.Index position
|
||||
|> Internal.prependSelector query
|
||||
|> Internal.Single showTrace
|
||||
|
||||
|
||||
|
||||
-- EXPECTATIONS --
|
||||
|
||||
|
||||
{-| Expect the number of elements matching the query fits the given expectation.
|
||||
|
||||
import Html exposing (div, ul, li)
|
||||
import Html.Attributes exposing (class)
|
||||
import Test.Html.Query as Query
|
||||
import Test exposing (test)
|
||||
import Test.Html.Selector exposing (tag)
|
||||
import Expect
|
||||
|
||||
|
||||
test "The list has three items" <|
|
||||
\() ->
|
||||
div []
|
||||
[ ul [ class "items active" ]
|
||||
[ li [] [ text "first item" ]
|
||||
, li [] [ text "second item" ]
|
||||
, li [] [ text "third item" ]
|
||||
]
|
||||
]
|
||||
|> Query.fromHtml
|
||||
|> Query.findAll [ tag "li" ]
|
||||
|> Query.count (Expect.equal 3)
|
||||
|
||||
-}
|
||||
count : (Int -> Expectation) -> Multiple msg -> Expectation
|
||||
count expect ((Internal.Multiple showTrace query) as multiple) =
|
||||
(List.length >> expect >> failWithQuery showTrace "Query.count" query)
|
||||
|> Internal.multipleToExpectation multiple
|
||||
|
||||
|
||||
{-| Expect the element to have at least one descendant matching
|
||||
|
||||
import Html exposing (div, ul, li)
|
||||
import Html.Attributes exposing (class)
|
||||
import Test.Html.Query as Query
|
||||
import Test exposing (test)
|
||||
import Test.Html.Selector exposing (tag, classes)
|
||||
|
||||
|
||||
test "The list has two li: one with the text \"third item\" and \
|
||||
another one with \"first item\"" <|
|
||||
\() ->
|
||||
div []
|
||||
[ ul [ class "items active" ]
|
||||
[ li [] [ text "first item" ]
|
||||
, li [] [ text "second item" ]
|
||||
, li [] [ text "third item" ]
|
||||
]
|
||||
]
|
||||
|> Query.fromHtml
|
||||
|> Query.contains
|
||||
[ li [] [ text "third item" ]
|
||||
, li [] [ text "first item" ]
|
||||
]
|
||||
|
||||
-}
|
||||
contains : List (Html msg) -> Single msg -> Expectation
|
||||
contains expectedHtml (Internal.Single showTrace query) =
|
||||
let
|
||||
expectedElmHtml =
|
||||
List.map htmlToElm expectedHtml
|
||||
in
|
||||
Internal.contains
|
||||
expectedElmHtml
|
||||
query
|
||||
|> failWithQuery showTrace "Query.contains" query
|
||||
|
||||
|
||||
htmlToElm : Html msg -> ElmHtml msg
|
||||
htmlToElm =
|
||||
Inert.fromHtml >> Inert.toElmHtml
|
||||
|
||||
|
||||
{-| Expect the element to match all of the given selectors.
|
||||
|
||||
import Html exposing (div, ul, li)
|
||||
import Html.Attributes exposing (class)
|
||||
import Test.Html.Query as Query
|
||||
import Test exposing (test)
|
||||
import Test.Html.Selector exposing (tag, classes)
|
||||
|
||||
|
||||
test "The list has both the classes 'items' and 'active'" <|
|
||||
\() ->
|
||||
div []
|
||||
[ ul [ class "items active" ]
|
||||
[ li [] [ text "first item" ]
|
||||
, li [] [ text "second item" ]
|
||||
, li [] [ text "third item" ]
|
||||
]
|
||||
]
|
||||
|> Query.fromHtml
|
||||
|> Query.find [ tag "ul" ]
|
||||
|> Query.has [ tag "ul", classes [ "items", "active" ] ]
|
||||
|
||||
-}
|
||||
has : List Selector -> Single msg -> Expectation
|
||||
has selectors (Internal.Single showTrace query) =
|
||||
Internal.has selectors query
|
||||
|> failWithQuery showTrace ("Query.has " ++ Internal.joinAsList selectorToString selectors) query
|
||||
|
||||
|
||||
{-| Expect the element to **not** match all of the given selectors.
|
||||
|
||||
import Html exposing (div)
|
||||
import Html.Attributes as Attributes
|
||||
import Test.Html.Query as Query
|
||||
import Test exposing (test)
|
||||
import Test.Html.Selector exposing (tag, class)
|
||||
|
||||
|
||||
test "The div element has no progress-bar class" <|
|
||||
\() ->
|
||||
div [ Attributes.class "button" ] []
|
||||
|> Query.fromHtml
|
||||
|> Query.find [ tag "div" ]
|
||||
|> Query.hasNot [ tag "div", class "progress-bar" ]
|
||||
|
||||
-}
|
||||
hasNot : List Selector -> Single msg -> Expectation
|
||||
hasNot selectors (Internal.Single showTrace query) =
|
||||
let
|
||||
queryName =
|
||||
"Query.hasNot " ++ Internal.joinAsList selectorToString selectors
|
||||
in
|
||||
Internal.hasNot selectors query
|
||||
|> failWithQuery showTrace queryName query
|
||||
|
||||
|
||||
{-| Expect that a [`Single`](#Single) expectation will hold true for each of the
|
||||
[`Multiple`](#Multiple) matched elements.
|
||||
|
||||
import Html exposing (div, ul, li)
|
||||
import Html.Attributes exposing (class)
|
||||
import Test.Html.Query as Query
|
||||
import Test exposing (test)
|
||||
import Test.Html.Selector exposing (tag, classes)
|
||||
|
||||
|
||||
test "The list has both the classes 'items' and 'active'" <|
|
||||
\() ->
|
||||
div []
|
||||
[ ul [ class "items active" ]
|
||||
[ li [] [ text "first item" ]
|
||||
, li [] [ text "second item" ]
|
||||
, li [] [ text "third item" ]
|
||||
]
|
||||
]
|
||||
|> Query.fromHtml
|
||||
|> Query.findAll [ tag "ul" ]
|
||||
|> Query.each
|
||||
[ Query.has [ tag "ul" ]
|
||||
, Query.has [ classes [ "items", "active" ] ]
|
||||
]
|
||||
|
||||
-}
|
||||
each : (Single msg -> Expectation) -> Multiple msg -> Expectation
|
||||
each check (Internal.Multiple showTrace query) =
|
||||
Internal.expectAll check query
|
||||
|> failWithQuery showTrace "Query.each" query
|
||||
559
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/src/Test/Html/Query/Internal.elm
vendored
Normal file
559
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/src/Test/Html/Query/Internal.elm
vendored
Normal file
@@ -0,0 +1,559 @@
|
||||
module Test.Html.Query.Internal exposing (..)
|
||||
|
||||
import ElmHtml.InternalTypes exposing (ElmHtml(..))
|
||||
import ElmHtml.ToString exposing (nodeToStringWithOptions)
|
||||
import Expect exposing (Expectation)
|
||||
import Html.Inert as Inert exposing (Node)
|
||||
import Test.Html.Descendant as Descendant
|
||||
import Test.Html.Selector.Internal as InternalSelector exposing (Selector, selectorToString)
|
||||
import Test.Runner
|
||||
|
||||
|
||||
{-| Note: the selectors are stored in reverse order for better prepending perf.
|
||||
-}
|
||||
type Query msg
|
||||
= Query (Inert.Node msg) (List SelectorQuery)
|
||||
|
||||
|
||||
type SelectorQuery
|
||||
= Find (List Selector)
|
||||
| FindAll (List Selector)
|
||||
| Children (List Selector)
|
||||
-- First and Index are separate so we can report Query.first in error messages
|
||||
| First
|
||||
| Index Int
|
||||
|
||||
|
||||
{-| The Bool is `showTrace` - whether to show the Query.fromHtml trace at
|
||||
the beginning of the error message.
|
||||
|
||||
We need to track this so that Query.each can turn it off. Otherwise you get
|
||||
fromHtml printed twice - once at the very top, then again for the nested
|
||||
expectation that Query.each delegated to.
|
||||
|
||||
-}
|
||||
type Single msg
|
||||
= Single Bool (Query msg)
|
||||
|
||||
|
||||
{-| The Bool is `showTrace` - see `Single` for more info.
|
||||
-}
|
||||
type Multiple msg
|
||||
= Multiple Bool (Query msg)
|
||||
|
||||
|
||||
type QueryError
|
||||
= NoResultsForSingle String
|
||||
| MultipleResultsForSingle String Int
|
||||
|
||||
|
||||
toLines : String -> Query msg -> String -> List String
|
||||
toLines expectationFailure (Query node selectors) queryName =
|
||||
toLinesHelp expectationFailure [ Inert.toElmHtml node ] (List.reverse selectors) queryName []
|
||||
|> List.reverse
|
||||
|
||||
|
||||
prettyPrint : ElmHtml msg -> String
|
||||
prettyPrint =
|
||||
nodeToStringWithOptions { indent = 4, newLines = True }
|
||||
|
||||
|
||||
toOutputLine : Query msg -> String
|
||||
toOutputLine (Query node selectors) =
|
||||
prettyPrint (Inert.toElmHtml node)
|
||||
|
||||
|
||||
toLinesHelp : String -> List (ElmHtml msg) -> List SelectorQuery -> String -> List String -> List String
|
||||
toLinesHelp expectationFailure elmHtmlList selectorQueries queryName results =
|
||||
let
|
||||
bailOut result =
|
||||
-- Bail out early so the last error message the user
|
||||
-- sees is Query.find rather than something like
|
||||
-- Query.has, to reflect how we didn't make it that far.
|
||||
String.join "\n\n\n✗ " [ result, expectationFailure ] :: results
|
||||
|
||||
recurse newElmHtmlList rest result =
|
||||
toLinesHelp
|
||||
expectationFailure
|
||||
newElmHtmlList
|
||||
rest
|
||||
queryName
|
||||
(result :: results)
|
||||
in
|
||||
case selectorQueries of
|
||||
[] ->
|
||||
String.join "\n\n" [ queryName, expectationFailure ] :: results
|
||||
|
||||
selectorQuery :: rest ->
|
||||
case selectorQuery of
|
||||
FindAll selectors ->
|
||||
let
|
||||
elements =
|
||||
elmHtmlList
|
||||
|> List.concatMap getChildren
|
||||
|> InternalSelector.queryAll selectors
|
||||
in
|
||||
("Query.findAll " ++ joinAsList selectorToString selectors)
|
||||
|> withHtmlContext (getHtmlContext elements)
|
||||
|> recurse elements rest
|
||||
|
||||
Find selectors ->
|
||||
let
|
||||
elements =
|
||||
elmHtmlList
|
||||
|> List.concatMap getChildren
|
||||
|> InternalSelector.queryAll selectors
|
||||
|
||||
result =
|
||||
("Query.find " ++ joinAsList selectorToString selectors)
|
||||
|> withHtmlContext (getHtmlContext elements)
|
||||
in
|
||||
if List.length elements == 1 then
|
||||
recurse elements rest result
|
||||
else
|
||||
bailOut result
|
||||
|
||||
Children selectors ->
|
||||
let
|
||||
elements =
|
||||
elmHtmlList
|
||||
|> List.concatMap getChildren
|
||||
|> InternalSelector.queryAllChildren selectors
|
||||
in
|
||||
("Query.children " ++ joinAsList selectorToString selectors)
|
||||
|> withHtmlContext (getHtmlContext elements)
|
||||
|> recurse elements rest
|
||||
|
||||
First ->
|
||||
let
|
||||
elements =
|
||||
elmHtmlList
|
||||
|> List.head
|
||||
|> Maybe.map (\elem -> [ elem ])
|
||||
|> Maybe.withDefault []
|
||||
|
||||
result =
|
||||
"Query.first"
|
||||
|> withHtmlContext (getHtmlContext elements)
|
||||
in
|
||||
if List.length elements == 1 then
|
||||
recurse elements rest result
|
||||
else
|
||||
bailOut result
|
||||
|
||||
Index index ->
|
||||
let
|
||||
elements =
|
||||
elmHtmlList
|
||||
|> getElementAt index
|
||||
|
||||
result =
|
||||
("Query.index " ++ toString index)
|
||||
|> withHtmlContext (getHtmlContext elements)
|
||||
in
|
||||
if List.length elements == 1 then
|
||||
recurse elements rest result
|
||||
else
|
||||
bailOut result
|
||||
|
||||
|
||||
withHtmlContext : String -> String -> String
|
||||
withHtmlContext htmlStr str =
|
||||
String.join "\n\n" [ str, htmlStr ]
|
||||
|
||||
|
||||
getHtmlContext : List (ElmHtml msg) -> String
|
||||
getHtmlContext elmHtmlList =
|
||||
if List.isEmpty elmHtmlList then
|
||||
"0 matches found for this query."
|
||||
else
|
||||
let
|
||||
maxDigits =
|
||||
elmHtmlList
|
||||
|> List.length
|
||||
|> toString
|
||||
|> String.length
|
||||
in
|
||||
elmHtmlList
|
||||
|> List.indexedMap (printIndented maxDigits)
|
||||
|> String.join "\n\n"
|
||||
|
||||
|
||||
joinAsList : (a -> String) -> List a -> String
|
||||
joinAsList toStr list =
|
||||
if List.isEmpty list then
|
||||
"[]"
|
||||
else
|
||||
"[ " ++ String.join ", " (List.map toStr list) ++ " ]"
|
||||
|
||||
|
||||
printIndented : Int -> Int -> ElmHtml msg -> String
|
||||
printIndented maxDigits index elmHtml =
|
||||
let
|
||||
caption =
|
||||
(toString (index + 1) ++ ")")
|
||||
|> String.padRight (maxDigits + 3) ' '
|
||||
|> String.append baseIndentation
|
||||
|
||||
indentation =
|
||||
String.repeat (String.length caption) " "
|
||||
in
|
||||
case String.split "\n" (prettyPrint elmHtml) of
|
||||
[] ->
|
||||
""
|
||||
|
||||
first :: rest ->
|
||||
rest
|
||||
|> List.map (String.append indentation)
|
||||
|> (::) (caption ++ first)
|
||||
|> String.join "\n"
|
||||
|
||||
|
||||
baseIndentation : String
|
||||
baseIndentation =
|
||||
" "
|
||||
|
||||
|
||||
prependSelector : Query msg -> SelectorQuery -> Query msg
|
||||
prependSelector (Query node selectors) selector =
|
||||
Query node (selector :: selectors)
|
||||
|
||||
|
||||
{-| This is a more efficient implementation of the following:
|
||||
|
||||
list
|
||||
|> Array.fromList
|
||||
|> Array.get index
|
||||
|> Maybe.map (\elem -> [ elem ])
|
||||
|> Maybe.withDefault []
|
||||
|
||||
It also supports wraparound via negative indeces, e.g. passing -1 for an index
|
||||
gets you the last element.
|
||||
|
||||
-}
|
||||
getElementAt : Int -> List a -> List a
|
||||
getElementAt index list =
|
||||
let
|
||||
length =
|
||||
List.length list
|
||||
in
|
||||
-- Avoid attempting % 0
|
||||
if length == 0 then
|
||||
[]
|
||||
else
|
||||
-- Support wraparound, e.g. passing -1 to get the last element.
|
||||
getElementAtHelp (index % length) list
|
||||
|
||||
|
||||
getElementAtHelp : Int -> List a -> List a
|
||||
getElementAtHelp index list =
|
||||
case list of
|
||||
[] ->
|
||||
[]
|
||||
|
||||
first :: rest ->
|
||||
if index == 0 then
|
||||
[ first ]
|
||||
else
|
||||
getElementAtHelp (index - 1) rest
|
||||
|
||||
|
||||
traverse : Query msg -> Result QueryError (List (ElmHtml msg))
|
||||
traverse (Query node selectorQueries) =
|
||||
traverseSelectors selectorQueries [ Inert.toElmHtml node ]
|
||||
|
||||
|
||||
traverseSelectors : List SelectorQuery -> List (ElmHtml msg) -> Result QueryError (List (ElmHtml msg))
|
||||
traverseSelectors selectorQueries elmHtmlList =
|
||||
List.foldr
|
||||
(traverseSelector >> Result.andThen)
|
||||
(Ok elmHtmlList)
|
||||
selectorQueries
|
||||
|
||||
|
||||
traverseSelector : SelectorQuery -> List (ElmHtml msg) -> Result QueryError (List (ElmHtml msg))
|
||||
traverseSelector selectorQuery elmHtmlList =
|
||||
case selectorQuery of
|
||||
Find selectors ->
|
||||
elmHtmlList
|
||||
|> List.concatMap getChildren
|
||||
|> InternalSelector.queryAll selectors
|
||||
|> verifySingle "Query.find"
|
||||
|> Result.map (\elem -> [ elem ])
|
||||
|
||||
FindAll selectors ->
|
||||
elmHtmlList
|
||||
|> List.concatMap getChildren
|
||||
|> InternalSelector.queryAll selectors
|
||||
|> Ok
|
||||
|
||||
Children selectors ->
|
||||
elmHtmlList
|
||||
|> List.concatMap getChildren
|
||||
|> InternalSelector.queryAllChildren selectors
|
||||
|> Ok
|
||||
|
||||
First ->
|
||||
elmHtmlList
|
||||
|> List.head
|
||||
|> Maybe.map (\elem -> Ok [ elem ])
|
||||
|> Maybe.withDefault (Err (NoResultsForSingle "Query.first"))
|
||||
|
||||
Index index ->
|
||||
let
|
||||
elements =
|
||||
elmHtmlList
|
||||
|> getElementAt index
|
||||
in
|
||||
if List.length elements == 1 then
|
||||
Ok elements
|
||||
else
|
||||
Err (NoResultsForSingle ("Query.index " ++ toString index))
|
||||
|
||||
|
||||
getChildren : ElmHtml msg -> List (ElmHtml msg)
|
||||
getChildren elmHtml =
|
||||
case elmHtml of
|
||||
NodeEntry { children } ->
|
||||
children
|
||||
|
||||
_ ->
|
||||
[]
|
||||
|
||||
|
||||
isElement : ElmHtml msg -> Bool
|
||||
isElement elmHtml =
|
||||
case elmHtml of
|
||||
NodeEntry _ ->
|
||||
True
|
||||
|
||||
_ ->
|
||||
False
|
||||
|
||||
|
||||
verifySingle : String -> List a -> Result QueryError a
|
||||
verifySingle queryName list =
|
||||
case list of
|
||||
[] ->
|
||||
Err (NoResultsForSingle queryName)
|
||||
|
||||
singleton :: [] ->
|
||||
Ok singleton
|
||||
|
||||
multiples ->
|
||||
Err (MultipleResultsForSingle queryName (List.length multiples))
|
||||
|
||||
|
||||
expectAll : (Single msg -> Expectation) -> Query msg -> Expectation
|
||||
expectAll check query =
|
||||
case traverse query of
|
||||
Ok list ->
|
||||
expectAllHelp 0 check list
|
||||
|
||||
Err error ->
|
||||
Expect.fail (queryErrorToString query error)
|
||||
|
||||
|
||||
expectAllHelp : Int -> (Single msg -> Expectation) -> List (ElmHtml msg) -> Expectation
|
||||
expectAllHelp successes check list =
|
||||
case list of
|
||||
[] ->
|
||||
Expect.pass
|
||||
|
||||
elmHtml :: rest ->
|
||||
let
|
||||
expectation =
|
||||
Query (Inert.fromElmHtml elmHtml) []
|
||||
|> Single False
|
||||
|> check
|
||||
in
|
||||
case Test.Runner.getFailure expectation of
|
||||
Just { given, message } ->
|
||||
let
|
||||
prefix =
|
||||
if successes > 0 then
|
||||
"Element #" ++ toString (successes + 1) ++ " failed this test:"
|
||||
else
|
||||
"The first element failed this test:"
|
||||
in
|
||||
[ prefix, message ]
|
||||
|> String.join "\n\n"
|
||||
|> Expect.fail
|
||||
|
||||
Nothing ->
|
||||
expectAllHelp (successes + 1) check rest
|
||||
|
||||
|
||||
multipleToExpectation : Multiple msg -> (List (ElmHtml msg) -> Expectation) -> Expectation
|
||||
multipleToExpectation (Multiple _ query) check =
|
||||
case traverse query of
|
||||
Ok list ->
|
||||
check list
|
||||
|
||||
Err error ->
|
||||
Expect.fail (queryErrorToString query error)
|
||||
|
||||
|
||||
queryErrorToString : Query msg -> QueryError -> String
|
||||
queryErrorToString query error =
|
||||
case error of
|
||||
NoResultsForSingle queryName ->
|
||||
queryName ++ " always expects to find 1 element, but it found 0 instead."
|
||||
|
||||
MultipleResultsForSingle queryName resultCount ->
|
||||
queryName
|
||||
++ " always expects to find 1 element, but it found "
|
||||
++ toString resultCount
|
||||
++ " instead.\n\n\nHINT: If you actually expected "
|
||||
++ toString resultCount
|
||||
++ " elements, use Query.findAll instead of Query.find."
|
||||
|
||||
|
||||
contains : List (ElmHtml msg) -> Query msg -> Expectation
|
||||
contains expectedDescendants query =
|
||||
case traverse query of
|
||||
Ok elmHtmlList ->
|
||||
let
|
||||
missing =
|
||||
missingDescendants elmHtmlList expectedDescendants
|
||||
|
||||
prettyPrint missingDescendants =
|
||||
String.join
|
||||
"\n\n---------------------------------------------\n\n"
|
||||
(List.indexedMap
|
||||
(\index descendant -> printIndented 3 index descendant)
|
||||
missingDescendants
|
||||
)
|
||||
in
|
||||
if List.isEmpty missing then
|
||||
Expect.pass
|
||||
else
|
||||
Expect.fail
|
||||
(String.join ""
|
||||
[ "\t✗ /"
|
||||
, toString <| List.length missing
|
||||
, "\\ missing descendants: \n\n"
|
||||
, prettyPrint missing
|
||||
]
|
||||
)
|
||||
|
||||
Err error ->
|
||||
Expect.fail (queryErrorToString query error)
|
||||
|
||||
|
||||
missingDescendants : List (ElmHtml msg) -> List (ElmHtml msg) -> List (ElmHtml msg)
|
||||
missingDescendants elmHtmlList expected =
|
||||
let
|
||||
isMissing =
|
||||
\expectedDescendant ->
|
||||
not <| Descendant.isDescendant elmHtmlList expectedDescendant
|
||||
in
|
||||
List.filter isMissing expected
|
||||
|
||||
|
||||
has : List Selector -> Query msg -> Expectation
|
||||
has selectors query =
|
||||
case traverse query of
|
||||
Ok elmHtmlList ->
|
||||
if List.isEmpty (InternalSelector.queryAll selectors elmHtmlList) then
|
||||
selectors
|
||||
|> List.map (showSelectorOutcome elmHtmlList)
|
||||
|> String.join "\n"
|
||||
|> Expect.fail
|
||||
else
|
||||
Expect.pass
|
||||
|
||||
Err error ->
|
||||
Expect.fail (queryErrorToString query error)
|
||||
|
||||
|
||||
hasNot : List Selector -> Query msg -> Expectation
|
||||
hasNot selectors query =
|
||||
case traverse query of
|
||||
Ok [] ->
|
||||
Expect.pass
|
||||
|
||||
Ok elmHtmlList ->
|
||||
case InternalSelector.queryAll selectors elmHtmlList of
|
||||
[] ->
|
||||
Expect.pass
|
||||
|
||||
_ ->
|
||||
selectors
|
||||
|> List.map (showSelectorOutcomeInverse elmHtmlList)
|
||||
|> String.join "\n"
|
||||
|> Expect.fail
|
||||
|
||||
Err error ->
|
||||
Expect.pass
|
||||
|
||||
|
||||
showSelectorOutcome : List (ElmHtml msg) -> Selector -> String
|
||||
showSelectorOutcome elmHtmlList selector =
|
||||
let
|
||||
outcome =
|
||||
case InternalSelector.queryAll [ selector ] elmHtmlList of
|
||||
[] ->
|
||||
"✗"
|
||||
|
||||
_ ->
|
||||
"✓"
|
||||
in
|
||||
String.join " " [ outcome, "has", selectorToString selector ]
|
||||
|
||||
|
||||
showSelectorOutcomeInverse : List (ElmHtml msg) -> Selector -> String
|
||||
showSelectorOutcomeInverse elmHtmlList selector =
|
||||
let
|
||||
outcome =
|
||||
case InternalSelector.queryAll [ selector ] elmHtmlList of
|
||||
[] ->
|
||||
"✓"
|
||||
|
||||
_ ->
|
||||
"✗"
|
||||
in
|
||||
String.join " " [ outcome, "has not", selectorToString selector ]
|
||||
|
||||
|
||||
|
||||
-- HELPERS --
|
||||
|
||||
|
||||
failWithQuery : Bool -> String -> Query msg -> Expectation -> Expectation
|
||||
failWithQuery showTrace queryName query expectation =
|
||||
case Test.Runner.getFailure expectation of
|
||||
Just { given, message } ->
|
||||
let
|
||||
lines =
|
||||
toLines message query queryName
|
||||
|> List.map prefixOutputLine
|
||||
|
||||
tracedLines =
|
||||
if showTrace then
|
||||
addQueryFromHtmlLine query :: lines
|
||||
else
|
||||
lines
|
||||
in
|
||||
tracedLines
|
||||
|> String.join "\n\n\n"
|
||||
|> Expect.fail
|
||||
|
||||
Nothing ->
|
||||
expectation
|
||||
|
||||
|
||||
addQueryFromHtmlLine : Query msg -> String
|
||||
addQueryFromHtmlLine query =
|
||||
String.join "\n\n"
|
||||
[ prefixOutputLine "Query.fromHtml"
|
||||
, toOutputLine query
|
||||
|> String.split "\n"
|
||||
|> List.map ((++) baseIndentation)
|
||||
|> String.join "\n"
|
||||
]
|
||||
|
||||
|
||||
prefixOutputLine : String -> String
|
||||
prefixOutputLine =
|
||||
(++) "▼ "
|
||||
306
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/src/Test/Html/Selector.elm
vendored
Normal file
306
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/src/Test/Html/Selector.elm
vendored
Normal file
@@ -0,0 +1,306 @@
|
||||
module Test.Html.Selector
|
||||
exposing
|
||||
( Selector
|
||||
, all
|
||||
, attribute
|
||||
, checked
|
||||
, class
|
||||
, classes
|
||||
, disabled
|
||||
, exactClassName
|
||||
, id
|
||||
, selected
|
||||
, style
|
||||
, tag
|
||||
, text
|
||||
)
|
||||
|
||||
{-| Selecting HTML elements.
|
||||
|
||||
@docs Selector
|
||||
|
||||
|
||||
## General Selectors
|
||||
|
||||
@docs tag, text, attribute, all
|
||||
|
||||
|
||||
## Attributes
|
||||
|
||||
@docs id, class, classes, exactClassName, style, checked, selected, disabled
|
||||
|
||||
-}
|
||||
|
||||
import ElmHtml.InternalTypes
|
||||
import Html exposing (Attribute)
|
||||
import Html.Inert
|
||||
import Json.Decode
|
||||
import Test.Html.Selector.Internal as Internal exposing (..)
|
||||
|
||||
|
||||
{-| A selector used to filter sets of elements.
|
||||
-}
|
||||
type alias Selector =
|
||||
Internal.Selector
|
||||
|
||||
|
||||
{-| Combine the given selectors into one which requires all of them to match.
|
||||
|
||||
import Html
|
||||
import Html.Attributes as Attr
|
||||
import Test.Html.Query as Query
|
||||
import Test exposing (test)
|
||||
import Test.Html.Selector exposing (class, text, all, Selector)
|
||||
|
||||
|
||||
replyBtnSelector : Selector
|
||||
replyBtnSelector =
|
||||
all [ class "btn", text "Reply" ]
|
||||
|
||||
|
||||
test "Button has the class 'btn' and the text 'Reply'" <|
|
||||
\() ->
|
||||
Html.button [ Attr.class "btn btn-large" ] [ Html.text "Reply" ]
|
||||
|> Query.fromHtml
|
||||
|> Query.has [ replyBtnSelector ]
|
||||
|
||||
-}
|
||||
all : List Selector -> Selector
|
||||
all =
|
||||
All
|
||||
|
||||
|
||||
{-| Matches elements that have all the given classes (and possibly others as well).
|
||||
|
||||
When you only care about one class instead of several, you can use
|
||||
[`class`](#class) instead of passing this function a list with one value in it.
|
||||
|
||||
To match the element's exact class attribute string, use [`className`](#className).
|
||||
|
||||
import Html
|
||||
import Html.Attributes as Attr
|
||||
import Test.Html.Query as Query
|
||||
import Test exposing (test)
|
||||
import Test.Html.Selector exposing (classes)
|
||||
|
||||
|
||||
test "Button has the classes btn and btn-large" <|
|
||||
\() ->
|
||||
Html.button [ Attr.class "btn btn-large" ] [ Html.text "Reply" ]
|
||||
|> Query.fromHtml
|
||||
|> Query.has [ classes [ "btn", "btn-large" ] ]
|
||||
|
||||
-}
|
||||
classes : List String -> Selector
|
||||
classes =
|
||||
Classes
|
||||
|
||||
|
||||
{-| Matches elements that have the given class (and possibly others as well).
|
||||
|
||||
To match multiple classes at once, use [`classes`](#classes) instead.
|
||||
|
||||
To match the element's exact class attribute string, use [`className`](#className).
|
||||
|
||||
import Html
|
||||
import Html.Attributes as Attr
|
||||
import Test.Html.Query as Query
|
||||
import Test exposing (test)
|
||||
import Test.Html.Selector exposing (class)
|
||||
|
||||
|
||||
test "Button has the class btn-large" <|
|
||||
\() ->
|
||||
Html.button [ Attr.class "btn btn-large" ] [ Html.text "Reply" ]
|
||||
|> Query.fromHtml
|
||||
|> Query.has [ class "btn-large" ]
|
||||
|
||||
-}
|
||||
class : String -> Selector
|
||||
class =
|
||||
Class
|
||||
|
||||
|
||||
{-| Matches the element's exact class attribute string.
|
||||
|
||||
This is used less often than [`class`](#class), [`classes`](#classes) or
|
||||
[`attribute`](#attribute), which check for the *presence* of a class as opposed
|
||||
to matching the entire class attribute exactly.
|
||||
|
||||
import Html
|
||||
import Html.Attributes as Attr
|
||||
import Test.Html.Query as Query
|
||||
import Test exposing (test)
|
||||
import Test.Html.Selector exposing (exactClassName)
|
||||
|
||||
|
||||
test "Button has the exact class 'btn btn-large'" <|
|
||||
\() ->
|
||||
Html.button [ Attr.class "btn btn-large" ] [ Html.text "Reply" ]
|
||||
|> Query.fromHtml
|
||||
|> Query.has [ exactClassName "btn btn-large" ]
|
||||
|
||||
-}
|
||||
exactClassName : String -> Selector
|
||||
exactClassName =
|
||||
namedAttr "className"
|
||||
|
||||
|
||||
{-| Matches elements that have the given `id` attribute.
|
||||
|
||||
import Html
|
||||
import Html.Attributes as Attr
|
||||
import Test.Html.Query as Query
|
||||
import Test exposing (test)
|
||||
import Test.Html.Selector exposing (id, text)
|
||||
|
||||
|
||||
test "the welcome <h1> says hello!" <|
|
||||
\() ->
|
||||
Html.div []
|
||||
[ Html.h1 [ Attr.id "welcome" ] [ Html.text "Hello!" ] ]
|
||||
|> Query.fromHtml
|
||||
|> Query.find [ id "welcome" ]
|
||||
|> Query.has [ text "Hello!" ]
|
||||
|
||||
-}
|
||||
id : String -> Selector
|
||||
id =
|
||||
namedAttr "id"
|
||||
|
||||
|
||||
{-| Matches elements that have the given tag.
|
||||
|
||||
import Html
|
||||
import Html.Attributes as Attr
|
||||
import Test.Html.Query as Query
|
||||
import Test exposing (test)
|
||||
import Test.Html.Selector exposing (tag, text)
|
||||
|
||||
|
||||
test "the welcome <h1> says hello!" <|
|
||||
\() ->
|
||||
Html.div []
|
||||
[ Html.h1 [ Attr.id "welcome" ] [ Html.text "Hello!" ] ]
|
||||
|> Query.fromHtml
|
||||
|> Query.find [ tag "h1" ]
|
||||
|> Query.has [ text "Hello!" ]
|
||||
|
||||
-}
|
||||
tag : String -> Selector
|
||||
tag name =
|
||||
Tag name
|
||||
|
||||
|
||||
{-| Matches elements that have the given attribute in a way that makes sense
|
||||
given their semantics in `Html`.
|
||||
|
||||
See [Selecting elements by `Html.Attribute msg` in the README](http://package.elm-lang.org/packages/eeue56/elm-html-test/latest#selecting-elements-by-html-attribute-msg-)
|
||||
|
||||
-}
|
||||
attribute : Attribute Never -> Selector
|
||||
attribute attr =
|
||||
case Html.Inert.parseAttribute attr of
|
||||
ElmHtml.InternalTypes.Attribute { key, value } ->
|
||||
if String.toLower key == "class" then
|
||||
value
|
||||
|> String.split " "
|
||||
|> Classes
|
||||
else
|
||||
namedAttr key value
|
||||
|
||||
ElmHtml.InternalTypes.Property { key, value } ->
|
||||
if key == "className" then
|
||||
value
|
||||
|> Json.Decode.decodeValue Json.Decode.string
|
||||
|> Result.map (String.split " ")
|
||||
|> Result.withDefault []
|
||||
|> Classes
|
||||
else
|
||||
value
|
||||
|> Json.Decode.decodeValue Json.Decode.string
|
||||
|> Result.map (namedAttr key)
|
||||
|> orElseLazy
|
||||
(\() ->
|
||||
value
|
||||
|> Json.Decode.decodeValue Json.Decode.bool
|
||||
|> Result.map (namedBoolAttr key)
|
||||
)
|
||||
|> Result.withDefault Invalid
|
||||
|
||||
ElmHtml.InternalTypes.Styles styles ->
|
||||
Style styles
|
||||
|
||||
_ ->
|
||||
Invalid
|
||||
|
||||
|
||||
{-| Matches elements that have all the given style properties (and possibly others as well).
|
||||
|
||||
import Html
|
||||
import Html.Attributes as Attr
|
||||
import Test.Html.Query as Query
|
||||
import Test exposing (test)
|
||||
import Test.Html.Selector exposing (classes)
|
||||
|
||||
|
||||
test "the Reply button has red text" <|
|
||||
\() ->
|
||||
Html.div []
|
||||
[ Html.button [ Attr.style [ ( "color", "red" ) ] ] [ Html.text "Reply" ] ]
|
||||
|> Query.has [ style [ ( "color", "red" ) ] ]
|
||||
|
||||
-}
|
||||
style : List ( String, String ) -> Selector
|
||||
style style =
|
||||
Style style
|
||||
|
||||
|
||||
{-| Matches elements that have a
|
||||
[`text`](http://package.elm-lang.org/packages/elm-lang/html/latest/Html-Attributes#text)
|
||||
attribute with the given value.
|
||||
-}
|
||||
text : String -> Selector
|
||||
text =
|
||||
Internal.Text
|
||||
|
||||
|
||||
{-| Matches elements that have a
|
||||
[`selected`](http://package.elm-lang.org/packages/elm-lang/html/latest/Html-Attributes#selected)
|
||||
attribute with the given value.
|
||||
-}
|
||||
selected : Bool -> Selector
|
||||
selected =
|
||||
namedBoolAttr "selected"
|
||||
|
||||
|
||||
{-| Matches elements that have a
|
||||
[`disabled`](http://package.elm-lang.org/packages/elm-lang/html/latest/Html-Attributes#disabled)
|
||||
attribute with the given value.
|
||||
-}
|
||||
disabled : Bool -> Selector
|
||||
disabled =
|
||||
namedBoolAttr "disabled"
|
||||
|
||||
|
||||
{-| Matches elements that have a
|
||||
[`checked`](http://package.elm-lang.org/packages/elm-lang/html/latest/Html-Attributes#checked)
|
||||
attribute with the given value.
|
||||
-}
|
||||
checked : Bool -> Selector
|
||||
checked =
|
||||
namedBoolAttr "checked"
|
||||
|
||||
|
||||
|
||||
-- HELPERS
|
||||
|
||||
|
||||
orElseLazy : (() -> Result x a) -> Result x a -> Result x a
|
||||
orElseLazy fma mb =
|
||||
case mb of
|
||||
Err _ ->
|
||||
fma ()
|
||||
|
||||
Ok _ ->
|
||||
mb
|
||||
136
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/src/Test/Html/Selector/Internal.elm
vendored
Normal file
136
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/src/Test/Html/Selector/Internal.elm
vendored
Normal file
@@ -0,0 +1,136 @@
|
||||
module Test.Html.Selector.Internal exposing (..)
|
||||
|
||||
import ElmHtml.InternalTypes exposing (ElmHtml)
|
||||
import ElmHtml.Query
|
||||
|
||||
|
||||
type Selector
|
||||
= All (List Selector)
|
||||
| Classes (List String)
|
||||
| Class String
|
||||
| Attribute { name : String, value : String }
|
||||
| BoolAttribute { name : String, value : Bool }
|
||||
| Style (List ( String, String ))
|
||||
| Tag String
|
||||
| Text String
|
||||
| Invalid
|
||||
|
||||
|
||||
selectorToString : Selector -> String
|
||||
selectorToString criteria =
|
||||
case criteria of
|
||||
All list ->
|
||||
list
|
||||
|> List.map selectorToString
|
||||
|> String.join " "
|
||||
|
||||
Classes list ->
|
||||
"classes " ++ toString (String.join " " list)
|
||||
|
||||
Class class ->
|
||||
"class " ++ toString class
|
||||
|
||||
Attribute { name, value } ->
|
||||
"attribute "
|
||||
++ toString name
|
||||
++ " "
|
||||
++ toString value
|
||||
|
||||
BoolAttribute { name, value } ->
|
||||
"attribute "
|
||||
++ toString name
|
||||
++ " "
|
||||
++ toString value
|
||||
|
||||
Style style ->
|
||||
"styles " ++ styleToString style
|
||||
|
||||
Tag name ->
|
||||
"tag " ++ toString name
|
||||
|
||||
Text text ->
|
||||
"text " ++ toString text
|
||||
|
||||
Invalid ->
|
||||
"invalid"
|
||||
|
||||
|
||||
styleToString : List ( String, String ) -> String
|
||||
styleToString style =
|
||||
style
|
||||
|> List.map (\( k, v ) -> k ++ ":" ++ v ++ ";")
|
||||
|> String.join " "
|
||||
|
||||
|
||||
queryAll : List Selector -> List (ElmHtml msg) -> List (ElmHtml msg)
|
||||
queryAll selectors list =
|
||||
case selectors of
|
||||
[] ->
|
||||
list
|
||||
|
||||
selector :: rest ->
|
||||
query ElmHtml.Query.query queryAll selector list
|
||||
|> queryAllChildren rest
|
||||
|
||||
|
||||
queryAllChildren : List Selector -> List (ElmHtml msg) -> List (ElmHtml msg)
|
||||
queryAllChildren selectors list =
|
||||
case selectors of
|
||||
[] ->
|
||||
list
|
||||
|
||||
selector :: rest ->
|
||||
query ElmHtml.Query.queryChildren queryAllChildren selector list
|
||||
|> queryAllChildren rest
|
||||
|
||||
|
||||
query :
|
||||
(ElmHtml.Query.Selector -> ElmHtml msg -> List (ElmHtml msg))
|
||||
-> (List Selector -> List (ElmHtml msg) -> List (ElmHtml msg))
|
||||
-> Selector
|
||||
-> List (ElmHtml msg)
|
||||
-> List (ElmHtml msg)
|
||||
query fn fnAll selector list =
|
||||
case selector of
|
||||
All selectors ->
|
||||
fnAll selectors list
|
||||
|
||||
Classes classes ->
|
||||
List.concatMap (fn (ElmHtml.Query.ClassList classes)) list
|
||||
|
||||
Class class ->
|
||||
List.concatMap (fn (ElmHtml.Query.ClassList [ class ])) list
|
||||
|
||||
Attribute { name, value } ->
|
||||
List.concatMap (fn (ElmHtml.Query.Attribute name value)) list
|
||||
|
||||
BoolAttribute { name, value } ->
|
||||
List.concatMap (fn (ElmHtml.Query.BoolAttribute name value)) list
|
||||
|
||||
Style style ->
|
||||
List.concatMap (fn (ElmHtml.Query.Style style)) list
|
||||
|
||||
Tag name ->
|
||||
List.concatMap (fn (ElmHtml.Query.Tag name)) list
|
||||
|
||||
Text text ->
|
||||
List.concatMap (fn (ElmHtml.Query.ContainsText text)) list
|
||||
|
||||
Invalid ->
|
||||
[]
|
||||
|
||||
|
||||
namedAttr : String -> String -> Selector
|
||||
namedAttr name value =
|
||||
Attribute
|
||||
{ name = name
|
||||
, value = value
|
||||
}
|
||||
|
||||
|
||||
namedBoolAttr : String -> Bool -> Selector
|
||||
namedBoolAttr name value =
|
||||
BoolAttribute
|
||||
{ name = name
|
||||
, value = value
|
||||
}
|
||||
64
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/tests/Attributes.elm
vendored
Normal file
64
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/tests/Attributes.elm
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
module Attributes exposing (..)
|
||||
|
||||
import Expect
|
||||
import Html.Attributes as Attr
|
||||
import Json.Encode as Encode
|
||||
import Test exposing (..)
|
||||
import Test.Html.Selector as Selector
|
||||
import Test.Html.Selector.Internal exposing (Selector(..), namedAttr, namedBoolAttr)
|
||||
|
||||
|
||||
all : Test
|
||||
all =
|
||||
describe "Selector.attribute"
|
||||
[ test "can generate a StringAttribute selector" <|
|
||||
\() ->
|
||||
Attr.title "test"
|
||||
|> Selector.attribute
|
||||
|> Expect.equal (namedAttr "title" "test")
|
||||
, test "works for things like `value` which are technically properties" <|
|
||||
\() ->
|
||||
Attr.value "test"
|
||||
|> Selector.attribute
|
||||
|> Expect.equal (namedAttr "value" "test")
|
||||
, test "can generate a BoolAttribute selector" <|
|
||||
\() ->
|
||||
Attr.checked True
|
||||
|> Selector.attribute
|
||||
|> Expect.equal (namedBoolAttr "checked" True)
|
||||
, test "can generate a Style selector" <|
|
||||
\() ->
|
||||
Attr.style [ ( "margin", "0" ) ]
|
||||
|> Selector.attribute
|
||||
|> Expect.equal (Style [ ( "margin", "0" ) ])
|
||||
, describe "classes" <|
|
||||
[ test "can generate a Classes selector" <|
|
||||
\() ->
|
||||
Attr.class "hello world"
|
||||
|> Selector.attribute
|
||||
|> Expect.equal (Classes [ "hello", "world" ])
|
||||
, test "catches a situation where the user passes classes using Html.Attr.attribute \"class\" \"the-class\"" <|
|
||||
\() ->
|
||||
Attr.attribute "class" "hello world"
|
||||
|> Selector.attribute
|
||||
|> Expect.equal (Classes [ "hello", "world" ])
|
||||
, test "can find a class attribute in a case insensitive manner" <|
|
||||
\() ->
|
||||
Attr.attribute "CLASS" "hello world"
|
||||
|> Selector.attribute
|
||||
|> Expect.equal (Classes [ "hello", "world" ])
|
||||
, test "finds className property only by exact match" <|
|
||||
\() ->
|
||||
Attr.property "classname" (Encode.string "hello world")
|
||||
|> Selector.attribute
|
||||
|> Expect.all
|
||||
[ Expect.notEqual (Classes [ "hello world" ])
|
||||
, Expect.equal (Attribute { name = "classname", value = "hello world" })
|
||||
]
|
||||
]
|
||||
, test "anything else fails" <|
|
||||
\() ->
|
||||
Attr.property "unknown" (Encode.int 1)
|
||||
|> Selector.attribute
|
||||
|> Expect.equal Invalid
|
||||
]
|
||||
89
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/tests/Descendant.elm
vendored
Normal file
89
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/tests/Descendant.elm
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
module Descendant exposing (..)
|
||||
|
||||
import Html exposing (Html)
|
||||
import Test exposing (..)
|
||||
import ElmHtml.InternalTypes exposing (ElmHtml(..))
|
||||
import Expect
|
||||
import Html exposing (..)
|
||||
import Html.Inert exposing (fromHtml, toElmHtml)
|
||||
import Test.Html.Query as Query exposing (Single)
|
||||
import Test.Html.Descendant exposing (isDescendant)
|
||||
|
||||
|
||||
wrapper : Html msg -> Html msg -> Bool
|
||||
wrapper html potentialDescendant =
|
||||
let
|
||||
elmHtml =
|
||||
[ htmlToElm html ]
|
||||
|
||||
potentialDescendantElmHtml =
|
||||
htmlToElm potentialDescendant
|
||||
in
|
||||
isDescendant elmHtml potentialDescendantElmHtml
|
||||
|
||||
|
||||
all : Test
|
||||
all =
|
||||
describe "Contains assertion"
|
||||
[ test "returns true if it contains the expected html once" <|
|
||||
\() ->
|
||||
let
|
||||
aSingleDescendant =
|
||||
someTitle "foo"
|
||||
|
||||
html =
|
||||
div [] [ aSingleDescendant ]
|
||||
in
|
||||
wrapper html aSingleDescendant
|
||||
|> Expect.true ""
|
||||
, test "returns true if it contains the expected html more than once" <|
|
||||
\() ->
|
||||
let
|
||||
aMultiInstanceDescendant =
|
||||
someTitle "foo"
|
||||
|
||||
html =
|
||||
div []
|
||||
[ aMultiInstanceDescendant
|
||||
, aMultiInstanceDescendant
|
||||
]
|
||||
in
|
||||
wrapper html aMultiInstanceDescendant
|
||||
|> Expect.true ""
|
||||
, test "return true if the node is a nested descendant" <|
|
||||
\() ->
|
||||
let
|
||||
aNestedDescendant =
|
||||
someTitle "foo"
|
||||
|
||||
html =
|
||||
div []
|
||||
[ div []
|
||||
[ div [] [ aNestedDescendant ]
|
||||
]
|
||||
]
|
||||
in
|
||||
wrapper html aNestedDescendant
|
||||
|> Expect.true ""
|
||||
, test "returns false if it does not contain the node" <|
|
||||
\() ->
|
||||
let
|
||||
notInHtml =
|
||||
img [] []
|
||||
|
||||
html =
|
||||
div [] [ someTitle "foo" ]
|
||||
in
|
||||
wrapper html notInHtml
|
||||
|> Expect.false ""
|
||||
]
|
||||
|
||||
|
||||
someTitle : String -> Html msg
|
||||
someTitle str =
|
||||
h1 [] [ text str ]
|
||||
|
||||
|
||||
htmlToElm : Html msg -> ElmHtml msg
|
||||
htmlToElm =
|
||||
toElmHtml << fromHtml
|
||||
172
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/tests/Events.elm
vendored
Normal file
172
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/tests/Events.elm
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
module Events exposing (..)
|
||||
|
||||
import Expect
|
||||
import Html exposing (Html, button, div, input, text)
|
||||
import Html.Attributes as Attr exposing (href)
|
||||
import Html.Events exposing (..)
|
||||
import Html.Keyed as Keyed
|
||||
import Html.Lazy as Lazy
|
||||
import Json.Decode exposing (Value)
|
||||
import Json.Encode as Encode
|
||||
import Test exposing (..)
|
||||
import Test.Html.Event as Event exposing (Event)
|
||||
import Test.Html.Query as Query exposing (Single)
|
||||
import Test.Html.Selector exposing (tag)
|
||||
|
||||
|
||||
all : Test
|
||||
all =
|
||||
describe "trigerring events"
|
||||
[ test "returns msg for click on element" <|
|
||||
\() ->
|
||||
Query.fromHtml sampleHtml
|
||||
|> Query.findAll [ tag "button" ]
|
||||
|> Query.first
|
||||
|> Event.simulate Event.click
|
||||
|> Event.expect SampleMsg
|
||||
, test "returns msg for click on lazy html" <|
|
||||
\() ->
|
||||
Query.fromHtml sampleLazyHtml
|
||||
|> Query.findAll [ tag "button" ]
|
||||
|> Query.first
|
||||
|> Event.simulate Event.click
|
||||
|> Event.expect SampleMsg
|
||||
, test "returns msg for click on mapped html" <|
|
||||
\() ->
|
||||
Query.fromHtml sampleMappedHtml
|
||||
|> Query.findAll [ tag "button" ]
|
||||
|> Query.first
|
||||
|> Event.simulate Event.click
|
||||
|> Event.expect MappedSampleMsg
|
||||
, test "returns msg for click on mapped lazy html" <|
|
||||
\() ->
|
||||
Query.fromHtml sampleMappedLazyHtml
|
||||
|> Query.findAll [ tag "button" ]
|
||||
|> Query.first
|
||||
|> Event.simulate Event.click
|
||||
|> Event.expect MappedSampleMsg
|
||||
, test "returns msg for click on mapped keyed html" <|
|
||||
\() ->
|
||||
Query.fromHtml sampleMappedKeyedHtml
|
||||
|> Query.findAll [ tag "button" ]
|
||||
|> Query.first
|
||||
|> Event.simulate Event.click
|
||||
|> Event.expect MappedSampleMsg
|
||||
, test "returns msg for click on deep mapped html" <|
|
||||
\() ->
|
||||
Query.fromHtml deepMappedHtml
|
||||
|> Query.findAll [ tag "input" ]
|
||||
|> Query.first
|
||||
|> Event.simulate (Event.input "foo")
|
||||
|> Event.expect (SampleInputMsg "foobar")
|
||||
, test "returns msg for input with transformation" <|
|
||||
\() ->
|
||||
input [ onInput (String.toUpper >> SampleInputMsg) ] []
|
||||
|> Query.fromHtml
|
||||
|> Event.simulate (Event.input "cats")
|
||||
|> Event.expect (SampleInputMsg "CATS")
|
||||
, test "returns msg for check event" <|
|
||||
\() ->
|
||||
input [ onCheck SampleCheckedMsg ] []
|
||||
|> Query.fromHtml
|
||||
|> Event.simulate (Event.check True)
|
||||
|> Event.expect (SampleCheckedMsg True)
|
||||
, test "returns msg for custom event" <|
|
||||
\() ->
|
||||
input [ on "keyup" (Json.Decode.map SampleKeyUpMsg keyCode) ] []
|
||||
|> Query.fromHtml
|
||||
|> Event.simulate ( "keyup", Encode.object [ ( "keyCode", Encode.int 5 ) ] )
|
||||
|> Event.expect (SampleKeyUpMsg 5)
|
||||
, testEvent onDoubleClick Event.doubleClick
|
||||
, testEvent onMouseDown Event.mouseDown
|
||||
, testEvent onMouseUp Event.mouseUp
|
||||
, testEvent onMouseLeave Event.mouseLeave
|
||||
, testEvent onMouseOver Event.mouseOver
|
||||
, testEvent onMouseOut Event.mouseOut
|
||||
, testEvent onSubmit Event.submit
|
||||
, testEvent onBlur Event.blur
|
||||
, testEvent onFocus Event.focus
|
||||
, test "event result" <|
|
||||
\() ->
|
||||
Query.fromHtml sampleHtml
|
||||
|> Query.find [ tag "button" ]
|
||||
|> Event.simulate Event.click
|
||||
|> Event.toResult
|
||||
|> Expect.equal (Ok SampleMsg)
|
||||
]
|
||||
|
||||
|
||||
type Msg
|
||||
= SampleMsg
|
||||
| MappedSampleMsg
|
||||
| SampleInputMsg String
|
||||
| SampleCheckedMsg Bool
|
||||
| SampleKeyUpMsg Int
|
||||
|
||||
|
||||
sampleHtml : Html Msg
|
||||
sampleHtml =
|
||||
div [ Attr.class "container" ]
|
||||
[ button [ onClick SampleMsg ] [ text "click me" ]
|
||||
]
|
||||
|
||||
|
||||
sampleLazyHtml : Html Msg
|
||||
sampleLazyHtml =
|
||||
div [ Attr.class "container" ]
|
||||
[ Lazy.lazy
|
||||
(\str -> button [ onClick SampleMsg ] [ text str ])
|
||||
"click me"
|
||||
]
|
||||
|
||||
|
||||
sampleMappedHtml : Html Msg
|
||||
sampleMappedHtml =
|
||||
div [ Attr.class "container" ]
|
||||
[ Html.map (always MappedSampleMsg) (button [ onClick SampleMsg ] [ text "click me" ])
|
||||
]
|
||||
|
||||
|
||||
sampleMappedLazyHtml : Html Msg
|
||||
sampleMappedLazyHtml =
|
||||
div [ Attr.class "container" ]
|
||||
[ Html.map (always MappedSampleMsg) <|
|
||||
Lazy.lazy
|
||||
(\str -> button [ onClick SampleMsg ] [ text str ])
|
||||
"click me"
|
||||
]
|
||||
|
||||
|
||||
sampleMappedKeyedHtml : Html Msg
|
||||
sampleMappedKeyedHtml =
|
||||
div [ Attr.class "container" ]
|
||||
[ Html.map (always MappedSampleMsg) <|
|
||||
Keyed.node "button"
|
||||
[ onClick SampleMsg ]
|
||||
[ ( "key", text "click me" ) ]
|
||||
]
|
||||
|
||||
|
||||
deepMappedHtml : Html Msg
|
||||
deepMappedHtml =
|
||||
div []
|
||||
[ Html.map SampleInputMsg
|
||||
(div []
|
||||
[ Html.map (\msg -> msg ++ "bar")
|
||||
(div []
|
||||
[ input [ onInput identity ] []
|
||||
]
|
||||
)
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
testEvent : (Msg -> Html.Attribute Msg) -> ( String, Value ) -> Test
|
||||
testEvent testOn (( eventName, eventValue ) as event) =
|
||||
test ("returns msg for " ++ eventName ++ "(" ++ toString eventValue ++ ") event") <|
|
||||
\() ->
|
||||
input [ testOn SampleMsg ] []
|
||||
|> Query.fromHtml
|
||||
|> Event.simulate event
|
||||
|> Event.expect SampleMsg
|
||||
321
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/tests/Queries.elm
vendored
Normal file
321
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/tests/Queries.elm
vendored
Normal file
@@ -0,0 +1,321 @@
|
||||
module Queries exposing (..)
|
||||
|
||||
import Expect
|
||||
import Html exposing (Html, a, div, footer, header, li, section, span, ul)
|
||||
import Html.Attributes as Attr exposing (href)
|
||||
import Html.Lazy as Lazy
|
||||
import Test exposing (..)
|
||||
import Test.Html.Query as Query exposing (Single)
|
||||
import Test.Html.Selector exposing (..)
|
||||
|
||||
|
||||
htmlTests : Test
|
||||
htmlTests =
|
||||
describe "Html" <|
|
||||
List.map (\toTest -> toTest (Query.fromHtml sampleHtml)) testers
|
||||
|
||||
|
||||
lazyTests : Test
|
||||
lazyTests =
|
||||
describe "lazy Html" <|
|
||||
List.map (\toTest -> toTest (Query.fromHtml sampleLazyHtml)) testers
|
||||
|
||||
|
||||
testers : List (Single msg -> Test)
|
||||
testers =
|
||||
[ testFindAll
|
||||
, testKeep
|
||||
, testFind
|
||||
, testRoot
|
||||
, testFirst
|
||||
, testIndex
|
||||
, testChildren
|
||||
]
|
||||
|
||||
|
||||
testRoot : Single msg -> Test
|
||||
testRoot output =
|
||||
describe "root query without find or findAll"
|
||||
[ describe "finds itself" <|
|
||||
[ test "sees it's a <section class='root'>" <|
|
||||
\() ->
|
||||
output
|
||||
|> Expect.all
|
||||
[ Query.has [ class "root" ]
|
||||
, Query.has [ tag "section" ]
|
||||
]
|
||||
, test "recognizes its exact className" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.has [ exactClassName "root" ]
|
||||
, test "recognizes its class by classes" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.has [ classes [ "root" ] ]
|
||||
, test "recognizes its style by a single css property" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.has [ style [ ( "color", "red" ) ] ]
|
||||
, test "recognizes its style by multiple css properties" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.has [ style [ ( "color", "red" ), ( "background", "purple" ) ] ]
|
||||
, test "recognizes its style does not include a css property" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.hasNot [ style [ ( "color", "green" ) ] ]
|
||||
, test "recognizes if is has a specific descendant" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.contains [ someView "Such a title !" ]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
testFind : Single msg -> Test
|
||||
testFind output =
|
||||
describe "Query.find []"
|
||||
[ describe "finds the one child" <|
|
||||
[ test "sees it's a <div class='container'>" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.find []
|
||||
|> Expect.all
|
||||
[ Query.has [ class "container" ]
|
||||
, Query.has [ tag "div" ]
|
||||
]
|
||||
, test "recognizes its exact className" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.find []
|
||||
|> Query.has [ exactClassName "container" ]
|
||||
, test "recognizes its class by classes" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.find []
|
||||
|> Query.has [ classes [ "container" ] ]
|
||||
, test "recognizes its style by style list" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.has [ style [ ( "color", "blue" ) ] ]
|
||||
, test "recognizes if is has a specific descendant" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.find []
|
||||
|> Query.contains [ someView "Such a title !" ]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
testFindAll : Single msg -> Test
|
||||
testFindAll output =
|
||||
describe "Query.findAll []"
|
||||
[ describe "finds the one child" <|
|
||||
[ test "and only the one child" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.findAll []
|
||||
|> Query.count (Expect.equal 1)
|
||||
, test "sees it's a <div class='container'>" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.findAll []
|
||||
|> Expect.all
|
||||
[ Query.each (Query.has [ class "container" ])
|
||||
, Query.each (Query.has [ tag "div" ])
|
||||
]
|
||||
, test "recognizes its exact className" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.findAll []
|
||||
|> Query.each (Query.has [ exactClassName "container" ])
|
||||
, test "recognizes its class by classes" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.findAll []
|
||||
|> Query.each (Query.has [ classes [ "container" ] ])
|
||||
]
|
||||
, describe "finds multiple descendants"
|
||||
[ test "with tag selectors that return one match at the start" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.findAll [ tag "header" ]
|
||||
|> Query.count (Expect.equal 1)
|
||||
, test "with tag selectors that return multiple matches" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.findAll [ tag "section" ]
|
||||
|> Query.count (Expect.equal 2)
|
||||
, test "with tag selectors that return one match at the end" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.find [ tag "footer" ]
|
||||
|> Query.has [ text "this is the footer" ]
|
||||
, test "sees the nested div" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.findAll [ tag "div" ]
|
||||
|> Query.count (Expect.equal 2)
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
testKeep : Single msg -> Test
|
||||
testKeep output =
|
||||
describe "Query.keep"
|
||||
[ test "only keep a subsect of a result" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.findAll [ tag "section" ]
|
||||
|> Query.keep (tag "ul")
|
||||
|> Query.keep (class "list-item")
|
||||
|> Expect.all
|
||||
[ Query.each (Query.has [ tag "li" ])
|
||||
, Query.first >> Query.has [ text "first item" ]
|
||||
]
|
||||
, test "keep from the second section as well" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.findAll [ tag "section" ]
|
||||
|> Query.keep (class "nested-div")
|
||||
|> Query.first
|
||||
|> Query.has [ text "boring section" ]
|
||||
, test "keep elements from both matches" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.findAll [ tag "section" ]
|
||||
|> Query.keep (class "tooltip-questions")
|
||||
|> Query.count (Expect.equal 2)
|
||||
]
|
||||
|
||||
|
||||
testFirst : Single msg -> Test
|
||||
testFirst output =
|
||||
describe "Query.first"
|
||||
[ describe "finds the one child" <|
|
||||
[ test "sees it's a <div class='container'>" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.findAll []
|
||||
|> Query.first
|
||||
|> Query.has [ tag "div", class "container" ]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
testIndex : Single msg -> Test
|
||||
testIndex output =
|
||||
describe "Query.index"
|
||||
[ describe "Query.index 0" <|
|
||||
[ test "sees it's a <div class='container'>" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.findAll []
|
||||
|> Query.index 0
|
||||
|> Query.has [ tag "div", class "container" ]
|
||||
]
|
||||
, describe "Query.index -1" <|
|
||||
[ test "sees it's a <div class='container'>" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.findAll []
|
||||
|> Query.index -1
|
||||
|> Query.has [ tag "div", class "container" ]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
testChildren : Single msg -> Test
|
||||
testChildren output =
|
||||
describe "Query.children"
|
||||
[ describe "on the root" <|
|
||||
[ test "sees the root has one child" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.children []
|
||||
|> Expect.all
|
||||
[ Query.count (Expect.equal 1)
|
||||
, Query.each (Query.hasNot [ class "root" ])
|
||||
]
|
||||
, test "doesn't see the nested div" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.children [ class "nested-div" ]
|
||||
|> Query.count (Expect.equal 0)
|
||||
, test "only children which match the selector get returned" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.find [ class "some-list" ]
|
||||
|> Query.children [ class "selected" ]
|
||||
|> Query.count (Expect.equal 1)
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
sampleHtml : Html msg
|
||||
sampleHtml =
|
||||
section [ Attr.class "root", Attr.style [ ( "color", "red" ), ( "background", "purple" ), ( "font-weight", "bold" ) ] ]
|
||||
[ div [ Attr.class "container", Attr.style [ ( "color", "blue" ) ] ]
|
||||
[ header [ Attr.class "funky themed", Attr.id "heading" ]
|
||||
[ a [ href "http://elm-lang.org" ] [ Html.text "home" ]
|
||||
, a [ href "http://elm-lang.org/examples" ] [ Html.text "examples" ]
|
||||
, a [ href "http://elm-lang.org/docs" ] [ Html.text "docs" ]
|
||||
]
|
||||
, someView "Such a title !"
|
||||
, section [ Attr.class "funky themed", Attr.id "section" ]
|
||||
[ ul [ Attr.class "some-list" ]
|
||||
[ li [ Attr.class "list-item themed" ] [ Html.text "first item" ]
|
||||
, li [ Attr.class "list-item themed" ] [ Html.text "second item" ]
|
||||
, li [ Attr.class "list-item themed selected" ] [ Html.text "third item" ]
|
||||
, li [ Attr.class "list-item themed" ] [ Html.text "fourth item" ]
|
||||
, span [ Attr.class "tooltip-questions" ] [ Html.text "?" ]
|
||||
]
|
||||
]
|
||||
, section []
|
||||
[ div [ Attr.class "nested-div" ] [ Html.text "boring section" ]
|
||||
, span [ Attr.class "tooltip-questions" ] [ Html.text "?" ]
|
||||
]
|
||||
, footer []
|
||||
[ Html.text "this is the footer"
|
||||
, span [ Attr.class "tooltip-questions" ] [ Html.text "?" ]
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
sampleLazyHtml : Html msg
|
||||
sampleLazyHtml =
|
||||
section [ Attr.class "root", Attr.style [ ( "color", "red" ), ( "background", "purple" ), ( "font-weight", "bold" ) ] ]
|
||||
[ div [ Attr.class "container", Attr.style [ ( "color", "blue" ) ] ]
|
||||
[ header [ Attr.class "funky themed", Attr.id "heading" ]
|
||||
[ Lazy.lazy (\str -> a [ href "http://elm-lang.org" ] [ Html.text str ]) "home"
|
||||
, Lazy.lazy (\str -> a [ href "http://elm-lang.org/examples" ] [ Html.text str ]) "examples"
|
||||
, Lazy.lazy (\str -> a [ href "http://elm-lang.org/docs" ] [ Html.text str ]) "docs"
|
||||
]
|
||||
, someView "Such a title !"
|
||||
, section [ Attr.class "funky themed", Attr.id "section" ]
|
||||
[ ul [ Attr.class "some-list" ]
|
||||
[ Lazy.lazy (\str -> li [ Attr.class "list-item themed" ] [ Html.text str ]) "first item"
|
||||
, Lazy.lazy (\str -> li [ Attr.class "list-item themed" ] [ Html.text str ]) "second item"
|
||||
, Lazy.lazy (\str -> li [ Attr.class "list-item themed selected" ] [ Html.text str ]) "third item"
|
||||
, Lazy.lazy (\str -> li [ Attr.class "list-item themed" ] [ Html.text str ]) "fourth item"
|
||||
, Lazy.lazy (\str -> span [ Attr.class "tooltip-questions" ] [ Html.text str ]) "?"
|
||||
]
|
||||
]
|
||||
, section []
|
||||
[ div [ Attr.class "nested-div" ]
|
||||
[ Html.text "boring section"
|
||||
, Lazy.lazy (\str -> span [ Attr.class "tooltip-questions" ] [ Html.text str ]) "?"
|
||||
]
|
||||
]
|
||||
, footer []
|
||||
[ Lazy.lazy2 (\a b -> Html.text <| a ++ b) "this is " "the footer"
|
||||
, Lazy.lazy (\str -> span [ Attr.class "tooltip-questions" ] [ Html.text str ]) "?"
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
someView : String -> Html msg
|
||||
someView str =
|
||||
Html.h1 [] [ Html.text str ]
|
||||
51
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/tests/TestExample.elm
vendored
Normal file
51
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/tests/TestExample.elm
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
module TestExample exposing (all)
|
||||
|
||||
import Expect
|
||||
import Html.Attributes exposing (href)
|
||||
import Test exposing (..)
|
||||
import Test.Html.Query as Query
|
||||
import Test.Html.Selector exposing (..)
|
||||
import ExampleApp exposing (exampleModel, view)
|
||||
|
||||
|
||||
all : Test
|
||||
all =
|
||||
let
|
||||
output =
|
||||
view exampleModel
|
||||
|> Query.fromHtml
|
||||
in
|
||||
describe "view exampleModel"
|
||||
[ test "expect 4x <li> somewhere on the page" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.findAll [ tag "li" ]
|
||||
|> Query.count (Expect.equal 4)
|
||||
, test "expect 4x <li> inside a <ul>" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.find [ tag "ul" ]
|
||||
|> Query.findAll [ tag "li" ]
|
||||
|> Query.count (Expect.equal 4)
|
||||
, test "expect header to have 3 links in it" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.findAll [ tag "a" ]
|
||||
|> Query.count (Expect.equal 3)
|
||||
, test "expect header to have a link to the Elm homepage" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.find [ id "heading" ]
|
||||
|> Query.has [ attribute <| href "http://elm-lang.org" ]
|
||||
, test "expect footer to have footer text" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.find [ tag "footer" ]
|
||||
|> Query.has [ tag "footer", text "this is the footer" ]
|
||||
, test "expect each <li> to have classes list-item and themed" <|
|
||||
\() ->
|
||||
output
|
||||
|> Query.find [ tag "ul" ]
|
||||
|> Query.findAll [ tag "li" ]
|
||||
|> Query.each (Query.has [ classes [ "list-item", "themed" ] ])
|
||||
]
|
||||
21
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/tests/elm-package.json
vendored
Normal file
21
part9/tests/elm-stuff/packages/eeue56/elm-html-test/5.1.2/tests/elm-package.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"summary": "helpful summary of your project, less than 80 characters",
|
||||
"repository": "https://github.com/eeue56/elm-html-test.git",
|
||||
"license": "BSD3",
|
||||
"source-directories": [
|
||||
".",
|
||||
"../src",
|
||||
"../examples"
|
||||
],
|
||||
"exposed-modules": [],
|
||||
"native-modules": true,
|
||||
"dependencies": {
|
||||
"eeue56/elm-html-in-elm": "5.1.0 <= v < 6.0.0",
|
||||
"eeue56/elm-html-query": "3.0.0 <= v < 4.0.0",
|
||||
"elm-community/elm-test": "4.0.0 <= v < 5.0.0",
|
||||
"elm-lang/core": "5.0.0 <= v < 6.0.0",
|
||||
"elm-lang/html": "2.0.0 <= v < 3.0.0"
|
||||
},
|
||||
"elm-version": "0.18.0 <= v < 0.19.0"
|
||||
}
|
||||
4
part9/tests/elm-stuff/packages/eeue56/elm-lazy-list/1.0.0/.gitignore
vendored
Normal file
4
part9/tests/elm-stuff/packages/eeue56/elm-lazy-list/1.0.0/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# elm-package generated files
|
||||
elm-stuff
|
||||
# elm-repl generated files
|
||||
repl-temp-*
|
||||
29
part9/tests/elm-stuff/packages/eeue56/elm-lazy-list/1.0.0/LICENSE
vendored
Normal file
29
part9/tests/elm-stuff/packages/eeue56/elm-lazy-list/1.0.0/LICENSE
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2017, Noah
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
9
part9/tests/elm-stuff/packages/eeue56/elm-lazy-list/1.0.0/README.md
vendored
Normal file
9
part9/tests/elm-stuff/packages/eeue56/elm-lazy-list/1.0.0/README.md
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
# elm-lazy-list
|
||||
|
||||
This package is used to represent an infinite list of values, to be computed as they are needed. It is mainly designed for use with Elm test.
|
||||
|
||||
|
||||
singleton 5
|
||||
|> cons 6
|
||||
-- only evaluated here!
|
||||
|> toList --> 6, 5
|
||||
16
part9/tests/elm-stuff/packages/eeue56/elm-lazy-list/1.0.0/elm-package.json
vendored
Normal file
16
part9/tests/elm-stuff/packages/eeue56/elm-lazy-list/1.0.0/elm-package.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"summary": "A lazy list of values in pure Elm",
|
||||
"repository": "https://github.com/eeue56/elm-lazy-list.git",
|
||||
"license": "BSD3",
|
||||
"source-directories": [
|
||||
"src"
|
||||
],
|
||||
"exposed-modules": ["Lazy.List"],
|
||||
"dependencies": {
|
||||
"eeue56/elm-lazy": "1.0.0 <= v < 2.0.0",
|
||||
"elm-lang/core": "5.1.1 <= v < 6.0.0",
|
||||
"elm-lang/html": "2.0.0 <= v < 3.0.0"
|
||||
},
|
||||
"elm-version": "0.18.0 <= v < 0.19.0"
|
||||
}
|
||||
748
part9/tests/elm-stuff/packages/eeue56/elm-lazy-list/1.0.0/src/Lazy/List.elm
vendored
Normal file
748
part9/tests/elm-stuff/packages/eeue56/elm-lazy-list/1.0.0/src/Lazy/List.elm
vendored
Normal file
@@ -0,0 +1,748 @@
|
||||
module Lazy.List exposing (..)
|
||||
|
||||
{-| Lazy list implementation in Elm.
|
||||
|
||||
# Types
|
||||
@docs LazyList, LazyListView
|
||||
|
||||
# Constructors
|
||||
@docs cons, empty, singleton
|
||||
|
||||
# Query operations
|
||||
@docs isEmpty, head, tail, headAndTail, member, length
|
||||
|
||||
# Conversions
|
||||
@docs toList, fromList, toArray, fromArray
|
||||
|
||||
# Map-reduce et al.
|
||||
@docs map, zip, reduce, flatten, append, foldl, foldr
|
||||
|
||||
# Common operations
|
||||
@docs intersperse, interleave, reverse, cycle, iterate, repeat, take, takeWhile, drop, dropWhile
|
||||
|
||||
# Filtering operations
|
||||
@docs keepIf, dropIf, filterMap, unique
|
||||
|
||||
# Chaining operations
|
||||
@docs andMap, andThen
|
||||
|
||||
# Useful math stuff
|
||||
@docs numbers, sum, product
|
||||
|
||||
# All the maps!
|
||||
@docs map2, map3, map4, map5
|
||||
|
||||
# All the zips!
|
||||
@docs zip3, zip4, zip5
|
||||
|
||||
# All the Cartesian products!
|
||||
**Warning:** Calling these functions on large lists and then calling `toList` can easily overflow the stack. Consider
|
||||
passing the results to `take aConstantNumber`.
|
||||
|
||||
@docs product2, product3, product4, product5
|
||||
|
||||
# Infix Operators
|
||||
@docs (:::), (+++)
|
||||
|
||||
-}
|
||||
|
||||
import Array exposing (Array)
|
||||
import List
|
||||
import Random exposing (Generator, Seed)
|
||||
import Lazy exposing (Lazy, lazy, force)
|
||||
|
||||
|
||||
{-| Analogous to `List` type. This is the actual implementation type for the
|
||||
`LazyList` type. This type is exposed to the user if the user so wishes to
|
||||
do pattern matching or understand how the list type works. It is not
|
||||
recommended to work with this type directly. Try working solely with the
|
||||
provided functions in the package.
|
||||
-}
|
||||
type LazyListView a
|
||||
= Nil
|
||||
| Cons a (LazyList a)
|
||||
|
||||
|
||||
{-| Lazy List type.
|
||||
-}
|
||||
type alias LazyList a =
|
||||
Lazy (LazyListView a)
|
||||
|
||||
|
||||
{-| Create an empty list.
|
||||
-}
|
||||
empty : LazyList a
|
||||
empty =
|
||||
lazy <|
|
||||
\() -> Nil
|
||||
|
||||
|
||||
{-| Create a singleton list.
|
||||
-}
|
||||
singleton : a -> LazyList a
|
||||
singleton a =
|
||||
cons a empty
|
||||
|
||||
|
||||
{-| Detect if a list is empty or not.
|
||||
-}
|
||||
isEmpty : LazyList a -> Bool
|
||||
isEmpty list =
|
||||
case force list of
|
||||
Nil ->
|
||||
True
|
||||
|
||||
_ ->
|
||||
False
|
||||
|
||||
|
||||
{-| Add a value to the front of a list.
|
||||
-}
|
||||
cons : a -> LazyList a -> LazyList a
|
||||
cons a list =
|
||||
lazy <|
|
||||
\() ->
|
||||
Cons a list
|
||||
|
||||
|
||||
{-| Get the head of a list.
|
||||
-}
|
||||
head : LazyList a -> Maybe a
|
||||
head list =
|
||||
case force list of
|
||||
Nil ->
|
||||
Nothing
|
||||
|
||||
Cons first _ ->
|
||||
Just first
|
||||
|
||||
|
||||
{-| Get the tail of a list.
|
||||
-}
|
||||
tail : LazyList a -> Maybe (LazyList a)
|
||||
tail list =
|
||||
case force list of
|
||||
Nil ->
|
||||
Nothing
|
||||
|
||||
Cons _ rest ->
|
||||
Just rest
|
||||
|
||||
|
||||
{-| Get the head and tail of a list.
|
||||
-}
|
||||
headAndTail : LazyList a -> Maybe ( a, LazyList a )
|
||||
headAndTail list =
|
||||
case force list of
|
||||
Nil ->
|
||||
Nothing
|
||||
|
||||
Cons first rest ->
|
||||
Just ( first, rest )
|
||||
|
||||
|
||||
{-| Repeat a value ad infinitum.
|
||||
Be careful when you use this. The result of this is a truly infinite list.
|
||||
Do not try calling `reduce` or `toList` on an infinite list as it'll never
|
||||
finish computing. Make sure you then filter it down to a finite list with `head`
|
||||
or `take` or something.
|
||||
-}
|
||||
repeat : a -> LazyList a
|
||||
repeat a =
|
||||
lazy <|
|
||||
\() ->
|
||||
Cons a (repeat a)
|
||||
|
||||
|
||||
{-| Append a list to another list.
|
||||
-}
|
||||
append : LazyList a -> LazyList a -> LazyList a
|
||||
append list1 list2 =
|
||||
lazy <|
|
||||
\() ->
|
||||
case force list1 of
|
||||
Nil ->
|
||||
force list2
|
||||
|
||||
Cons first rest ->
|
||||
force (first ::: rest +++ list2)
|
||||
|
||||
|
||||
{-| Interleave the elements of a list in another list. The two lists get
|
||||
interleaved at the end.
|
||||
-}
|
||||
interleave : LazyList a -> LazyList a -> LazyList a
|
||||
interleave list1 list2 =
|
||||
lazy <|
|
||||
\() ->
|
||||
case force list1 of
|
||||
Nil ->
|
||||
force list2
|
||||
|
||||
Cons first1 rest1 ->
|
||||
case force list2 of
|
||||
Nil ->
|
||||
force list1
|
||||
|
||||
Cons first2 rest2 ->
|
||||
force (first1 ::: first2 ::: interleave rest1 rest2)
|
||||
|
||||
|
||||
{-| Places the given value between all members of the given list.
|
||||
-}
|
||||
intersperse : a -> LazyList a -> LazyList a
|
||||
intersperse a list =
|
||||
lazy <|
|
||||
\() ->
|
||||
case force list of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first rest ->
|
||||
case force rest of
|
||||
Nil ->
|
||||
force (first ::: empty)
|
||||
|
||||
Cons second tail ->
|
||||
case force tail of
|
||||
Nil ->
|
||||
force (first ::: a ::: second ::: empty)
|
||||
|
||||
_ ->
|
||||
force (first ::: a ::: second ::: a ::: intersperse a tail)
|
||||
|
||||
|
||||
{-| Take a list and repeat it ad infinitum. This cycles a finite list
|
||||
by putting the front after the end of the list. This results in a no-op in
|
||||
the case of an infinite list.
|
||||
-}
|
||||
cycle : LazyList a -> LazyList a
|
||||
cycle list =
|
||||
list
|
||||
+++ (lazy <|
|
||||
\() ->
|
||||
force (cycle list)
|
||||
)
|
||||
|
||||
|
||||
{-| Create an infinite list of applications of a function on some value.
|
||||
|
||||
Equivalent to:
|
||||
|
||||
x ::: f x ::: f (f x) ::: f (f (f x)) ::: ... -- etc...
|
||||
-}
|
||||
iterate : (a -> a) -> a -> LazyList a
|
||||
iterate f a =
|
||||
lazy <|
|
||||
\() ->
|
||||
Cons a (iterate f (f a))
|
||||
|
||||
|
||||
{-| The infinite list of counting numbers.
|
||||
|
||||
i.e.:
|
||||
|
||||
1 ::: 2 ::: 3 ::: 4 ::: 5 ::: ... -- etc...
|
||||
-}
|
||||
numbers : LazyList number
|
||||
numbers =
|
||||
iterate ((+) 1) 1
|
||||
|
||||
|
||||
{-| Take at most `n` many values from a list.
|
||||
-}
|
||||
take : Int -> LazyList a -> LazyList a
|
||||
take n list =
|
||||
lazy <|
|
||||
\() ->
|
||||
if n <= 0 then
|
||||
Nil
|
||||
else
|
||||
case force list of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first rest ->
|
||||
Cons first (take (n - 1) rest)
|
||||
|
||||
|
||||
{-| Take elements from a list as long as the predicate is satisfied.
|
||||
-}
|
||||
takeWhile : (a -> Bool) -> LazyList a -> LazyList a
|
||||
takeWhile predicate list =
|
||||
lazy <|
|
||||
\() ->
|
||||
case force list of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first rest ->
|
||||
if predicate first then
|
||||
Cons first (takeWhile predicate rest)
|
||||
else
|
||||
Nil
|
||||
|
||||
|
||||
{-| Drop at most `n` many values from a list.
|
||||
-}
|
||||
drop : Int -> LazyList a -> LazyList a
|
||||
drop n list =
|
||||
lazy <|
|
||||
\() ->
|
||||
if n <= 0 then
|
||||
force list
|
||||
else
|
||||
case force list of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first rest ->
|
||||
force (drop (n - 1) rest)
|
||||
|
||||
|
||||
{-| Drop elements from a list as long as the predicate is satisfied.
|
||||
-}
|
||||
dropWhile : (a -> Bool) -> LazyList a -> LazyList a
|
||||
dropWhile predicate list =
|
||||
lazy <|
|
||||
\() ->
|
||||
case force list of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first rest ->
|
||||
if predicate first then
|
||||
force (dropWhile predicate rest)
|
||||
else
|
||||
force list
|
||||
|
||||
|
||||
{-| Test if a value is a member of a list.
|
||||
-}
|
||||
member : a -> LazyList a -> Bool
|
||||
member a list =
|
||||
case force list of
|
||||
Nil ->
|
||||
False
|
||||
|
||||
Cons first rest ->
|
||||
first == a || member a rest
|
||||
|
||||
|
||||
{-| Get the length of a lazy list.
|
||||
|
||||
Warning: This will not terminate if the list is infinite.
|
||||
-}
|
||||
length : LazyList a -> Int
|
||||
length =
|
||||
reduce (\_ n -> n + 1) 0
|
||||
|
||||
|
||||
{-| Remove all duplicates from a list and return a list of distinct elements.
|
||||
-}
|
||||
unique : LazyList a -> LazyList a
|
||||
unique list =
|
||||
lazy <|
|
||||
\() ->
|
||||
case force list of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first rest ->
|
||||
if member first rest then
|
||||
force (unique rest)
|
||||
else
|
||||
Cons first (unique rest)
|
||||
|
||||
|
||||
{-| Keep all elements in a list that satisfy the given predicate.
|
||||
-}
|
||||
keepIf : (a -> Bool) -> LazyList a -> LazyList a
|
||||
keepIf predicate list =
|
||||
lazy <|
|
||||
\() ->
|
||||
case force list of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first rest ->
|
||||
if predicate first then
|
||||
Cons first (keepIf predicate rest)
|
||||
else
|
||||
force (keepIf predicate rest)
|
||||
|
||||
|
||||
{-| Drop all elements in a list that satisfy the given predicate.
|
||||
-}
|
||||
dropIf : (a -> Bool) -> LazyList a -> LazyList a
|
||||
dropIf predicate =
|
||||
keepIf (\n -> not (predicate n))
|
||||
|
||||
|
||||
{-| Map a function that may fail over a lazy list, keeping only
|
||||
the values that were successfully transformed.
|
||||
-}
|
||||
filterMap : (a -> Maybe b) -> LazyList a -> LazyList b
|
||||
filterMap transform list =
|
||||
lazy <|
|
||||
\() ->
|
||||
case force list of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first rest ->
|
||||
case transform first of
|
||||
Just val ->
|
||||
Cons val (filterMap transform rest)
|
||||
|
||||
Nothing ->
|
||||
force (filterMap transform rest)
|
||||
|
||||
|
||||
{-| Reduce a list with a given reducer and an initial value.
|
||||
|
||||
Example :
|
||||
reduce (+) 0 (1 ::: 2 ::: 3 ::: 4 ::: empty) == 10
|
||||
-}
|
||||
reduce : (a -> b -> b) -> b -> LazyList a -> b
|
||||
reduce reducer b list =
|
||||
case force list of
|
||||
Nil ->
|
||||
b
|
||||
|
||||
Cons first rest ->
|
||||
reduce reducer (reducer first b) rest
|
||||
|
||||
|
||||
{-| Analogous to `List.foldl`. Is an alias for `reduce`.
|
||||
-}
|
||||
foldl : (a -> b -> b) -> b -> LazyList a -> b
|
||||
foldl =
|
||||
reduce
|
||||
|
||||
|
||||
{-| Analogous to `List.foldr`.
|
||||
-}
|
||||
foldr : (a -> b -> b) -> b -> LazyList a -> b
|
||||
foldr reducer b list =
|
||||
Array.foldr reducer b (toArray list)
|
||||
|
||||
|
||||
{-| Get the sum of a list of numbers.
|
||||
-}
|
||||
sum : LazyList number -> number
|
||||
sum =
|
||||
reduce (+) 0
|
||||
|
||||
|
||||
{-| Get the product of a list of numbers.
|
||||
-}
|
||||
product : LazyList number -> number
|
||||
product =
|
||||
reduce (*) 1
|
||||
|
||||
|
||||
{-| Flatten a list of lists into a single list by appending all the inner
|
||||
lists into one big list.
|
||||
-}
|
||||
flatten : LazyList (LazyList a) -> LazyList a
|
||||
flatten list =
|
||||
lazy <|
|
||||
\() ->
|
||||
case force list of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first rest ->
|
||||
force (first +++ flatten rest)
|
||||
|
||||
|
||||
{-| Chain list producing operations. Map then flatten.
|
||||
-}
|
||||
andThen : (a -> LazyList b) -> LazyList a -> LazyList b
|
||||
andThen f list =
|
||||
map f list |> flatten
|
||||
|
||||
|
||||
{-| Reverse a list.
|
||||
-}
|
||||
reverse : LazyList a -> LazyList a
|
||||
reverse =
|
||||
reduce cons empty
|
||||
|
||||
|
||||
{-| Map a function to a list.
|
||||
-}
|
||||
map : (a -> b) -> LazyList a -> LazyList b
|
||||
map f list =
|
||||
lazy <|
|
||||
\() ->
|
||||
case force list of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first rest ->
|
||||
Cons (f first) (map f rest)
|
||||
|
||||
|
||||
{-| -}
|
||||
map2 : (a -> b -> c) -> LazyList a -> LazyList b -> LazyList c
|
||||
map2 f list1 list2 =
|
||||
lazy <|
|
||||
\() ->
|
||||
case force list1 of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first1 rest1 ->
|
||||
case force list2 of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first2 rest2 ->
|
||||
Cons (f first1 first2) (map2 f rest1 rest2)
|
||||
|
||||
|
||||
{-| Known as `mapN` in some circles. Allows you to apply `map` in cases
|
||||
where then number of arguments are greater than 5.
|
||||
|
||||
The argument order is such that it works well with `|>` chains.
|
||||
-}
|
||||
andMap : LazyList a -> LazyList (a -> b) -> LazyList b
|
||||
andMap listVal listFuncs =
|
||||
map2 (<|) listFuncs listVal
|
||||
|
||||
|
||||
{-| -}
|
||||
map3 : (a -> b -> c -> d) -> LazyList a -> LazyList b -> LazyList c -> LazyList d
|
||||
map3 f list1 list2 list3 =
|
||||
lazy <|
|
||||
\() ->
|
||||
case force list1 of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first1 rest1 ->
|
||||
case force list2 of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first2 rest2 ->
|
||||
case force list3 of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first3 rest3 ->
|
||||
Cons (f first1 first2 first3) (map3 f rest1 rest2 rest3)
|
||||
|
||||
|
||||
{-| -}
|
||||
map4 : (a -> b -> c -> d -> e) -> LazyList a -> LazyList b -> LazyList c -> LazyList d -> LazyList e
|
||||
map4 f list1 list2 list3 list4 =
|
||||
lazy <|
|
||||
\() ->
|
||||
case force list1 of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first1 rest1 ->
|
||||
case force list2 of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first2 rest2 ->
|
||||
case force list3 of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first3 rest3 ->
|
||||
case force list4 of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first4 rest4 ->
|
||||
Cons (f first1 first2 first3 first4) (map4 f rest1 rest2 rest3 rest4)
|
||||
|
||||
|
||||
{-| -}
|
||||
map5 : (a -> b -> c -> d -> e -> f) -> LazyList a -> LazyList b -> LazyList c -> LazyList d -> LazyList e -> LazyList f
|
||||
map5 f list1 list2 list3 list4 list5 =
|
||||
lazy <|
|
||||
\() ->
|
||||
case force list1 of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first1 rest1 ->
|
||||
case force list2 of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first2 rest2 ->
|
||||
case force list3 of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first3 rest3 ->
|
||||
case force list4 of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first4 rest4 ->
|
||||
case force list5 of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first5 rest5 ->
|
||||
Cons
|
||||
(f first1 first2 first3 first4 first5)
|
||||
(map5 f rest1 rest2 rest3 rest4 rest5)
|
||||
|
||||
|
||||
{-| -}
|
||||
zip : LazyList a -> LazyList b -> LazyList ( a, b )
|
||||
zip =
|
||||
map2 (,)
|
||||
|
||||
|
||||
{-| -}
|
||||
zip3 : LazyList a -> LazyList b -> LazyList c -> LazyList ( a, b, c )
|
||||
zip3 =
|
||||
map3 (,,)
|
||||
|
||||
|
||||
{-| -}
|
||||
zip4 : LazyList a -> LazyList b -> LazyList c -> LazyList d -> LazyList ( a, b, c, d )
|
||||
zip4 =
|
||||
map4 (,,,)
|
||||
|
||||
|
||||
{-| -}
|
||||
zip5 : LazyList a -> LazyList b -> LazyList c -> LazyList d -> LazyList e -> LazyList ( a, b, c, d, e )
|
||||
zip5 =
|
||||
map5 (,,,,)
|
||||
|
||||
|
||||
{-| Create a lazy list containing all possible pairs in the given lazy lists.
|
||||
-}
|
||||
product2 : LazyList a -> LazyList b -> LazyList ( a, b )
|
||||
product2 list1 list2 =
|
||||
lazy <|
|
||||
\() ->
|
||||
case force list1 of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first1 rest1 ->
|
||||
case force list2 of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons _ _ ->
|
||||
force <| map ((,) first1) list2 +++ product2 rest1 list2
|
||||
|
||||
|
||||
{-| Create a lazy list containing all possible triples in the given lazy lists.
|
||||
-}
|
||||
product3 : LazyList a -> LazyList b -> LazyList c -> LazyList ( a, b, c )
|
||||
product3 list1 list2 list3 =
|
||||
lazy <|
|
||||
\() ->
|
||||
case force list1 of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first1 rest1 ->
|
||||
force <| map (\( b, c ) -> ( first1, b, c )) (product2 list2 list3) +++ product3 rest1 list2 list3
|
||||
|
||||
|
||||
{-| Create a lazy list containing all possible 4-tuples in the given lazy lists.
|
||||
-}
|
||||
product4 : LazyList a -> LazyList b -> LazyList c -> LazyList d -> LazyList ( a, b, c, d )
|
||||
product4 list1 list2 list3 list4 =
|
||||
lazy <|
|
||||
\() ->
|
||||
case force list1 of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first1 rest1 ->
|
||||
force <| map (\( b, c, d ) -> ( first1, b, c, d )) (product3 list2 list3 list4) +++ product4 rest1 list2 list3 list4
|
||||
|
||||
|
||||
{-| Create a lazy list containing all possible 5-tuples in the given lazy lists.
|
||||
-}
|
||||
product5 : LazyList a -> LazyList b -> LazyList c -> LazyList d -> LazyList e -> LazyList ( a, b, c, d, e )
|
||||
product5 list1 list2 list3 list4 list5 =
|
||||
lazy <|
|
||||
\() ->
|
||||
case force list1 of
|
||||
Nil ->
|
||||
Nil
|
||||
|
||||
Cons first1 rest1 ->
|
||||
force <| map (\( b, c, d, e ) -> ( first1, b, c, d, e )) (product4 list2 list3 list4 list5) +++ product5 rest1 list2 list3 list4 list5
|
||||
|
||||
|
||||
{-| Convert a lazy list to a normal list.
|
||||
-}
|
||||
toList : LazyList a -> List a
|
||||
toList list =
|
||||
case force list of
|
||||
Nil ->
|
||||
[]
|
||||
|
||||
Cons first rest ->
|
||||
first :: toList rest
|
||||
|
||||
|
||||
{-| Convert a normal list to a lazy list.
|
||||
-}
|
||||
fromList : List a -> LazyList a
|
||||
fromList =
|
||||
List.foldr cons empty
|
||||
|
||||
|
||||
{-| Convert a lazy list to an array.
|
||||
-}
|
||||
toArray : LazyList a -> Array a
|
||||
toArray list =
|
||||
case force list of
|
||||
Nil ->
|
||||
Array.empty
|
||||
|
||||
Cons first rest ->
|
||||
Array.append (Array.push first Array.empty) (toArray rest)
|
||||
|
||||
|
||||
{-| Convert an array to a lazy list.
|
||||
-}
|
||||
fromArray : Array a -> LazyList a
|
||||
fromArray =
|
||||
Array.foldr cons empty
|
||||
|
||||
|
||||
|
||||
---------------------
|
||||
-- INFIX OPERATORS --
|
||||
---------------------
|
||||
|
||||
|
||||
infixr 5 :::
|
||||
|
||||
|
||||
{-| Alias for `cons`. Analogous to `::` for lists.
|
||||
-}
|
||||
(:::) : a -> LazyList a -> LazyList a
|
||||
(:::) =
|
||||
cons
|
||||
|
||||
|
||||
infixr 5 +++
|
||||
|
||||
|
||||
{-| Alias for `append`. Analogous to `++` for lists.
|
||||
-}
|
||||
(+++) : LazyList a -> LazyList a -> LazyList a
|
||||
(+++) =
|
||||
append
|
||||
32
part9/tests/elm-stuff/packages/eeue56/elm-lazy-list/1.0.0/tests/Example.elm
vendored
Normal file
32
part9/tests/elm-stuff/packages/eeue56/elm-lazy-list/1.0.0/tests/Example.elm
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
module Example exposing (..)
|
||||
|
||||
import Expect exposing (Expectation)
|
||||
import Fuzz exposing (Fuzzer, list, int, string)
|
||||
import Test exposing (..)
|
||||
import Lazy.List exposing (..)
|
||||
|
||||
|
||||
suite : Test
|
||||
suite =
|
||||
describe "List.lazy"
|
||||
[ test "Empty things are empty"
|
||||
(\_ ->
|
||||
empty
|
||||
|> isEmpty
|
||||
|> Expect.true "Empty is empty"
|
||||
)
|
||||
, test "A list of two things has two things"
|
||||
(\_ ->
|
||||
singleton 5
|
||||
|> cons 6
|
||||
|> toList
|
||||
|> Expect.equal [ 6, 5 ]
|
||||
)
|
||||
, test "The sum is correctly computed"
|
||||
(\_ ->
|
||||
singleton 10
|
||||
|> cons 6
|
||||
|> sum
|
||||
|> Expect.equal 16
|
||||
)
|
||||
]
|
||||
19
part9/tests/elm-stuff/packages/eeue56/elm-lazy-list/1.0.0/tests/elm-package.json
vendored
Normal file
19
part9/tests/elm-stuff/packages/eeue56/elm-lazy-list/1.0.0/tests/elm-package.json
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"summary": "Test Suites",
|
||||
"repository": "https://github.com/user/project.git",
|
||||
"license": "BSD3",
|
||||
"source-directories": [
|
||||
"../src",
|
||||
"."
|
||||
],
|
||||
"exposed-modules": [],
|
||||
"dependencies": {
|
||||
"eeue56/elm-html-test": "4.1.0 <= v < 5.0.0",
|
||||
"eeue56/elm-lazy": "1.0.0 <= v < 2.0.0",
|
||||
"elm-community/elm-test": "4.0.0 <= v < 5.0.0",
|
||||
"elm-lang/core": "5.1.1 <= v < 6.0.0",
|
||||
"elm-lang/html": "2.0.0 <= v < 3.0.0"
|
||||
},
|
||||
"elm-version": "0.18.0 <= v < 0.19.0"
|
||||
}
|
||||
4
part9/tests/elm-stuff/packages/eeue56/elm-lazy/1.0.0/.gitignore
vendored
Normal file
4
part9/tests/elm-stuff/packages/eeue56/elm-lazy/1.0.0/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# elm-package generated files
|
||||
elm-stuff
|
||||
# elm-repl generated files
|
||||
repl-temp-*
|
||||
29
part9/tests/elm-stuff/packages/eeue56/elm-lazy/1.0.0/LICENSE
vendored
Normal file
29
part9/tests/elm-stuff/packages/eeue56/elm-lazy/1.0.0/LICENSE
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2017, Noah
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
32
part9/tests/elm-stuff/packages/eeue56/elm-lazy/1.0.0/README.md
vendored
Normal file
32
part9/tests/elm-stuff/packages/eeue56/elm-lazy/1.0.0/README.md
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
# elm-lazy
|
||||
|
||||
|
||||
This library provides a way of putting of computations until they are needed, allowing for expensive calculations later.
|
||||
|
||||
lazySum : Lazy Int
|
||||
lazySum =
|
||||
lazy (\() -> sum <| List.range 1 1000000)
|
||||
|
||||
It also gives you a way of storing a computed value so that you do not need to re-compute it.
|
||||
|
||||
lazySum : Int -> Lazy Int
|
||||
lazySum n =
|
||||
lazy (\() -> sum <| List.range 0 n)
|
||||
|
||||
|
||||
lazySums : List Int -> List (Lazy Int)
|
||||
lazySums sums =
|
||||
List.map lazySum sums
|
||||
|
||||
-- evaluates the head, before putting it back on the list
|
||||
evaluteCurrentSum : List (Lazy Int) -> List (Lazy Int)
|
||||
evaluteCurrentSum xs =
|
||||
case xs of
|
||||
head::rest -> Lazy.evaluate head :: rest
|
||||
_ -> []
|
||||
|
||||
|
||||
## Notes
|
||||
|
||||
|
||||
This is a library based originally on the old `Lazy` implementation. However, it is written entirely in pure Elm. The main difference is explicit memoization, as we no longer use side-effects to achieve laziness.
|
||||
171
part9/tests/elm-stuff/packages/eeue56/elm-lazy/1.0.0/benchmarks/CoreLazy.elm
vendored
Normal file
171
part9/tests/elm-stuff/packages/eeue56/elm-lazy/1.0.0/benchmarks/CoreLazy.elm
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
module CoreLazy
|
||||
exposing
|
||||
( Lazy
|
||||
, force
|
||||
, lazy
|
||||
, map
|
||||
, map2
|
||||
, map3
|
||||
, map4
|
||||
, map5
|
||||
, apply
|
||||
, andThen
|
||||
)
|
||||
|
||||
{-| This library lets you delay a computation until later.
|
||||
|
||||
# Basics
|
||||
@docs Lazy, lazy, force
|
||||
|
||||
# Mapping
|
||||
@docs map, map2, map3, map4, map5
|
||||
|
||||
# Chaining
|
||||
@docs apply, andThen
|
||||
-}
|
||||
|
||||
import Native.Lazy
|
||||
|
||||
|
||||
-- PRIMITIVES
|
||||
|
||||
|
||||
{-| A wrapper around a value that will be lazily evaluated.
|
||||
-}
|
||||
type Lazy a
|
||||
= Lazy (() -> a)
|
||||
|
||||
|
||||
{-| Delay the evaluation of a value until later. For example, maybe we will
|
||||
need to generate a very long list and find its sum, but we do not want to do
|
||||
it unless it is absolutely necessary.
|
||||
|
||||
lazySum : Lazy Int
|
||||
lazySum =
|
||||
lazy (\() -> sum [1..1000000])
|
||||
|
||||
Now we only pay for `lazySum` if we actually need it.
|
||||
-}
|
||||
lazy : (() -> a) -> Lazy a
|
||||
lazy thunk =
|
||||
Lazy (Native.Lazy.memoize thunk)
|
||||
|
||||
|
||||
{-| Force the evaluation of a lazy value. This means we only pay for the
|
||||
computation when we need it. Here is a rather contrived example.
|
||||
|
||||
lazySum : Lazy Int
|
||||
lazySum =
|
||||
lazy (\() -> List.sum [1..1000000])
|
||||
|
||||
sums : (Int, Int, Int)
|
||||
sums =
|
||||
(force lazySum, force lazySum, force lazySum)
|
||||
|
||||
We are forcing this computation three times. The cool thing is that the first
|
||||
time you `force` a value, the result is stored. This means you pay the cost on
|
||||
the first one, but all the rest are very cheap, basically just looking up a
|
||||
value in memory.
|
||||
-}
|
||||
force : Lazy a -> a
|
||||
force (Lazy thunk) =
|
||||
thunk ()
|
||||
|
||||
|
||||
|
||||
-- COMPOSING LAZINESS
|
||||
|
||||
|
||||
{-| Lazily apply a function to a lazy value.
|
||||
|
||||
lazySum : Lazy Int
|
||||
lazySum =
|
||||
map List.sum (lazy (\() -> [1..1000000]))
|
||||
|
||||
The resulting lazy value will create a big list and sum it up when it is
|
||||
finally forced.
|
||||
-}
|
||||
map : (a -> b) -> Lazy a -> Lazy b
|
||||
map f a =
|
||||
lazy (\() -> f (force a))
|
||||
|
||||
|
||||
{-| Lazily apply a function to two lazy values.
|
||||
|
||||
lazySum : Lazy Int
|
||||
lazySum =
|
||||
lazy (\() -> List.sum [1..1000000])
|
||||
|
||||
lazySumPair : Lazy (Int, Int)
|
||||
lazySumPair =
|
||||
map2 (,) lazySum lazySum
|
||||
|
||||
-}
|
||||
map2 : (a -> b -> result) -> Lazy a -> Lazy b -> Lazy result
|
||||
map2 f a b =
|
||||
lazy (\() -> f (force a) (force b))
|
||||
|
||||
|
||||
{-| -}
|
||||
map3 : (a -> b -> c -> result) -> Lazy a -> Lazy b -> Lazy c -> Lazy result
|
||||
map3 f a b c =
|
||||
lazy (\() -> f (force a) (force b) (force c))
|
||||
|
||||
|
||||
{-| -}
|
||||
map4 : (a -> b -> c -> d -> result) -> Lazy a -> Lazy b -> Lazy c -> Lazy d -> Lazy result
|
||||
map4 f a b c d =
|
||||
lazy (\() -> f (force a) (force b) (force c) (force d))
|
||||
|
||||
|
||||
{-| -}
|
||||
map5 : (a -> b -> c -> d -> e -> result) -> Lazy a -> Lazy b -> Lazy c -> Lazy d -> Lazy e -> Lazy result
|
||||
map5 f a b c d e =
|
||||
lazy (\() -> f (force a) (force b) (force c) (force d) (force e))
|
||||
|
||||
|
||||
{-| Lazily apply a lazy function to a lazy value. This is pretty rare on its
|
||||
own, but it lets you map as high as you want.
|
||||
|
||||
map3 f a b == f `map` a `apply` b `apply` c
|
||||
|
||||
It is not the most beautiful, but it is equivalent and will let you create
|
||||
`map9` quite easily if you really need it.
|
||||
-}
|
||||
apply : Lazy (a -> b) -> Lazy a -> Lazy b
|
||||
apply f x =
|
||||
lazy (\() -> (force f) (force x))
|
||||
|
||||
|
||||
{-| Lazily chain together lazy computations, for when you have a series of
|
||||
steps that all need to be performed lazily. This can be nice when you need to
|
||||
pattern match on a value, for example, when appending lazy lists:
|
||||
|
||||
type List a = Empty | Node a (Lazy (List a))
|
||||
|
||||
cons : a -> Lazy (List a) -> Lazy (List a)
|
||||
cons first rest =
|
||||
Lazy.map (Node first) rest
|
||||
|
||||
append : Lazy (List a) -> Lazy (List a) -> Lazy (List a)
|
||||
append lazyList1 lazyList2 =
|
||||
let
|
||||
appendHelp list1 =
|
||||
case list1 of
|
||||
Empty ->
|
||||
lazyList2
|
||||
|
||||
Node first rest ->
|
||||
cons first (append rest list2))
|
||||
in
|
||||
lazyList1
|
||||
|> Lazy.andThen appendHelp
|
||||
|
||||
|
||||
By using `andThen` we ensure that neither `lazyList1` or `lazyList2` are forced
|
||||
before they are needed. So as written, the `append` function delays the pattern
|
||||
matching until later.
|
||||
-}
|
||||
andThen : (a -> Lazy b) -> Lazy a -> Lazy b
|
||||
andThen callback a =
|
||||
lazy (\() -> force (callback (force a)))
|
||||
108
part9/tests/elm-stuff/packages/eeue56/elm-lazy/1.0.0/benchmarks/Main.elm
vendored
Normal file
108
part9/tests/elm-stuff/packages/eeue56/elm-lazy/1.0.0/benchmarks/Main.elm
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
module Main exposing (..)
|
||||
|
||||
import Benchmark exposing (..)
|
||||
import Benchmark.Runner exposing (BenchmarkProgram, program)
|
||||
import CoreLazy
|
||||
import Lazy
|
||||
|
||||
|
||||
basicInt : Lazy.Lazy Int
|
||||
basicInt =
|
||||
Lazy.lazy (\() -> 1)
|
||||
|
||||
|
||||
basicCoreInt : CoreLazy.Lazy Int
|
||||
basicCoreInt =
|
||||
CoreLazy.lazy (\() -> 1)
|
||||
|
||||
|
||||
bigThunk : () -> List Int
|
||||
bigThunk _ =
|
||||
List.range 0 10000
|
||||
|
||||
|
||||
complexThing : () -> Lazy.Lazy (List Int)
|
||||
complexThing _ =
|
||||
Lazy.lazy (\() -> List.range 0 10000)
|
||||
|
||||
|
||||
complexCoreThing : () -> CoreLazy.Lazy (List Int)
|
||||
complexCoreThing _ =
|
||||
CoreLazy.lazy (\() -> List.range 0 10000)
|
||||
|
||||
|
||||
suite : Benchmark
|
||||
suite =
|
||||
describe "Lazy"
|
||||
[ describe "force"
|
||||
[ benchmark1 "force" Lazy.force basicInt
|
||||
, Benchmark.compare "forcing a small int"
|
||||
(benchmark1 "eeue56" Lazy.force basicInt)
|
||||
(benchmark1 "core" CoreLazy.force basicCoreInt)
|
||||
, Benchmark.compare "forcing a large list"
|
||||
(benchmark "eeue56" (complexThing >> Lazy.force))
|
||||
(benchmark "core" (complexCoreThing >> CoreLazy.force))
|
||||
, Benchmark.compare "memoization"
|
||||
(benchmark1 "eeue56"
|
||||
(\thing ->
|
||||
let
|
||||
xs =
|
||||
Lazy.lazy thing
|
||||
|
||||
firstPass =
|
||||
Lazy.evaluate xs
|
||||
|
||||
secondPass =
|
||||
Lazy.evaluate firstPass
|
||||
in
|
||||
secondPass |> Lazy.force
|
||||
)
|
||||
bigThunk
|
||||
)
|
||||
(benchmark1 "core"
|
||||
(\thing ->
|
||||
let
|
||||
xs =
|
||||
CoreLazy.lazy thing
|
||||
|
||||
firstPass =
|
||||
CoreLazy.force xs
|
||||
|
||||
secondPass =
|
||||
CoreLazy.force xs
|
||||
in
|
||||
xs |> CoreLazy.force
|
||||
)
|
||||
bigThunk
|
||||
)
|
||||
, Benchmark.compare "memoization foldl"
|
||||
(benchmark1 "eeue56"
|
||||
(\thing ->
|
||||
List.foldl (\_ lazyThing -> Lazy.evaluate lazyThing) (Lazy.lazy thing) (List.range 0 5)
|
||||
|> Lazy.force
|
||||
)
|
||||
bigThunk
|
||||
)
|
||||
(benchmark1 "core"
|
||||
(\thing ->
|
||||
List.foldl
|
||||
(\_ lazyThing ->
|
||||
let
|
||||
_ =
|
||||
CoreLazy.force lazyThing
|
||||
in
|
||||
lazyThing
|
||||
)
|
||||
(CoreLazy.lazy thing)
|
||||
(List.range 0 5)
|
||||
|> CoreLazy.force
|
||||
)
|
||||
bigThunk
|
||||
)
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
main : BenchmarkProgram
|
||||
main =
|
||||
program suite
|
||||
20
part9/tests/elm-stuff/packages/eeue56/elm-lazy/1.0.0/benchmarks/Native/Lazy.js
vendored
Normal file
20
part9/tests/elm-stuff/packages/eeue56/elm-lazy/1.0.0/benchmarks/Native/Lazy.js
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
var _user$project$Native_Lazy = function() {
|
||||
|
||||
function memoize(thunk)
|
||||
{
|
||||
var value;
|
||||
var isForced = false;
|
||||
return function(tuple0) {
|
||||
if (!isForced) {
|
||||
value = thunk(tuple0);
|
||||
isForced = true;
|
||||
}
|
||||
return value;
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
memoize: memoize
|
||||
};
|
||||
|
||||
}();
|
||||
18
part9/tests/elm-stuff/packages/eeue56/elm-lazy/1.0.0/benchmarks/elm-package.json
vendored
Normal file
18
part9/tests/elm-stuff/packages/eeue56/elm-lazy/1.0.0/benchmarks/elm-package.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"summary": "helpful summary of your project, less than 80 characters",
|
||||
"repository": "https://github.com/user/project.git",
|
||||
"license": "BSD3",
|
||||
"source-directories": [
|
||||
".",
|
||||
"../src"
|
||||
],
|
||||
"exposed-modules": [],
|
||||
"native-modules": true,
|
||||
"dependencies": {
|
||||
"BrianHicks/elm-benchmark": "1.0.2 <= v < 2.0.0",
|
||||
"elm-lang/core": "5.1.1 <= v < 6.0.0",
|
||||
"elm-lang/html": "2.0.0 <= v < 3.0.0"
|
||||
},
|
||||
"elm-version": "0.18.0 <= v < 0.19.0"
|
||||
}
|
||||
15
part9/tests/elm-stuff/packages/eeue56/elm-lazy/1.0.0/elm-package.json
vendored
Normal file
15
part9/tests/elm-stuff/packages/eeue56/elm-lazy/1.0.0/elm-package.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"summary": "Laziness and optional memoization in pure Elm",
|
||||
"repository": "https://github.com/eeue56/elm-lazy.git",
|
||||
"license": "BSD3",
|
||||
"source-directories": [
|
||||
"src"
|
||||
],
|
||||
"exposed-modules": ["Lazy"],
|
||||
"dependencies": {
|
||||
"elm-lang/core": "5.1.1 <= v < 6.0.0",
|
||||
"elm-lang/html": "2.0.0 <= v < 3.0.0"
|
||||
},
|
||||
"elm-version": "0.18.0 <= v < 0.19.0"
|
||||
}
|
||||
201
part9/tests/elm-stuff/packages/eeue56/elm-lazy/1.0.0/src/Lazy.elm
vendored
Normal file
201
part9/tests/elm-stuff/packages/eeue56/elm-lazy/1.0.0/src/Lazy.elm
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
module Lazy
|
||||
exposing
|
||||
( Lazy
|
||||
, force
|
||||
, lazy
|
||||
, evaluate
|
||||
, map
|
||||
, map2
|
||||
, map3
|
||||
, map4
|
||||
, map5
|
||||
, apply
|
||||
, andThen
|
||||
)
|
||||
|
||||
{-| This library lets you delay a computation until later.
|
||||
|
||||
# Basics
|
||||
@docs Lazy, lazy, force, evaluate
|
||||
|
||||
# Mapping
|
||||
@docs map, map2, map3, map4, map5
|
||||
|
||||
# Chaining
|
||||
@docs apply, andThen
|
||||
-}
|
||||
|
||||
-- PRIMITIVES
|
||||
|
||||
|
||||
{-| A wrapper around a value that will be lazily evaluated.
|
||||
-}
|
||||
type Lazy a
|
||||
= Lazy (() -> a)
|
||||
| Evaluated a
|
||||
|
||||
|
||||
{-| Delay the evaluation of a value until later. For example, maybe we will
|
||||
need to generate a very long list and find its sum, but we do not want to do
|
||||
it unless it is absolutely necessary.
|
||||
|
||||
lazySum : Lazy Int
|
||||
lazySum =
|
||||
lazy (\() -> sum <| List.range 1 1000000 )
|
||||
|
||||
Now we only pay for `lazySum` if we actually need it.
|
||||
-}
|
||||
lazy : (() -> a) -> Lazy a
|
||||
lazy thunk =
|
||||
Lazy thunk
|
||||
|
||||
|
||||
{-| Force the evaluation of a lazy value. This means we only pay for the
|
||||
computation when we need it. Here is a rather contrived example.
|
||||
|
||||
lazySum : Lazy Int
|
||||
lazySum =
|
||||
lazy (\() -> List.sum <| List.range 1 1000000)
|
||||
|
||||
sums : (Int, Int, Int)
|
||||
sums =
|
||||
(force lazySum, force lazySum, force lazySum)
|
||||
-}
|
||||
force : Lazy a -> a
|
||||
force piece =
|
||||
case piece of
|
||||
Evaluated a ->
|
||||
a
|
||||
|
||||
Lazy thunk ->
|
||||
thunk ()
|
||||
|
||||
|
||||
{-| Evaluate the lazy value if it has not already been evaluated. If it has,
|
||||
do nothing.
|
||||
|
||||
lazySum : Lazy Int
|
||||
lazySum =
|
||||
lazy (\() -> List.sum <| List.range 1 1000000)
|
||||
|
||||
sums : (Int, Int, Int)
|
||||
sums =
|
||||
let
|
||||
evaledSum =
|
||||
evaluate lazySum
|
||||
in
|
||||
(force evaledSum, force evaledSum, force evaledSum)
|
||||
|
||||
This is mainly useful for cases where you may want to store a lazy value as a
|
||||
lazy value and pass it around. For example, in a list. Where possible, it is better to use
|
||||
`force` and simply store the computed value seperately.
|
||||
|
||||
-}
|
||||
evaluate : Lazy a -> Lazy a
|
||||
evaluate piece =
|
||||
case piece of
|
||||
Evaluated a ->
|
||||
Evaluated a
|
||||
|
||||
Lazy thunk ->
|
||||
thunk ()
|
||||
|> Evaluated
|
||||
|
||||
|
||||
|
||||
-- COMPOSING LAZINESS
|
||||
|
||||
|
||||
{-| Lazily apply a function to a lazy value.
|
||||
|
||||
lazySum : Lazy Int
|
||||
lazySum =
|
||||
map List.sum (lazy (\() -> <| List.range 1 1000000)
|
||||
|
||||
The resulting lazy value will create a big list and sum it up when it is
|
||||
finally forced.
|
||||
-}
|
||||
map : (a -> b) -> Lazy a -> Lazy b
|
||||
map f a =
|
||||
lazy (\() -> f (force a))
|
||||
|
||||
|
||||
{-| Lazily apply a function to two lazy values.
|
||||
|
||||
lazySum : Lazy Int
|
||||
lazySum =
|
||||
lazy (\() -> List.sum <| List.range 1 1000000)
|
||||
|
||||
lazySumPair : Lazy (Int, Int)
|
||||
lazySumPair =
|
||||
map2 (,) lazySum lazySum
|
||||
|
||||
-}
|
||||
map2 : (a -> b -> result) -> Lazy a -> Lazy b -> Lazy result
|
||||
map2 f a b =
|
||||
lazy (\() -> f (force a) (force b))
|
||||
|
||||
|
||||
{-| -}
|
||||
map3 : (a -> b -> c -> result) -> Lazy a -> Lazy b -> Lazy c -> Lazy result
|
||||
map3 f a b c =
|
||||
lazy (\() -> f (force a) (force b) (force c))
|
||||
|
||||
|
||||
{-| -}
|
||||
map4 : (a -> b -> c -> d -> result) -> Lazy a -> Lazy b -> Lazy c -> Lazy d -> Lazy result
|
||||
map4 f a b c d =
|
||||
lazy (\() -> f (force a) (force b) (force c) (force d))
|
||||
|
||||
|
||||
{-| -}
|
||||
map5 : (a -> b -> c -> d -> e -> result) -> Lazy a -> Lazy b -> Lazy c -> Lazy d -> Lazy e -> Lazy result
|
||||
map5 f a b c d e =
|
||||
lazy (\() -> f (force a) (force b) (force c) (force d) (force e))
|
||||
|
||||
|
||||
{-| Lazily apply a lazy function to a lazy value. This is pretty rare on its
|
||||
own, but it lets you map as high as you want.
|
||||
|
||||
map3 f a b == f `map` a `apply` b `apply` c
|
||||
|
||||
It is not the most beautiful, but it is equivalent and will let you create
|
||||
`map9` quite easily if you really need it.
|
||||
-}
|
||||
apply : Lazy (a -> b) -> Lazy a -> Lazy b
|
||||
apply f x =
|
||||
lazy (\() -> (force f) (force x))
|
||||
|
||||
|
||||
{-| Lazily chain together lazy computations, for when you have a series of
|
||||
steps that all need to be performed lazily. This can be nice when you need to
|
||||
pattern match on a value, for example, when appending lazy lists:
|
||||
|
||||
type List a = Empty | Node a (Lazy (List a))
|
||||
|
||||
cons : a -> Lazy (List a) -> Lazy (List a)
|
||||
cons first rest =
|
||||
Lazy.map (Node first) rest
|
||||
|
||||
append : Lazy (List a) -> Lazy (List a) -> Lazy (List a)
|
||||
append lazyList1 lazyList2 =
|
||||
let
|
||||
appendHelp list1 =
|
||||
case list1 of
|
||||
Empty ->
|
||||
lazyList2
|
||||
|
||||
Node first rest ->
|
||||
cons first (append rest list2))
|
||||
in
|
||||
lazyList1
|
||||
|> Lazy.andThen appendHelp
|
||||
|
||||
|
||||
By using `andThen` we ensure that neither `lazyList1` or `lazyList2` are forced
|
||||
before they are needed. So as written, the `append` function delays the pattern
|
||||
matching until later.
|
||||
-}
|
||||
andThen : (a -> Lazy b) -> Lazy a -> Lazy b
|
||||
andThen callback a =
|
||||
lazy (\() -> force (callback (force a)))
|
||||
43
part9/tests/elm-stuff/packages/eeue56/elm-lazy/1.0.0/tests/Example.elm
vendored
Normal file
43
part9/tests/elm-stuff/packages/eeue56/elm-lazy/1.0.0/tests/Example.elm
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
module Example exposing (..)
|
||||
|
||||
import Lazy
|
||||
import Expect exposing (Expectation)
|
||||
import Fuzz exposing (Fuzzer, list, int, string)
|
||||
import Test exposing (..)
|
||||
|
||||
|
||||
suite : Test
|
||||
suite =
|
||||
describe "Laziness"
|
||||
[ fuzz int
|
||||
"lazy and force"
|
||||
(\x ->
|
||||
Lazy.lazy (\() -> x)
|
||||
|> Lazy.force
|
||||
|> Expect.equal x
|
||||
)
|
||||
, fuzz int
|
||||
"evaluate"
|
||||
(\x ->
|
||||
Lazy.lazy (\() -> x)
|
||||
|> Lazy.evaluate
|
||||
|> Lazy.force
|
||||
|> Expect.equal x
|
||||
)
|
||||
, fuzz int
|
||||
"map"
|
||||
(\x ->
|
||||
Lazy.lazy (\() -> x)
|
||||
|> Lazy.map (\x -> x + 1)
|
||||
|> Lazy.force
|
||||
|> Expect.equal (x + 1)
|
||||
)
|
||||
, fuzz2 int
|
||||
int
|
||||
"map2"
|
||||
(\x y ->
|
||||
Lazy.map2 (\x y -> x + y) (Lazy.lazy (\() -> x)) (Lazy.lazy (\() -> y))
|
||||
|> Lazy.force
|
||||
|> Expect.equal (x + y)
|
||||
)
|
||||
]
|
||||
18
part9/tests/elm-stuff/packages/eeue56/elm-lazy/1.0.0/tests/elm-package.json
vendored
Normal file
18
part9/tests/elm-stuff/packages/eeue56/elm-lazy/1.0.0/tests/elm-package.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"summary": "Test Suites",
|
||||
"repository": "https://github.com/user/project.git",
|
||||
"license": "BSD3",
|
||||
"source-directories": [
|
||||
"../src",
|
||||
"."
|
||||
],
|
||||
"exposed-modules": [],
|
||||
"dependencies": {
|
||||
"eeue56/elm-html-test": "4.1.0 <= v < 5.0.0",
|
||||
"elm-community/elm-test": "4.0.0 <= v < 5.0.0",
|
||||
"elm-lang/core": "5.1.1 <= v < 6.0.0",
|
||||
"elm-lang/html": "2.0.0 <= v < 3.0.0"
|
||||
},
|
||||
"elm-version": "0.18.0 <= v < 0.19.0"
|
||||
}
|
||||
4
part9/tests/elm-stuff/packages/eeue56/elm-shrink/1.0.0/.gitignore
vendored
Normal file
4
part9/tests/elm-stuff/packages/eeue56/elm-shrink/1.0.0/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# elm-package generated files
|
||||
elm-stuff
|
||||
# elm-repl generated files
|
||||
repl-temp-*
|
||||
29
part9/tests/elm-stuff/packages/eeue56/elm-shrink/1.0.0/LICENSE
vendored
Normal file
29
part9/tests/elm-stuff/packages/eeue56/elm-shrink/1.0.0/LICENSE
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
BSD 3-Clause License
|
||||
|
||||
Copyright (c) 2017, Noah
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* Neither the name of the copyright holder nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
1
part9/tests/elm-stuff/packages/eeue56/elm-shrink/1.0.0/README.md
vendored
Normal file
1
part9/tests/elm-stuff/packages/eeue56/elm-shrink/1.0.0/README.md
vendored
Normal file
@@ -0,0 +1 @@
|
||||
# elm-shrink
|
||||
18
part9/tests/elm-stuff/packages/eeue56/elm-shrink/1.0.0/elm-package.json
vendored
Normal file
18
part9/tests/elm-stuff/packages/eeue56/elm-shrink/1.0.0/elm-package.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"summary": "A shrinker for use with tests, written in pure Elm",
|
||||
"repository": "https://github.com/eeue56/elm-shrink.git",
|
||||
"license": "BSD3",
|
||||
"source-directories": [
|
||||
"src"
|
||||
],
|
||||
"exposed-modules": ["Shrink"],
|
||||
"dependencies": {
|
||||
|
||||
"eeue56/elm-lazy": "1.0.0 <= v < 2.0.0",
|
||||
"eeue56/elm-lazy-list": "1.0.0 <= v < 2.0.0",
|
||||
"elm-lang/core": "5.1.1 <= v < 6.0.0",
|
||||
"elm-lang/html": "2.0.0 <= v < 3.0.0"
|
||||
},
|
||||
"elm-version": "0.18.0 <= v < 0.19.0"
|
||||
}
|
||||
467
part9/tests/elm-stuff/packages/eeue56/elm-shrink/1.0.0/src/Shrink.elm
vendored
Normal file
467
part9/tests/elm-stuff/packages/eeue56/elm-shrink/1.0.0/src/Shrink.elm
vendored
Normal file
@@ -0,0 +1,467 @@
|
||||
module Shrink exposing (Shrinker, shrink, noShrink, unit, bool, order, int, atLeastInt, float, atLeastFloat, char, atLeastChar, character, string, maybe, result, list, lazylist, array, tuple, tuple3, tuple4, tuple5, convert, keepIf, dropIf, merge, map, andMap)
|
||||
|
||||
{-| Library containing a collection of basic shrinking strategies and
|
||||
helper functions to help you construct shrinking strategies.
|
||||
|
||||
# Shrinking Basics
|
||||
@docs Shrinker, shrink
|
||||
|
||||
# Shrinkers
|
||||
@docs noShrink, unit, bool, order, int, atLeastInt, float, atLeastFloat, char, atLeastChar, character, string, maybe, result, lazylist, list, array, tuple, tuple3, tuple4, tuple5
|
||||
|
||||
# Functions on Shrinkers
|
||||
@docs convert, keepIf, dropIf, merge, map, andMap
|
||||
|
||||
-}
|
||||
|
||||
import Lazy.List exposing (LazyList, (:::), (+++), empty)
|
||||
import Lazy exposing (Lazy, force, lazy)
|
||||
import List
|
||||
import Array exposing (Array)
|
||||
import Char
|
||||
import String
|
||||
|
||||
|
||||
{-| The shrinker type.
|
||||
A shrinker is a function that takes a value and returns a list of values that
|
||||
are in some sense "smaller" than the given value. If there are no such values
|
||||
conceptually, then the shrinker should just return the empty list.
|
||||
-}
|
||||
type alias Shrinker a =
|
||||
a -> LazyList a
|
||||
|
||||
|
||||
{-| Perform shrinking. Takes a predicate that returns `True` if you want
|
||||
shrinking to continue (e.g. the test failed). Also takes a shrinker and a value
|
||||
to shrink. It returns the shrunken value, or the input value if no shrunken
|
||||
values that satisfy the predicate are found.
|
||||
-}
|
||||
shrink : (a -> Bool) -> Shrinker a -> a -> a
|
||||
shrink keepShrinking shrinker originalVal =
|
||||
let
|
||||
helper lazyList val =
|
||||
case force lazyList of
|
||||
Lazy.List.Nil ->
|
||||
val
|
||||
|
||||
Lazy.List.Cons head tail ->
|
||||
if keepShrinking head then
|
||||
helper (shrinker head) head
|
||||
else
|
||||
helper tail val
|
||||
in
|
||||
helper (shrinker originalVal) originalVal
|
||||
|
||||
|
||||
{-| Perform no shrinking. Equivalent to the empty lazy list.
|
||||
-}
|
||||
noShrink : Shrinker a
|
||||
noShrink _ =
|
||||
empty
|
||||
|
||||
|
||||
{-| Shrink the empty tuple. Equivalent to `noShrink`.
|
||||
-}
|
||||
unit : Shrinker ()
|
||||
unit =
|
||||
noShrink
|
||||
|
||||
|
||||
{-| Shrinker of bools.
|
||||
-}
|
||||
bool : Shrinker Bool
|
||||
bool b =
|
||||
case b of
|
||||
True ->
|
||||
False ::: empty
|
||||
|
||||
False ->
|
||||
empty
|
||||
|
||||
|
||||
{-| Shrinker of `Order` values.
|
||||
-}
|
||||
order : Shrinker Order
|
||||
order o =
|
||||
case o of
|
||||
GT ->
|
||||
EQ ::: LT ::: empty
|
||||
|
||||
LT ->
|
||||
EQ ::: empty
|
||||
|
||||
EQ ->
|
||||
empty
|
||||
|
||||
|
||||
{-| Shrinker of integers.
|
||||
-}
|
||||
int : Shrinker Int
|
||||
int n =
|
||||
if n < 0 then
|
||||
-n ::: Lazy.List.map ((*) -1) (seriesInt 0 -n)
|
||||
else
|
||||
seriesInt 0 n
|
||||
|
||||
|
||||
{-| Construct a shrinker of ints which considers the given int to
|
||||
be most minimal.
|
||||
-}
|
||||
atLeastInt : Int -> Shrinker Int
|
||||
atLeastInt min n =
|
||||
if n < 0 && n >= min then
|
||||
-n ::: Lazy.List.map ((*) -1) (seriesInt 0 -n)
|
||||
else
|
||||
seriesInt (max 0 min) n
|
||||
|
||||
|
||||
{-| Shrinker of floats.
|
||||
-}
|
||||
float : Shrinker Float
|
||||
float n =
|
||||
if n < 0 then
|
||||
-n ::: Lazy.List.map ((*) -1) (seriesFloat 0 -n)
|
||||
else
|
||||
seriesFloat 0 n
|
||||
|
||||
|
||||
{-| Construct a shrinker of floats which considers the given float to
|
||||
be most minimal.
|
||||
-}
|
||||
atLeastFloat : Float -> Shrinker Float
|
||||
atLeastFloat min n =
|
||||
if n < 0 && n >= min then
|
||||
-n ::: Lazy.List.map ((*) -1) (seriesFloat 0 -n)
|
||||
else
|
||||
seriesFloat (max 0 min) n
|
||||
|
||||
|
||||
{-| Shrinker of chars.
|
||||
-}
|
||||
char : Shrinker Char
|
||||
char =
|
||||
convert Char.fromCode Char.toCode int
|
||||
|
||||
|
||||
{-| Construct a shrinker of chars which considers the given char to
|
||||
be most minimal.
|
||||
-}
|
||||
atLeastChar : Char -> Shrinker Char
|
||||
atLeastChar char =
|
||||
convert Char.fromCode Char.toCode (atLeastInt (Char.toCode char))
|
||||
|
||||
|
||||
{-| Shrinker of chars which considers the empty space as the most
|
||||
minimal char and omits the control key codes.
|
||||
|
||||
Equivalent to:
|
||||
|
||||
atLeastChar (Char.fromCode 32)
|
||||
-}
|
||||
character : Shrinker Char
|
||||
character =
|
||||
atLeastChar (Char.fromCode 32)
|
||||
|
||||
|
||||
{-| Shrinker of strings. Considers the empty string to be the most
|
||||
minimal string and the space to be the most minimal char.
|
||||
|
||||
Equivalent to:
|
||||
|
||||
convert String.fromList String.toList (list character)
|
||||
-}
|
||||
string : Shrinker String
|
||||
string =
|
||||
convert String.fromList String.toList (list character)
|
||||
|
||||
|
||||
{-| Maybe shrinker constructor.
|
||||
Takes a shrinker of values and returns a shrinker of Maybes.
|
||||
-}
|
||||
maybe : Shrinker a -> Shrinker (Maybe a)
|
||||
maybe shrink m =
|
||||
case m of
|
||||
Just a ->
|
||||
Nothing ::: Lazy.List.map Just (shrink a)
|
||||
|
||||
Nothing ->
|
||||
empty
|
||||
|
||||
|
||||
{-| Result shrinker constructor. Takes a shrinker of errors and a shrinker of
|
||||
values and returns a shrinker of Results.
|
||||
-}
|
||||
result : Shrinker error -> Shrinker value -> Shrinker (Result error value)
|
||||
result shrinkError shrinkValue r =
|
||||
case r of
|
||||
Ok value ->
|
||||
Lazy.List.map Ok (shrinkValue value)
|
||||
|
||||
Err error ->
|
||||
Lazy.List.map Err (shrinkError error)
|
||||
|
||||
|
||||
{-| Lazy List shrinker constructor. Takes a shrinker of values and returns a
|
||||
shrinker of Lazy Lists. The lazy list being shrunk must be finite. (I mean
|
||||
really, how do you shrink infinity?)
|
||||
-}
|
||||
lazylist : Shrinker a -> Shrinker (LazyList a)
|
||||
lazylist shrink l =
|
||||
lazy <|
|
||||
\() ->
|
||||
let
|
||||
n : Int
|
||||
n =
|
||||
Lazy.List.length l
|
||||
|
||||
shrinkOne : LazyList a -> LazyList (LazyList a)
|
||||
shrinkOne l =
|
||||
lazy <|
|
||||
\() ->
|
||||
case force l of
|
||||
Lazy.List.Nil ->
|
||||
force empty
|
||||
|
||||
Lazy.List.Cons x xs ->
|
||||
force
|
||||
(Lazy.List.map (flip (:::) xs) (shrink x)
|
||||
+++ Lazy.List.map ((:::) x) (shrinkOne xs)
|
||||
)
|
||||
|
||||
removes : Int -> Int -> Shrinker (LazyList a)
|
||||
removes k n l =
|
||||
lazy <|
|
||||
\() ->
|
||||
if k > n then
|
||||
force empty
|
||||
else if Lazy.List.isEmpty l then
|
||||
force (empty ::: empty)
|
||||
else
|
||||
let
|
||||
first =
|
||||
Lazy.List.take k l
|
||||
|
||||
rest =
|
||||
Lazy.List.drop k l
|
||||
in
|
||||
force <|
|
||||
rest
|
||||
::: Lazy.List.map ((+++) first) (removes k (n - k) rest)
|
||||
in
|
||||
force <|
|
||||
Lazy.List.andThen (\k -> removes k n l)
|
||||
(Lazy.List.takeWhile (\x -> x > 0) (Lazy.List.iterate (\n -> n // 2) n))
|
||||
+++ shrinkOne l
|
||||
|
||||
|
||||
{-| List shrinker constructor.
|
||||
Takes a shrinker of values and returns a shrinker of Lists.
|
||||
-}
|
||||
list : Shrinker a -> Shrinker (List a)
|
||||
list shrink =
|
||||
convert Lazy.List.toList Lazy.List.fromList (lazylist shrink)
|
||||
|
||||
|
||||
{-| Array shrinker constructor.
|
||||
Takes a shrinker of values and returns a shrinker of Arrays.
|
||||
-}
|
||||
array : Shrinker a -> Shrinker (Array a)
|
||||
array shrink =
|
||||
convert Lazy.List.toArray Lazy.List.fromArray (lazylist shrink)
|
||||
|
||||
|
||||
{-| 2-Tuple shrinker constructor.
|
||||
Takes a tuple of shrinkers and returns a shrinker of tuples.
|
||||
-}
|
||||
tuple : ( Shrinker a, Shrinker b ) -> Shrinker ( a, b )
|
||||
tuple ( shrinkA, shrinkB ) ( a, b ) =
|
||||
Lazy.List.map ((,) a) (shrinkB b)
|
||||
+++ Lazy.List.map (flip (,) b) (shrinkA a)
|
||||
+++ Lazy.List.map2 (,) (shrinkA a) (shrinkB b)
|
||||
|
||||
|
||||
{-| 3-Tuple shrinker constructor.
|
||||
Takes a tuple of shrinkers and returns a shrinker of tuples.
|
||||
-}
|
||||
tuple3 : ( Shrinker a, Shrinker b, Shrinker c ) -> Shrinker ( a, b, c )
|
||||
tuple3 ( shrinkA, shrinkB, shrinkC ) ( a, b, c ) =
|
||||
Lazy.List.map (\c -> ( a, b, c )) (shrinkC c)
|
||||
+++ Lazy.List.map (\b -> ( a, b, c )) (shrinkB b)
|
||||
+++ Lazy.List.map (\a -> ( a, b, c )) (shrinkA a)
|
||||
+++ Lazy.List.map2 (\b c -> ( a, b, c )) (shrinkB b) (shrinkC c)
|
||||
+++ Lazy.List.map2 (\a c -> ( a, b, c )) (shrinkA a) (shrinkC c)
|
||||
+++ Lazy.List.map2 (\a b -> ( a, b, c )) (shrinkA a) (shrinkB b)
|
||||
+++ Lazy.List.map3 (,,) (shrinkA a) (shrinkB b) (shrinkC c)
|
||||
|
||||
|
||||
{-| 4-Tuple shrinker constructor.
|
||||
Takes a tuple of shrinkers and returns a shrinker of tuples.
|
||||
-}
|
||||
tuple4 : ( Shrinker a, Shrinker b, Shrinker c, Shrinker d ) -> Shrinker ( a, b, c, d )
|
||||
tuple4 ( shrinkA, shrinkB, shrinkC, shrinkD ) ( a, b, c, d ) =
|
||||
Lazy.List.map (\d -> ( a, b, c, d )) (shrinkD d)
|
||||
+++ Lazy.List.map (\c -> ( a, b, c, d )) (shrinkC c)
|
||||
+++ Lazy.List.map (\b -> ( a, b, c, d )) (shrinkB b)
|
||||
+++ Lazy.List.map (\a -> ( a, b, c, d )) (shrinkA a)
|
||||
+++ Lazy.List.map2 (\c d -> ( a, b, c, d )) (shrinkC c) (shrinkD d)
|
||||
+++ Lazy.List.map2 (\b d -> ( a, b, c, d )) (shrinkB b) (shrinkD d)
|
||||
+++ Lazy.List.map2 (\a d -> ( a, b, c, d )) (shrinkA a) (shrinkD d)
|
||||
+++ Lazy.List.map2 (\b c -> ( a, b, c, d )) (shrinkB b) (shrinkC c)
|
||||
+++ Lazy.List.map2 (\a c -> ( a, b, c, d )) (shrinkA a) (shrinkC c)
|
||||
+++ Lazy.List.map2 (\a b -> ( a, b, c, d )) (shrinkA a) (shrinkB b)
|
||||
+++ Lazy.List.map3 (\b c d -> ( a, b, c, d )) (shrinkB b) (shrinkC c) (shrinkD d)
|
||||
+++ Lazy.List.map3 (\a c d -> ( a, b, c, d )) (shrinkA a) (shrinkC c) (shrinkD d)
|
||||
+++ Lazy.List.map3 (\a b d -> ( a, b, c, d )) (shrinkA a) (shrinkB b) (shrinkD d)
|
||||
+++ Lazy.List.map3 (\a b c -> ( a, b, c, d )) (shrinkA a) (shrinkB b) (shrinkC c)
|
||||
+++ Lazy.List.map4 (,,,) (shrinkA a) (shrinkB b) (shrinkC c) (shrinkD d)
|
||||
|
||||
|
||||
{-| 5-Tuple shrinker constructor.
|
||||
Takes a tuple of shrinkers and returns a shrinker of tuples.
|
||||
-}
|
||||
tuple5 : ( Shrinker a, Shrinker b, Shrinker c, Shrinker d, Shrinker e ) -> Shrinker ( a, b, c, d, e )
|
||||
tuple5 ( shrinkA, shrinkB, shrinkC, shrinkD, shrinkE ) ( a, b, c, d, e ) =
|
||||
Lazy.List.map (\e -> ( a, b, c, d, e )) (shrinkE e)
|
||||
+++ Lazy.List.map (\d -> ( a, b, c, d, e )) (shrinkD d)
|
||||
+++ Lazy.List.map (\c -> ( a, b, c, d, e )) (shrinkC c)
|
||||
+++ Lazy.List.map (\b -> ( a, b, c, d, e )) (shrinkB b)
|
||||
+++ Lazy.List.map (\a -> ( a, b, c, d, e )) (shrinkA a)
|
||||
+++ Lazy.List.map2 (\d e -> ( a, b, c, d, e )) (shrinkD d) (shrinkE e)
|
||||
+++ Lazy.List.map2 (\c e -> ( a, b, c, d, e )) (shrinkC c) (shrinkE e)
|
||||
+++ Lazy.List.map2 (\b e -> ( a, b, c, d, e )) (shrinkB b) (shrinkE e)
|
||||
+++ Lazy.List.map2 (\a e -> ( a, b, c, d, e )) (shrinkA a) (shrinkE e)
|
||||
+++ Lazy.List.map2 (\c d -> ( a, b, c, d, e )) (shrinkC c) (shrinkD d)
|
||||
+++ Lazy.List.map2 (\b d -> ( a, b, c, d, e )) (shrinkB b) (shrinkD d)
|
||||
+++ Lazy.List.map2 (\a d -> ( a, b, c, d, e )) (shrinkA a) (shrinkD d)
|
||||
+++ Lazy.List.map2 (\b c -> ( a, b, c, d, e )) (shrinkB b) (shrinkC c)
|
||||
+++ Lazy.List.map2 (\a c -> ( a, b, c, d, e )) (shrinkA a) (shrinkC c)
|
||||
+++ Lazy.List.map2 (\a b -> ( a, b, c, d, e )) (shrinkA a) (shrinkB b)
|
||||
+++ Lazy.List.map3 (\a b c -> ( a, b, c, d, e )) (shrinkA a) (shrinkB b) (shrinkC c)
|
||||
+++ Lazy.List.map3 (\a b d -> ( a, b, c, d, e )) (shrinkA a) (shrinkB b) (shrinkD d)
|
||||
+++ Lazy.List.map3 (\a c d -> ( a, b, c, d, e )) (shrinkA a) (shrinkC c) (shrinkD d)
|
||||
+++ Lazy.List.map3 (\b c d -> ( a, b, c, d, e )) (shrinkB b) (shrinkC c) (shrinkD d)
|
||||
+++ Lazy.List.map3 (\a b e -> ( a, b, c, d, e )) (shrinkA a) (shrinkB b) (shrinkE e)
|
||||
+++ Lazy.List.map3 (\a c e -> ( a, b, c, d, e )) (shrinkA a) (shrinkC c) (shrinkE e)
|
||||
+++ Lazy.List.map3 (\b c e -> ( a, b, c, d, e )) (shrinkB b) (shrinkC c) (shrinkE e)
|
||||
+++ Lazy.List.map3 (\a d e -> ( a, b, c, d, e )) (shrinkA a) (shrinkD d) (shrinkE e)
|
||||
+++ Lazy.List.map3 (\b d e -> ( a, b, c, d, e )) (shrinkB b) (shrinkD d) (shrinkE e)
|
||||
+++ Lazy.List.map3 (\c d e -> ( a, b, c, d, e )) (shrinkC c) (shrinkD d) (shrinkE e)
|
||||
+++ Lazy.List.map4 (\b c d e -> ( a, b, c, d, e )) (shrinkB b) (shrinkC c) (shrinkD d) (shrinkE e)
|
||||
+++ Lazy.List.map4 (\a c d e -> ( a, b, c, d, e )) (shrinkA a) (shrinkC c) (shrinkD d) (shrinkE e)
|
||||
+++ Lazy.List.map4 (\a b d e -> ( a, b, c, d, e )) (shrinkA a) (shrinkB b) (shrinkD d) (shrinkE e)
|
||||
+++ Lazy.List.map4 (\a b c d -> ( a, b, c, d, e )) (shrinkA a) (shrinkB b) (shrinkC c) (shrinkD d)
|
||||
+++ Lazy.List.map5 (,,,,) (shrinkA a) (shrinkB b) (shrinkC c) (shrinkD d) (shrinkE e)
|
||||
|
||||
|
||||
|
||||
----------------------
|
||||
-- HELPER FUNCTIONS --
|
||||
----------------------
|
||||
|
||||
|
||||
{-| Convert a Shrinker of a's into a Shrinker of b's using two inverse functions.
|
||||
|
||||
If you use this function as follows:
|
||||
|
||||
shrinkerB = f g shrinkerA
|
||||
|
||||
Make sure that
|
||||
|
||||
`f(g(x)) == x` for all x
|
||||
|
||||
Or else this process will generate garbage.
|
||||
-}
|
||||
convert : (a -> b) -> (b -> a) -> Shrinker a -> Shrinker b
|
||||
convert f g shrink b =
|
||||
Lazy.List.map f (shrink (g b))
|
||||
|
||||
|
||||
{-| Filter out the results of a shrinker. The resulting shrinker
|
||||
will only produce shrinks which satisfy the given predicate.
|
||||
-}
|
||||
keepIf : (a -> Bool) -> Shrinker a -> Shrinker a
|
||||
keepIf predicate shrink a =
|
||||
Lazy.List.keepIf predicate (shrink a)
|
||||
|
||||
|
||||
{-| Filter out the results of a shrinker. The resulting shrinker
|
||||
will only throw away shrinks which satisfy the given predicate.
|
||||
-}
|
||||
dropIf : (a -> Bool) -> Shrinker a -> Shrinker a
|
||||
dropIf predicate =
|
||||
keepIf (not << predicate)
|
||||
|
||||
|
||||
{-| Merge two shrinkers. Generates all the values in the first
|
||||
shrinker, and then all the non-duplicated values in the second
|
||||
shrinker.
|
||||
-}
|
||||
merge : Shrinker a -> Shrinker a -> Shrinker a
|
||||
merge shrink1 shrink2 a =
|
||||
Lazy.List.unique (shrink1 a +++ shrink2 a)
|
||||
|
||||
|
||||
{-| Re-export of `Lazy.List.map`
|
||||
This is useful in order to compose shrinkers, especially when used in
|
||||
conjunction with `andMap`. For example:
|
||||
|
||||
type alias Vector =
|
||||
{ x : Float
|
||||
, y : Float
|
||||
, z : Float
|
||||
}
|
||||
|
||||
vector : Shrinker Vector
|
||||
vector {x,y,z} =
|
||||
Vector
|
||||
`map` float x
|
||||
`andMap` float y
|
||||
`andMap` float z
|
||||
-}
|
||||
map : (a -> b) -> LazyList a -> LazyList b
|
||||
map =
|
||||
Lazy.List.map
|
||||
|
||||
|
||||
{-| Apply a lazy list of functions on a lazy list of values.
|
||||
|
||||
The argument order is so that it is easy to use in `|>` chains.
|
||||
-}
|
||||
andMap : LazyList a -> LazyList (a -> b) -> LazyList b
|
||||
andMap =
|
||||
Lazy.List.andMap
|
||||
|
||||
|
||||
|
||||
-----------------------
|
||||
-- PRIVATE FUNCTIONS --
|
||||
-----------------------
|
||||
|
||||
|
||||
seriesInt : Int -> Int -> LazyList Int
|
||||
seriesInt low high =
|
||||
if low >= high then
|
||||
empty
|
||||
else if low == high - 1 then
|
||||
low ::: empty
|
||||
else
|
||||
let
|
||||
low_ =
|
||||
low + ((high - low) // 2)
|
||||
in
|
||||
low ::: seriesInt low_ high
|
||||
|
||||
|
||||
seriesFloat : Float -> Float -> LazyList Float
|
||||
seriesFloat low high =
|
||||
if low >= high - 0.0001 then
|
||||
if high /= 0.000001 then
|
||||
Lazy.List.singleton (low + 0.000001)
|
||||
else
|
||||
empty
|
||||
else
|
||||
let
|
||||
low_ =
|
||||
low + ((high - low) / 2)
|
||||
in
|
||||
low ::: seriesFloat low_ high
|
||||
Reference in New Issue
Block a user