1module Testable exposing
9 , LayoutExpectation(..)
15 , compareFormattedColor
19 , formatColorWithAlpha
22 , getSpacingFromAttributes
33import Dict exposing (Dict)
34import Element exposing (Color)
35import Html exposing (Html)
37import Internal.Model as Internal
38import Test exposing (Test)
42 = El (List (Attr msg)) (Element msg)
43 | Row (List (Attr msg)) (List (Element msg))
44 | Column (List (Attr msg)) (List (Element msg))
45 | TextColumn (List (Attr msg)) (List (Element msg))
46 | Paragraph (List (Attr msg)) (List (Element msg))
61elementTypeToString : ElementType -> String
62elementTypeToString elem =
86toElementType : Element msg -> ElementType
111{-| We have an attribute id in order to remove tests when an overriding attribtue is assigned.
113Basically, we want to implictly test for height/width shrink.
115But we want to skip this test if width/height is already set.
117This allows us to do that by comparing identities.
127 = Attr (Element.Attribute msg)
129 { test : Surroundings msg -> List LayoutExpectation
133 | Batch (List (Attr msg))
136 { location : Location
137 , element : Element msg
138 , test : Surroundings msg -> List LayoutExpectation
142 { test : Surroundings msg -> List LayoutExpectation
144 , attr : Element.Attribute msg
165type alias Surroundings msg =
166 { siblings : List Found
168 , children : List Found
170 , selfElement : Element msg
172 -- These values are needed to perform some types of tests.
173 , parentLayout : LayoutContext
174 , parentSpacing : Int
182 , textMetrics : List TextMetrics
186type alias TextMetrics =
187 { actualBoundingBoxAscent : Float
188 , actualBoundingBoxDescent : Float
189 , actualBoundingBoxLeft : Float
190 , actualBoundingBoxRight : Float
196 metrics.actualBoundingBoxAscent
197 + metrics.actualBoundingBoxDescent
205type alias BoundingBox =
221type LayoutExpectation
223 { description : String
229type alias LayoutTest =
230 { elementDomId : String
231 , elementType : ElementType
233 , expectations : List LayoutExpectation
241equal : a -> a -> LayoutExpectation
244 { description = "Are equal"
245 , result = one == two
249true : String -> Bool -> LayoutExpectation
252 { description = label
257todo : String -> LayoutExpectation
266getIds : Element msg -> List String
268 "se-0" :: getElementId [ 0, 0 ] el
271getElementId : List Int -> Element msg -> List String
272getElementId level el =
277 attrID attrIndex attr =
280 getElementId (attrIndex :: -1 :: level) nearby.element
287 |> List.indexedMap attrID
290 childrenIDs children =
291 List.concat <| List.indexedMap (\i -> getElementId (i :: level)) children
295 id :: getElementId (0 :: level) child ++ attributeIDs attrs
297 Row attrs children ->
298 id :: childrenIDs children ++ attributeIDs attrs
300 Column attrs children ->
301 id :: childrenIDs children ++ attributeIDs attrs
303 TextColumn attrs children ->
304 id :: childrenIDs children ++ attributeIDs attrs
306 Paragraph attrs children ->
307 id :: childrenIDs children ++ attributeIDs attrs
320toElement : Element msg -> Element.Element msg
322 renderElement [ 0, 0 ] el
325toHtml : Element msg -> Html msg
327 Element.layout [ idAttr "0" ] <|
328 renderElement [ 0, 0 ] el
331idAttr : String -> Element.Attribute msg
333 Element.htmlAttribute (Html.Attributes.id ("se-" ++ id))
336renderElement : List Int -> Element msg -> Element.Element msg
337renderElement level el =
341 |> List.map String.fromInt
345 makeAttributes attrs =
347 |> List.indexedMap (renderAttribute level)
353 (id :: makeAttributes attrs)
354 (renderElement (0 :: level) child)
356 Row attrs children ->
358 (id :: makeAttributes attrs)
359 (List.indexedMap (\i -> renderElement (i :: level)) children)
361 Column attrs children ->
363 (id :: makeAttributes attrs)
364 (List.indexedMap (\i -> renderElement (i :: level)) children)
366 TextColumn attrs children ->
368 (id :: makeAttributes attrs)
369 (List.indexedMap (\i -> renderElement (i :: level)) children)
371 Paragraph attrs children ->
373 (id :: makeAttributes attrs)
374 (List.indexedMap (\i -> renderElement (i :: level)) children)
383renderAttribute : List Int -> Int -> Attr msg -> List (Element.Attribute msg)
384renderAttribute level attrIndex attr =
395 Nearby { location, element } ->
398 [ Element.above (renderElement (attrIndex :: -1 :: level) element) ]
401 [ Element.below (renderElement (attrIndex :: -1 :: level) element) ]
404 [ Element.onRight (renderElement (attrIndex :: -1 :: level) element) ]
407 [ Element.onLeft (renderElement (attrIndex :: -1 :: level) element) ]
410 [ Element.inFront (renderElement (attrIndex :: -1 :: level) element) ]
413 [ Element.behindContent (renderElement (attrIndex :: -1 :: level) element) ]
416 List.indexedMap (renderAttribute (attrIndex :: level)) batch
419 LabeledTest tested ->
427runTests : Dict String Found -> Element msg -> List LayoutTest
428runTests harvested el =
431 Dict.get "se-0" harvested
435 [ { elementDomId = "se-0"
436 , elementType = EmptyType
437 , label = "Finding root element"
440 { description = "Locating root element for rendering tests"
459levelToString : List Int -> String
462 |> List.map String.fromInt
464 |> (\x -> "se-" ++ x)
468 { siblings : List Found
470 , cache : Dict String Found
472 , element : Element msg
473 , location : LayoutContext
474 , parentSpacing : Int
477createTest { siblings, parent, cache, level, element, location, parentSpacing } =
481 |> Maybe.withDefault 0
486 testChildren : Found -> List (Element msg) -> List LayoutTest
487 testChildren found children =
490 -- Should check that this lookup doesn't fail.
491 -- Thoug if it does, it'll fail when the element itself is tested
494 Dict.get (levelToString (x :: level)) cache
496 (List.range 0 (List.length children))
498 List.foldl (applyChildTest found)
500 , upcoming = childrenFound
513 , previous : List Found
514 , tests : List LayoutTest
515 , upcoming : List Found
519 , previous : List Found
520 , tests : List LayoutTest
521 , upcoming : List Found
523 applyChildTest found child childTest =
524 -- { index, upcoming, previous, tests }
526 surroundingChildren =
527 case childTest.upcoming of
532 remaining ++ childTest.previous
536 { siblings = surroundingChildren
539 , level = childTest.index :: level
541 , parentSpacing = spacing
566 { index = childTest.index + 1
567 , tests = childTest.tests ++ childrenTests
569 case childTest.upcoming of
574 x :: childTest.previous
576 case childTest.upcoming of
584 tests : Found -> List (Attr msg) -> List (Element msg) -> List LayoutTest
585 tests self attributes children =
587 findBBox elem ( i, gathered ) =
600 case Dict.get (levelToString (i :: level)) cache of
604 Debug.log "el failed to find" elem
607 Debug.log "Failed to find child" (levelToString (i :: level))
619 List.foldl findBBox ( 0, [] ) children
625 -- Found -> Dict String Found -> List Int -> Int -> Surroundings -> Attr msg -> List Test
627 createAttributeTest self
631 { siblings = siblings
634 , selfElement = element
635 , children = childrenFoundData
636 , parentLayout = location
637 , parentSpacing = parentSpacing
644 ++ testChildren self children
646 case Dict.get id cache of
656 [ { elementDomId = id
657 , elementType = EmptyType
658 , label = "Finding element in DOM"
661 { description = "Locating element for rendering test"
671 tests self attrs [ child ]
673 Row attrs children ->
674 tests self attrs children
676 Column attrs children ->
677 tests self attrs children
679 TextColumn attrs children ->
680 tests self attrs children
682 Paragraph attrs children ->
683 tests self attrs children
700createAttributeTest parent cache level attrIndex surroundings attr =
703 "#" ++ levelToString level
713 [ { elementDomId = domId
715 toElementType surroundings.selfElement
716 , label = details.label
717 , expectations = details.test surroundings
727 , level = attrIndex :: -1 :: level
728 , location = IsNearby nearby.location
732 { label = nearby.label
743 |> List.indexedMap (\i attribute -> createAttributeTest parent cache level i surroundings attribute)
746 LabeledTest { label, test } ->
747 [ { elementDomId = domId
748 , elementType = toElementType surroundings.selfElement
750 , expectations = test surroundings
755addAttribute : Attr msg -> Element msg -> Element msg
756addAttribute attr el =
759 El (attr :: attrs) child
761 Row attrs children ->
762 Row (attr :: attrs) children
764 Column attrs children ->
765 Column (attr :: attrs) children
767 TextColumn attrs children ->
768 TextColumn (attr :: attrs) children
770 Paragraph attrs children ->
771 Paragraph (attr :: attrs) children
780compareFormattedColor : Color -> String -> Bool
781compareFormattedColor color expected =
782 formatColor color == expected || formatColorWithAlpha color == expected
785formatColorWithAlpha : Color -> String
786formatColorWithAlpha (Internal.Rgba red green blue alpha) =
788 ("rgba(" ++ String.fromInt (round (red * 255)))
789 ++ (", " ++ String.fromInt (round (green * 255)))
790 ++ (", " ++ String.fromInt (round (blue * 255)))
795 ("rgba(" ++ String.fromInt (round (red * 255)))
796 ++ (", " ++ String.fromInt (round (green * 255)))
797 ++ (", " ++ String.fromInt (round (blue * 255)))
798 ++ (", " ++ String.fromFloat alpha ++ ")")
801formatColor : Color -> String
802formatColor (Internal.Rgba red green blue alpha) =
804 ("rgb(" ++ String.fromInt (round (red * 255)))
805 ++ (", " ++ String.fromInt (round (green * 255)))
806 ++ (", " ++ String.fromInt (round (blue * 255)))
810 ("rgb(" ++ String.fromInt (round (red * 255)))
811 ++ (", " ++ String.fromInt (round (green * 255)))
812 ++ (", " ++ String.fromInt (round (blue * 255)))
816getSpacingFromAttributes attrs =
821 (Spacing i) :: remain ->
824 (Batch batched) :: remain ->
825 getSpacingFromAttributes (batched ++ remain)
828 getSpacingFromAttributes remain
831getSpacing : Element msg -> Maybe Int
834 getSpacingAttr attr found =
835 if found /= Nothing then
844 List.foldr getSpacingAttr Nothing attrs
850 List.foldr getSpacingAttr Nothing attrs
862 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