1module Testable exposing
9 , LayoutExpectation(..)
15 , compareFormattedColor
19 , formatColorWithAlpha
32import Dict exposing (Dict)
33import Element exposing (Color)
34import Html exposing (Html)
36import Internal.Model as Internal
37import Test exposing (Test)
41 = El (List (Attr msg)) (Element msg)
42 | Row (List (Attr msg)) (List (Element msg))
43 | Column (List (Attr msg)) (List (Element msg))
44 | TextColumn (List (Attr msg)) (List (Element msg))
45 | Paragraph (List (Attr msg)) (List (Element msg))
60elementTypeToString : ElementType -> String
61elementTypeToString elem =
85toElementType : Element msg -> ElementType
110{-| We have an attribute id in order to remove tests when an overriding attribtue is assigned.
112Basically, we want to implictly test for height/width shrink.
114But we want to skip this test if width/height is already set.
116This allows us to do that by comparing identities.
126 = Attr (Element.Attribute msg)
128 { test : Surroundings msg -> List LayoutExpectation
132 | Batch (List (Attr msg))
135 { location : Location
136 , element : Element msg
137 , test : Surroundings msg -> List LayoutExpectation
141 { test : Surroundings msg -> List LayoutExpectation
143 , attr : Element.Attribute msg
164type alias Surroundings msg =
165 { siblings : List Found
167 , children : List Found
169 , selfElement : Element msg
171 -- These values are needed to perform some types of tests.
172 , parentLayout : LayoutContext
173 , parentSpacing : Int
181 , textMetrics : List TextMetrics
185type alias TextMetrics =
186 { actualBoundingBoxAscent : Float
187 , actualBoundingBoxDescent : Float
188 , actualBoundingBoxLeft : Float
189 , actualBoundingBoxRight : Float
195 metrics.actualBoundingBoxAscent
196 + metrics.actualBoundingBoxDescent
204type alias BoundingBox =
220type LayoutExpectation
222 { description : String
228type alias LayoutTest =
229 { elementDomId : String
230 , elementType : ElementType
232 , expectations : List LayoutExpectation
240equal : a -> a -> LayoutExpectation
243 { description = "Are equal"
244 , result = one == two
248true : String -> Bool -> LayoutExpectation
251 { description = label
256todo : String -> LayoutExpectation
265getIds : Element msg -> List String
267 "se-0" :: getElementId [ 0, 0 ] el
270getElementId : List Int -> Element msg -> List String
271getElementId level el =
276 attrID attrIndex attr =
279 getElementId (attrIndex :: -1 :: level) nearby.element
286 |> List.indexedMap attrID
289 childrenIDs children =
290 List.concat <| List.indexedMap (\i -> getElementId (i :: level)) children
294 id :: getElementId (0 :: level) child ++ attributeIDs attrs
296 Row attrs children ->
297 id :: childrenIDs children ++ attributeIDs attrs
299 Column attrs children ->
300 id :: childrenIDs children ++ attributeIDs attrs
302 TextColumn attrs children ->
303 id :: childrenIDs children ++ attributeIDs attrs
305 Paragraph attrs children ->
306 id :: childrenIDs children ++ attributeIDs attrs
319toElement : Element msg -> Element.Element msg
321 renderElement [ 0, 0 ] el
324toHtml : Element msg -> Html msg
326 Element.layout [ idAttr "0" ] <|
327 renderElement [ 0, 0 ] el
330idAttr : String -> Element.Attribute msg
332 Element.htmlAttribute (Html.Attributes.id ("se-" ++ id))
335renderElement : List Int -> Element msg -> Element.Element msg
336renderElement level el =
340 |> List.map String.fromInt
344 makeAttributes attrs =
346 |> List.indexedMap (renderAttribute level)
352 (id :: makeAttributes attrs)
353 (renderElement (0 :: level) child)
355 Row attrs children ->
357 (id :: makeAttributes attrs)
358 (List.indexedMap (\i -> renderElement (i :: level)) children)
360 Column attrs children ->
362 (id :: makeAttributes attrs)
363 (List.indexedMap (\i -> renderElement (i :: level)) children)
365 TextColumn attrs children ->
367 (id :: makeAttributes attrs)
368 (List.indexedMap (\i -> renderElement (i :: level)) children)
370 Paragraph attrs children ->
372 (id :: makeAttributes attrs)
373 (List.indexedMap (\i -> renderElement (i :: level)) children)
382renderAttribute : List Int -> Int -> Attr msg -> List (Element.Attribute msg)
383renderAttribute level attrIndex attr =
394 Nearby { location, element } ->
397 [ Element.above (renderElement (attrIndex :: -1 :: level) element) ]
400 [ Element.below (renderElement (attrIndex :: -1 :: level) element) ]
403 [ Element.onRight (renderElement (attrIndex :: -1 :: level) element) ]
406 [ Element.onLeft (renderElement (attrIndex :: -1 :: level) element) ]
409 [ Element.inFront (renderElement (attrIndex :: -1 :: level) element) ]
412 [ Element.behindContent (renderElement (attrIndex :: -1 :: level) element) ]
415 List.indexedMap (renderAttribute (attrIndex :: level)) batch
418 LabeledTest tested ->
426runTests : Dict String Found -> Element msg -> List LayoutTest
427runTests harvested el =
430 Dict.get "se-0" harvested
434 [ { elementDomId = "se-0"
435 , elementType = EmptyType
436 , label = "Finding root element"
439 { description = "Locating root element for rendering tests"
458levelToString : List Int -> String
461 |> List.map String.fromInt
463 |> (\x -> "se-" ++ x)
467 { siblings : List Found
469 , cache : Dict String Found
471 , element : Element msg
472 , location : LayoutContext
473 , parentSpacing : Int
476createTest { siblings, parent, cache, level, element, location, parentSpacing } =
480 |> Maybe.withDefault 0
485 testChildren : Found -> List (Element msg) -> List LayoutTest
486 testChildren found children =
489 -- Should check that this lookup doesn't fail.
490 -- Thoug if it does, it'll fail when the element itself is tested
493 Dict.get (levelToString (x :: level)) cache
495 (List.range 0 (List.length children))
497 List.foldl (applyChildTest found)
499 , upcoming = childrenFound
512 , previous : List Found
513 , tests : List LayoutTest
514 , upcoming : List Found
518 , previous : List Found
519 , tests : List LayoutTest
520 , upcoming : List Found
522 applyChildTest found child childTest =
523 -- { index, upcoming, previous, tests }
525 surroundingChildren =
526 case childTest.upcoming of
531 remaining ++ childTest.previous
535 { siblings = surroundingChildren
538 , level = childTest.index :: level
540 , parentSpacing = spacing
565 { index = childTest.index + 1
566 , tests = childTest.tests ++ childrenTests
568 case childTest.upcoming of
573 x :: childTest.previous
575 case childTest.upcoming of
583 tests : Found -> List (Attr msg) -> List (Element msg) -> List LayoutTest
584 tests self attributes children =
586 findBBox elem ( i, gathered ) =
599 case Dict.get (levelToString (i :: level)) cache of
603 Debug.log "el failed to find" elem
606 Debug.log "Failed to find child" (levelToString (i :: level))
618 List.foldl findBBox ( 0, [] ) children
624 -- Found -> Dict String Found -> List Int -> Int -> Surroundings -> Attr msg -> List Test
626 createAttributeTest self
630 { siblings = siblings
633 , selfElement = element
634 , children = childrenFoundData
635 , parentLayout = location
636 , parentSpacing = parentSpacing
643 ++ testChildren self children
645 case Dict.get id cache of
655 [ { elementDomId = id
656 , elementType = EmptyType
657 , label = "Finding element in DOM"
660 { description = "Locating element for rendering test"
670 tests self attrs [ child ]
672 Row attrs children ->
673 tests self attrs children
675 Column attrs children ->
676 tests self attrs children
678 TextColumn attrs children ->
679 tests self attrs children
681 Paragraph attrs children ->
682 tests self attrs children
699createAttributeTest parent cache level attrIndex surroundings attr =
702 "#" ++ levelToString level
712 [ { elementDomId = domId
714 toElementType surroundings.selfElement
715 , label = details.label
716 , expectations = details.test surroundings
726 , level = attrIndex :: -1 :: level
727 , location = IsNearby nearby.location
731 { label = nearby.label
742 |> List.indexedMap (\i attribute -> createAttributeTest parent cache (attrIndex :: level) i surroundings attribute)
745 LabeledTest { label, test } ->
746 [ { elementDomId = domId
747 , elementType = toElementType surroundings.selfElement
749 , expectations = test surroundings
754addAttribute : Attr msg -> Element msg -> Element msg
755addAttribute attr el =
758 El (attr :: attrs) child
760 Row attrs children ->
761 Row (attr :: attrs) children
763 Column attrs children ->
764 Column (attr :: attrs) children
766 TextColumn attrs children ->
767 TextColumn (attr :: attrs) children
769 Paragraph attrs children ->
770 Paragraph (attr :: attrs) children
779compareFormattedColor : Color -> String -> Bool
780compareFormattedColor color expected =
781 formatColor color == expected || formatColorWithAlpha color == expected
784formatColorWithAlpha : Color -> String
785formatColorWithAlpha (Internal.Rgba red green blue alpha) =
787 ("rgba(" ++ String.fromInt (round (red * 255)))
788 ++ (", " ++ String.fromInt (round (green * 255)))
789 ++ (", " ++ String.fromInt (round (blue * 255)))
794 ("rgba(" ++ String.fromInt (round (red * 255)))
795 ++ (", " ++ String.fromInt (round (green * 255)))
796 ++ (", " ++ String.fromInt (round (blue * 255)))
797 ++ (", " ++ String.fromFloat alpha ++ ")")
800formatColor : Color -> String
801formatColor (Internal.Rgba red green blue alpha) =
803 ("rgb(" ++ String.fromInt (round (red * 255)))
804 ++ (", " ++ String.fromInt (round (green * 255)))
805 ++ (", " ++ String.fromInt (round (blue * 255)))
809 ("rgb(" ++ String.fromInt (round (red * 255)))
810 ++ (", " ++ String.fromInt (round (green * 255)))
811 ++ (", " ++ String.fromInt (round (blue * 255)))
815getSpacing : Element msg -> Maybe Int
818 getSpacingAttr attr found =
819 if found /= Nothing then
828 List.foldr getSpacingAttr Nothing attrs
834 List.foldr getSpacingAttr Nothing attrs
846 TextColumn attrs _ ->
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list