git.iko.soy/typeable/elm-ui
on e4e9786 help sign in
1107 lines 39 kB history raw
1module Testable.Element exposing
2 ( Length(..)
3 , above
4 , alignBottom
5 , alignLeft
6 , alignRight
7 , alignTop
8 , alpha
9 , behindContent
10 , below
11 , centerX
12 , centerY
13 , column
14 , el
15 , expectRoundedEquality
16 , fill
17 , fillPortion
18 , height
19 , inFront
20 , isVisible
21 , label
22 , maximum
23 , minimum
24 , none
25 , onLeft
26 , onRight
27 , padding
28 , paddingXY
29 , paragraph
30 , px
31 , row
32 , shrink
33 , spacing
34 , text
35 , textColumn
36 , transparent
37 , width
38 )
40{-| This module should mirror the top level `Element` api, with one important distinction.
42The resulting `Element msg` structure can either be rendered to Html or transformed into a test suite that can be run.
44In order to run the test:
46 - render html
47 - gather information from the browser
48 - generate tests
50-}
52import Dict
53import Element
54import Expect
55import Html.Attributes
56import Testable
59text : String -> Testable.Element msg
60text =
61 Testable.Text
64el : List (Testable.Attr msg) -> Testable.Element msg -> Testable.Element msg
65el =
66 Testable.El
69row : List (Testable.Attr msg) -> List (Testable.Element msg) -> Testable.Element msg
70row =
71 Testable.Row
74column : List (Testable.Attr msg) -> List (Testable.Element msg) -> Testable.Element msg
75column =
76 Testable.Column
79none : Testable.Element msg
80none =
81 Testable.Empty
84paragraph : List (Testable.Attr msg) -> List (Testable.Element msg) -> Testable.Element msg
85paragraph =
86 Testable.Paragraph
89textColumn : List (Testable.Attr msg) -> List (Testable.Element msg) -> Testable.Element msg
90textColumn =
91 Testable.TextColumn
94type Length
95 = Px Int
96 | Fill Int
97 | Shrink
98 | Minimum Int Length
99 | Maximum Int Length
102minimum =
103 Minimum
106maximum =
107 Maximum
110px : Int -> Length
111px =
112 Px
115fill : Length
116fill =
117 Fill 1
120shrink : Length
121shrink =
122 Shrink
125fillPortion : Int -> Length
126fillPortion =
127 Fill
130label : String -> Testable.Attr msg
131label =
132 Testable.Label
135transparent : Bool -> Testable.Attr msg
136transparent on =
137 Testable.LabeledTest
138 { label =
139 if on then
140 "transparent"
142 else
143 "opaque"
144 , attr = Element.transparent on
145 , test =
146 \context _ ->
147 let
148 selfTransparency =
149 context.self.style
150 |> Dict.get "opacity"
151 |> Maybe.withDefault "notfound"
153 value =
154 if on then
155 "0"
157 else
158 "1"
159 in
160 Expect.equal value selfTransparency
161 }
164{-| -}
165isVisible : Testable.Attr msg
166isVisible =
167 Testable.LabeledTest
168 { label = "is-visible"
169 , attr = Element.htmlAttribute (Html.Attributes.style "not" "applicable")
170 , test =
171 \context _ ->
172 Expect.equal context.self.isVisible True
173 }
176{-| -}
177alpha : Float -> Testable.Attr msg
178alpha a =
179 Testable.LabeledTest
180 { label = "alpha-" ++ String.fromFloat a
181 , attr = Element.alpha a
182 , test =
183 \context _ ->
184 let
185 selfTransparency =
186 context.self.style
187 |> Dict.get "opacity"
188 |> Maybe.withDefault "notfound"
189 in
190 Expect.equal (String.fromFloat a) selfTransparency
191 }
194{-| -}
195padding : Int -> Testable.Attr msg
196padding pad =
197 Testable.LabeledTest
198 { label = "padding " ++ String.fromInt pad
199 , attr = Element.padding pad
200 , test =
201 \found _ ->
202 Expect.true ("Padding " ++ String.fromInt pad ++ " is present")
203 (List.all ((==) pad)
204 [ floor found.self.bbox.padding.left
205 , floor found.self.bbox.padding.right
206 , floor found.self.bbox.padding.top
207 , floor found.self.bbox.padding.bottom
208 ]
209 )
210 }
213{-| -}
214paddingXY : Int -> Int -> Testable.Attr msg
215paddingXY x y =
216 Testable.LabeledTest
217 { label = "paddingXY " ++ String.fromInt x ++ ", " ++ String.fromInt y
218 , attr = Element.paddingXY x y
219 , test =
220 \found _ ->
221 Expect.true ("PaddingXY (" ++ String.fromInt x ++ ", " ++ String.fromInt y ++ ") is present")
222 (List.all ((==) x)
223 [ floor found.self.bbox.padding.left
224 , floor found.self.bbox.padding.right
225 ]
226 && List.all ((==) y)
227 [ floor found.self.bbox.padding.top
228 , floor found.self.bbox.padding.bottom
229 ]
230 )
231 }
234widthHelper maybeMin maybeMax len =
235 let
236 addMin l =
237 case maybeMin of
238 Nothing ->
239 l
241 Just minPx ->
242 l |> Element.minimum minPx
244 addMax l =
245 case maybeMax of
246 Nothing ->
247 l
249 Just maxPx ->
250 l |> Element.maximum maxPx
252 minLabel =
253 case maybeMin of
254 Nothing ->
255 ""
257 Just i ->
258 " min:" ++ String.fromInt i
260 maxLabel =
261 case maybeMax of
262 Nothing ->
263 ""
265 Just i ->
266 " max:" ++ String.fromInt i
268 minMaxTest actualWidth =
269 case ( maybeMin, maybeMax ) of
270 ( Nothing, Nothing ) ->
271 True
273 ( Just lower, Nothing ) ->
274 lower <= actualWidth
276 ( Just lower, Just higher ) ->
277 lower <= actualWidth && actualWidth <= higher
279 ( Nothing, Just higher ) ->
280 actualWidth <= higher
281 in
282 case len of
283 Minimum m newLen ->
284 widthHelper (Just m) maybeMax newLen
286 Maximum m newLen ->
287 widthHelper maybeMin (Just m) newLen
289 Px val ->
290 -- Pixel values should ignore min and max?
291 Testable.LabeledTest
292 { label = "width " ++ String.fromInt val ++ "px" ++ minLabel ++ maxLabel
293 , attr =
294 Element.width
295 (Element.px val
296 |> addMin
297 |> addMax
298 )
299 , test =
300 \found _ ->
301 Expect.all
302 [ \_ ->
303 Expect.true "exact width is exact" (floor found.self.bbox.width == val)
304 , \_ -> Expect.true "min/max is upheld" (minMaxTest (floor found.self.bbox.width))
305 ]
306 ()
307 }
309 Fill portion ->
310 Testable.LabeledTest
311 { label = "width fill-" ++ String.fromInt portion ++ minLabel ++ maxLabel
312 , attr =
313 Element.width
314 (Element.fillPortion portion
315 |> addMin
316 |> addMax
317 )
318 , test =
319 \context _ ->
320 if List.member context.location [ Testable.IsNearby Testable.OnRight, Testable.IsNearby Testable.OnLeft ] then
321 Expect.true "width fill doesn't apply to onright/onleft elements" True
323 else
324 let
325 parentAvailableWidth =
326 context.parent.bbox.width - (context.self.bbox.padding.left + context.self.bbox.padding.right)
327 in
328 case context.location of
329 Testable.IsNearby _ ->
330 Expect.true "Nearby Element has fill width"
331 ((floor context.parent.bbox.width == floor context.self.bbox.width)
332 || minMaxTest (floor context.self.bbox.width)
333 )
335 Testable.InColumn ->
336 Expect.true "Element within column has fill width"
337 ((floor parentAvailableWidth == floor context.self.bbox.width)
338 || minMaxTest (floor context.self.bbox.width)
339 )
341 Testable.InEl ->
342 Expect.true "Element within element has fill width" <|
343 (floor parentAvailableWidth == floor context.self.bbox.width)
344 || minMaxTest (floor context.self.bbox.width)
346 _ ->
347 let
348 spacePerPortion =
349 parentAvailableWidth / toFloat (List.length context.siblings + 1)
350 in
351 Expect.true "element has fill width" <|
352 (floor spacePerPortion == floor context.self.bbox.width)
353 || minMaxTest (floor context.self.bbox.width)
354 }
356 Shrink ->
357 Testable.LabeledTest
358 { label = "width shrink" ++ minLabel ++ maxLabel
359 , attr =
360 Element.width
361 (Element.shrink
362 |> addMin
363 |> addMax
364 )
365 , test =
366 \context _ ->
367 let
368 childWidth child =
369 -- TODO: add margin values to widths
370 child.bbox.width
372 totalChildren =
373 context.children
374 |> List.map childWidth
375 |> List.sum
377 horizontalPadding =
378 context.self.bbox.padding.left + context.self.bbox.padding.right
380 spacingValue =
381 toFloat context.parentSpacing * (toFloat (List.length context.children) - 1)
382 in
383 if totalChildren == 0 then
384 -- TODO: The issue is that we have a hard time measuring `text` elements
385 -- So if a element has a text child, then it's width isn't going to show up in the system.
386 expectRoundedEquality context.self.bbox.width context.self.bbox.width
388 else
389 -- This fails if this element is actually a column
390 -- So we need to capture what this element is in order to do this calculation.
391 expectRoundedEquality (totalChildren + horizontalPadding + spacingValue) context.self.bbox.width
392 }
395heightHelper maybeMin maybeMax len =
396 let
397 addMin l =
398 case maybeMin of
399 Nothing ->
400 l
402 Just minPx ->
403 l |> Element.minimum minPx
405 addMax l =
406 case maybeMax of
407 Nothing ->
408 l
410 Just maxPx ->
411 l |> Element.maximum maxPx
413 minLabel =
414 case maybeMin of
415 Nothing ->
416 ""
418 Just i ->
419 " min:" ++ String.fromInt i
421 maxLabel =
422 case maybeMax of
423 Nothing ->
424 ""
426 Just i ->
427 " max:" ++ String.fromInt i
429 minMaxTest actualheight =
430 case ( maybeMin, maybeMax ) of
431 ( Nothing, Nothing ) ->
432 True
434 ( Just lower, Nothing ) ->
435 lower <= actualheight
437 ( Just lower, Just higher ) ->
438 lower <= actualheight && actualheight <= higher
440 ( Nothing, Just higher ) ->
441 actualheight <= higher
442 in
443 case len of
444 Minimum m newLen ->
445 heightHelper (Just m) maybeMax newLen
447 Maximum m newLen ->
448 heightHelper maybeMin (Just m) newLen
450 Px val ->
451 -- Pixel values should ignore min and max?
452 Testable.LabeledTest
453 { label = "height " ++ String.fromInt val ++ "px" ++ minLabel ++ maxLabel
454 , attr =
455 Element.height
456 (Element.px val
457 |> addMin
458 |> addMax
459 )
460 , test =
461 \found _ ->
462 Expect.all
463 [ \_ ->
464 Expect.true ("exact height is exact: " ++ String.fromInt (floor found.self.bbox.height) ++ "," ++ String.fromInt val)
465 (floor found.self.bbox.height == val)
466 , \_ ->
467 Expect.true "min/max holds true"
468 (minMaxTest (floor found.self.bbox.height))
469 ]
470 ()
471 }
473 Fill portion ->
474 Testable.LabeledTest
475 { label = "height fill-" ++ String.fromInt portion ++ minLabel ++ maxLabel
476 , attr =
477 Element.height
478 (Element.fillPortion portion
479 |> addMin
480 |> addMax
481 )
482 , test =
483 \context _ ->
484 if List.member context.location [ Testable.IsNearby Testable.Above, Testable.IsNearby Testable.Below ] then
485 Expect.true "height fill doesn't apply to above/below elements" True
487 else
488 let
489 parentAvailableHeight =
490 context.parent.bbox.height - (context.self.bbox.padding.top + context.self.bbox.padding.bottom)
491 in
492 case context.location of
493 Testable.IsNearby _ ->
494 Expect.true "Nearby Element has fill height"
495 ((floor context.parent.bbox.height == floor context.self.bbox.height)
496 || minMaxTest (floor context.self.bbox.height)
497 )
499 Testable.InColumn ->
500 Expect.true "Element within column has fill height"
501 ((floor parentAvailableHeight == floor context.self.bbox.height)
502 || minMaxTest (floor context.self.bbox.height)
503 )
505 Testable.InEl ->
506 Expect.true "Element within el has fill height" <|
507 (floor parentAvailableHeight == floor context.self.bbox.height)
508 || minMaxTest (floor context.self.bbox.height)
510 _ ->
511 let
512 spacePerPortion =
513 parentAvailableHeight / toFloat (List.length context.siblings + 1)
514 in
515 Expect.true "el has fill height" <|
516 (floor spacePerPortion == floor context.self.bbox.height)
517 || minMaxTest (floor context.self.bbox.height)
518 }
520 Shrink ->
521 Testable.LabeledTest
522 { label = "height shrink" ++ minLabel ++ maxLabel
523 , attr =
524 Element.height
525 (Element.shrink
526 |> addMin
527 |> addMax
528 )
529 , test =
530 \context _ ->
531 let
532 childWidth child =
533 -- TODO: add margin values to heights
534 child.bbox.height
536 totalChildren =
537 context.children
538 |> List.map childWidth
539 |> List.sum
541 verticalPadding =
542 context.self.bbox.padding.top + context.self.bbox.padding.bottom
544 spacingValue =
545 toFloat context.parentSpacing * (toFloat (List.length context.children) - 1)
546 in
547 if totalChildren == 0 then
548 -- TODO: The issue is that we have a hard time measuring `text` elements
549 -- So if a element has a text child, then it's height isn't going to show up in the system.
550 expectRoundedEquality context.self.bbox.height context.self.bbox.height
552 else
553 -- This fails if this element is actually a column
554 -- So we need to capture what this element is in order to do this calculation.
555 expectRoundedEquality (totalChildren + verticalPadding + spacingValue) context.self.bbox.height
556 }
559width : Length -> Testable.Attr msg
560width len =
561 widthHelper Nothing Nothing len
564height : Length -> Testable.Attr msg
565height len =
566 heightHelper Nothing Nothing len
569spacing : Int -> Testable.Attr msg
570spacing space =
571 Testable.Batch
572 [ Testable.Spacing space
573 , Testable.LabeledTest
574 { label = "spacing: " ++ String.fromInt space
575 , attr = Element.spacing space
576 , test =
577 \found _ ->
578 let
579 findDistance child total =
580 List.concatMap
581 (\otherChild ->
582 let
583 horizontal =
584 round <|
585 child.bbox.left
586 - otherChild.bbox.right
588 vertical =
589 round <|
590 child.bbox.top
591 - otherChild.bbox.bottom
592 in
593 [ if horizontal > 0 then
594 horizontal
596 else
597 space
598 , if vertical > 0 then
599 vertical
601 else
602 space
603 ]
604 )
605 found.children
606 ++ total
608 distances =
609 List.foldl findDistance [] found.children
611 allAreSpaced =
612 List.foldl
613 (\x wrong ->
614 if not (x >= space) then
615 x :: wrong
617 else
618 wrong
619 )
620 []
621 distances
622 in
623 Expect.true
624 ("All children are at least "
625 ++ String.fromInt space
626 ++ " pixels apart."
627 ++ Debug.toString allAreSpaced
628 ++ " are not though"
629 )
630 (allAreSpaced == [])
631 }
632 ]
635{-| alignLeft needs to account for
637 - parent padding
638 - elements to the left
639 - spacing value
641in order to calculate the expected result.
643Also need parent rendering context if this is to work with wrapped rows in the future.
645All sibling elements
647-}
648alignLeft : Testable.Attr msg
649alignLeft =
650 Testable.LabeledTest
651 { label = "alignLeft"
652 , attr = Element.alignLeft
653 , test =
654 \found _ ->
655 if List.member found.location [ Testable.IsNearby Testable.OnLeft, Testable.IsNearby Testable.OnRight ] then
656 Expect.true "alignLeft doesn't apply to elements that are onLeft or onRight" True
658 else if
659 List.member found.location
660 [ Testable.IsNearby Testable.InFront
661 , Testable.IsNearby Testable.Behind
662 , Testable.IsNearby Testable.Above
663 , Testable.IsNearby Testable.Below
664 ]
665 then
666 expectRoundedEquality
667 found.self.bbox.left
668 found.parent.bbox.left
670 else if List.length found.siblings == 0 then
671 expectRoundedEquality
672 found.self.bbox.left
673 (found.parent.bbox.left + found.parent.bbox.padding.left)
675 else
676 case found.location of
677 Testable.InRow ->
678 let
679 siblingsOnLeft =
680 List.filter (\x -> x.bbox.right < found.self.bbox.left) found.siblings
682 spacings =
683 toFloat (List.length siblingsOnLeft * found.parentSpacing)
685 widthsOnLeft =
686 siblingsOnLeft
687 |> List.map (.width << .bbox)
688 |> List.sum
689 in
690 expectRoundedEquality
691 found.self.bbox.left
692 (found.parent.bbox.left + (found.parent.bbox.padding.left + widthsOnLeft + spacings))
694 _ ->
695 expectRoundedEquality
696 found.self.bbox.left
697 (found.parent.bbox.left + found.parent.bbox.padding.left)
698 }
701{-| -}
702centerX : Testable.Attr msg
703centerX =
704 Testable.LabeledTest
705 { label = "centerX"
706 , attr = Element.centerX
707 , test =
708 \found _ ->
709 let
710 selfCenter : Float
711 selfCenter =
712 found.self.bbox.left + (found.self.bbox.width / 2)
714 parentCenter : Float
715 parentCenter =
716 found.parent.bbox.left + (found.parent.bbox.width / 2)
717 in
718 if List.member found.location [ Testable.IsNearby Testable.OnRight, Testable.IsNearby Testable.OnLeft ] then
719 Expect.true "centerX doesn't apply to elements that are onLeft or onRight" True
721 else if List.length found.siblings == 0 then
722 expectRoundedEquality
723 selfCenter
724 parentCenter
726 else
727 case found.location of
728 Testable.InRow ->
729 let
730 siblingsOnLeft =
731 List.filter (\x -> x.bbox.right < found.self.bbox.left) found.siblings
733 siblingsOnRight =
734 List.filter (\x -> x.bbox.left > found.self.bbox.right) found.siblings
736 widthsOnLeft : Float
737 widthsOnLeft =
738 siblingsOnLeft
739 |> List.map (.width << .bbox)
740 |> List.sum
741 |> (\x -> x + (toFloat (List.length siblingsOnLeft) * toFloat found.parentSpacing))
743 widthsOnRight =
744 siblingsOnRight
745 |> List.map (.width << .bbox)
746 |> List.sum
747 |> (\x -> x + (toFloat (List.length siblingsOnRight) * toFloat found.parentSpacing))
749 expectedCenter : Float
750 expectedCenter =
751 found.parent.bbox.left
752 + widthsOnLeft
753 + ((found.parent.bbox.width - (widthsOnRight + widthsOnLeft))
754 / 2
755 )
756 in
757 expectRoundedEquality
758 selfCenter
759 expectedCenter
761 _ ->
762 expectRoundedEquality selfCenter parentCenter
763 }
766{-| -}
767alignRight : Testable.Attr msg
768alignRight =
769 Testable.LabeledTest
770 { label = "alignRight"
771 , attr = Element.alignRight
772 , test =
773 \found _ ->
774 if List.member found.location [ Testable.IsNearby Testable.OnLeft, Testable.IsNearby Testable.OnRight ] then
775 Expect.true "alignRight doesn't apply to elements that are onLeft or onRight" True
777 else if
778 List.member found.location
779 [ Testable.IsNearby Testable.InFront
780 , Testable.IsNearby Testable.Behind
781 , Testable.IsNearby Testable.Above
782 , Testable.IsNearby Testable.Below
783 ]
784 then
785 expectRoundedEquality
786 found.self.bbox.right
787 found.parent.bbox.right
789 else if List.length found.siblings == 0 then
790 expectRoundedEquality
791 found.self.bbox.right
792 (found.parent.bbox.right + found.parent.bbox.padding.right)
794 else
795 case found.location of
796 Testable.InRow ->
797 let
798 siblingsOnRight =
799 List.filter (\x -> x.bbox.left > found.self.bbox.right) found.siblings
801 spacings =
802 toFloat (List.length siblingsOnRight * found.parentSpacing)
804 widthsOnRight =
805 siblingsOnRight
806 |> List.map (.width << .bbox)
807 |> List.sum
808 in
809 expectRoundedEquality
810 found.self.bbox.right
811 (found.parent.bbox.right - (found.parent.bbox.padding.right + widthsOnRight + spacings))
813 _ ->
814 expectRoundedEquality
815 found.self.bbox.right
816 (found.parent.bbox.right + found.parent.bbox.padding.right)
817 }
820{-| -}
821alignTop : Testable.Attr msg
822alignTop =
823 Testable.LabeledTest
824 { label = "alignTop"
825 , attr = Element.alignTop
826 , test =
827 \found _ ->
828 if List.member found.location [ Testable.IsNearby Testable.Above, Testable.IsNearby Testable.Below ] then
829 Expect.true "alignTop doesn't apply to elements that are above or below" True
831 else if
832 List.member found.location
833 [ Testable.IsNearby Testable.InFront
834 , Testable.IsNearby Testable.Behind
835 , Testable.IsNearby Testable.OnRight
836 , Testable.IsNearby Testable.OnLeft
837 ]
838 then
839 expectRoundedEquality
840 found.self.bbox.top
841 found.parent.bbox.top
843 else if List.length found.siblings == 0 then
844 expectRoundedEquality
845 found.self.bbox.top
846 (found.parent.bbox.top + found.parent.bbox.padding.top)
848 else
849 case found.location of
850 Testable.InColumn ->
851 let
852 siblingsAbove =
853 List.filter (\x -> x.bbox.bottom < found.self.bbox.top) found.siblings
855 spacings =
856 toFloat (List.length siblingsAbove * found.parentSpacing)
858 heightsAbove =
859 siblingsAbove
860 |> List.map (.height << .bbox)
861 |> List.sum
862 in
863 expectRoundedEquality
864 found.self.bbox.top
865 (found.parent.bbox.top + (found.parent.bbox.padding.top + heightsAbove + spacings))
867 _ ->
868 expectRoundedEquality
869 found.self.bbox.top
870 found.parent.bbox.top
871 }
874{-| -}
875alignBottom : Testable.Attr msg
876alignBottom =
877 Testable.LabeledTest
878 { label = "alignBottom"
879 , attr = Element.alignBottom
880 , test =
881 \found _ ->
882 if List.member found.location [ Testable.IsNearby Testable.Above, Testable.IsNearby Testable.Below ] then
883 Expect.true "alignBottom doesn't apply to elements that are above or below" True
885 else if
886 List.member found.location
887 [ Testable.IsNearby Testable.InFront
888 , Testable.IsNearby Testable.Behind
889 , Testable.IsNearby Testable.OnRight
890 , Testable.IsNearby Testable.OnLeft
891 ]
892 then
893 expectRoundedEquality
894 found.self.bbox.bottom
895 found.parent.bbox.bottom
897 else if List.length found.siblings == 0 then
898 expectRoundedEquality
899 found.self.bbox.bottom
900 (found.parent.bbox.bottom + found.parent.bbox.padding.bottom)
902 else
903 case found.location of
904 Testable.InColumn ->
905 let
906 siblingsBelow =
907 List.filter (\x -> x.bbox.top > found.self.bbox.bottom) found.siblings
909 spacings =
910 toFloat (List.length siblingsBelow * found.parentSpacing)
912 heightsBelow =
913 siblingsBelow
914 |> List.map (.height << .bbox)
915 |> List.sum
916 in
917 expectRoundedEquality
918 found.self.bbox.bottom
919 (found.parent.bbox.bottom - (found.parent.bbox.padding.bottom + heightsBelow + spacings))
921 _ ->
922 expectRoundedEquality
923 found.self.bbox.bottom
924 (found.parent.bbox.bottom + found.parent.bbox.padding.bottom)
925 }
928expectRoundedEquality x y =
929 Expect.true ("within 1 of each other " ++ String.fromFloat x ++ ":" ++ String.fromFloat y)
930 (abs (x - y) < 1)
933{-| -}
934centerY : Testable.Attr msg
935centerY =
936 Testable.LabeledTest
937 { label = "centerY"
938 , attr = Element.centerY
939 , test =
940 \found _ ->
941 let
942 selfCenter =
943 found.self.bbox.top + (found.self.bbox.height / 2)
945 parentCenter =
946 found.parent.bbox.top + (found.parent.bbox.height / 2)
947 in
948 if List.member found.location [ Testable.IsNearby Testable.Above, Testable.IsNearby Testable.Below ] then
949 Expect.true "centerY doesn't apply to elements that are above or below" True
951 else if List.length found.siblings == 0 then
952 expectRoundedEquality
953 selfCenter
954 parentCenter
956 else
957 case found.location of
958 Testable.InColumn ->
959 let
960 siblingsOnTop =
961 List.filter (\x -> x.bbox.bottom < found.self.bbox.top) found.siblings
963 siblingsBelow =
964 List.filter (\x -> x.bbox.top > found.self.bbox.bottom) found.siblings
966 heightsAbove : Float
967 heightsAbove =
968 siblingsOnTop
969 |> List.map (.height << .bbox)
970 |> List.sum
971 |> (\x -> x + (toFloat (List.length siblingsOnTop) * toFloat found.parentSpacing))
973 heightsBelow =
974 siblingsBelow
975 |> List.map (.height << .bbox)
976 |> List.sum
977 |> (\x -> x + (toFloat (List.length siblingsBelow) * toFloat found.parentSpacing))
979 expectedCenter : Float
980 expectedCenter =
981 found.parent.bbox.top
982 + heightsAbove
983 + ((found.parent.bbox.height - (heightsBelow + heightsAbove))
984 / 2
985 )
986 in
987 expectRoundedEquality
988 selfCenter
989 expectedCenter
991 _ ->
992 expectRoundedEquality selfCenter parentCenter
993 }
996{-| -}
997above : Testable.Element msg -> Testable.Attr msg
998above element =
999 Testable.Nearby
1000 { location = Testable.Above
1001 , element = element
1002 , label = "above"
1003 , test =
1004 \found _ ->
1005 expectRoundedEquality found.self.bbox.bottom found.parent.bbox.top
1009{-| -}
1010below : Testable.Element msg -> Testable.Attr msg
1011below element =
1012 Testable.Nearby
1013 { location = Testable.Below
1014 , element = element
1015 , label = "below"
1016 , test =
1017 \found _ ->
1018 expectRoundedEquality found.self.bbox.top found.parent.bbox.bottom
1022{-| -}
1023onRight : Testable.Element msg -> Testable.Attr msg
1024onRight element =
1025 Testable.Nearby
1026 { location = Testable.OnRight
1027 , element = element
1028 , label = "onRight"
1029 , test =
1030 \found _ ->
1031 expectRoundedEquality found.self.bbox.left found.parent.bbox.right
1035{-| -}
1036onLeft : Testable.Element msg -> Testable.Attr msg
1037onLeft element =
1038 Testable.Nearby
1039 { location = Testable.OnLeft
1040 , element = element
1041 , label = "onLeft"
1042 , test =
1043 \found _ ->
1044 expectRoundedEquality found.self.bbox.right found.parent.bbox.left
1048compare x vs y =
1049 vs (round x) (round y) || vs (floor x) (floor y)
1052{-| -}
1053inFront : Testable.Element msg -> Testable.Attr msg
1054inFront element =
1055 Testable.Nearby
1056 { location = Testable.InFront
1057 , element = element
1058 , label = "inFront"
1059 , test =
1060 withinHelper
1064withinHelper found _ =
1065 let
1066 horizontalCheck =
1067 if found.self.bbox.width > found.parent.bbox.width then
1068 [ compare found.self.bbox.right (<=) found.parent.bbox.right
1069 || compare found.self.bbox.left (>=) found.parent.bbox.left
1072 else
1073 [ compare found.self.bbox.right (<=) found.parent.bbox.right
1074 , compare found.self.bbox.left (>=) found.parent.bbox.left
1077 verticalCheck =
1078 if found.self.bbox.width > found.parent.bbox.width then
1079 [ compare found.self.bbox.top (>=) found.parent.bbox.top
1080 || compare found.self.bbox.bottom (<=) found.parent.bbox.bottom
1083 else
1084 [ compare found.self.bbox.top (>=) found.parent.bbox.top
1085 , compare found.self.bbox.bottom (<=) found.parent.bbox.bottom
1087 in
1088 Expect.true "within the confines of the parent"
1089 (List.all ((==) True)
1090 (List.concat
1091 [ horizontalCheck
1092 , verticalCheck
1098{-| -}
1099behindContent : Testable.Element msg -> Testable.Attr msg
1100behindContent element =
1101 Testable.Nearby
1102 { location = Testable.Behind
1103 , element = element
1104 , label = "behindContent"
1105 , test =
1106 withinHelper