@@ -10,6 +10,7 @@ module Testable.Element exposing
1010 , below
1111 , centerX
1212 , centerY
13+ , clip
1314 , column
1415 , el
1516 , expectRoundedEquality
@@ -20,6 +21,7 @@ module Testable.Element exposing
2021 , isVisible
2122 , label
2223 , layout
24+ , link
2325 , maximum
2426 , minimum
2527 , moveDown
@@ -36,10 +38,14 @@ module Testable.Element exposing
3638 , rgb
3739 , rgba
3840 , row
41+ , scrollbarX
42+ , scrollbarY
43+ , scrollbars
3944 , shrink
4045 , spacing
4146 , text
4247 , textColumn
48+ , toProgram
4349 , transparent
4450 , width
4551 )
@@ -58,17 +64,21 @@ In order to run the test:
5864
5965import Dict
6066import Element
61−import Expect
6267import Html.Attributes
6368import Testable
6469import Testable.Runner
6570
6671
67−layout : List (Testable.Attr msg) -> Testable.Element Testable.Runner.Msg -> Testable.Runner.TestableProgram
72+{-| This is used when we want to run all tests in a test suite instead of one at a time.
73+-}
74+toProgram : Testable.Runner.Testable -> Testable.Runner.TestableProgram
75+toProgram testable =
76+ Testable.Runner.program [ testable ]
77+
78+
79+layout : List (Testable.Attr msg) -> Testable.Element Testable.Runner.Msg -> Testable.Runner.Testable
6880layout attrs elem =
69− Testable.Runner.program
70− [ ( "Open Case", elem )
71− ]
81+ Testable.Runner.testable "Test" elem
7282
7383
7484text : String -> Testable.Element msg
@@ -77,18 +87,18 @@ text =
7787
7888
7989el : List (Testable.Attr msg) -> Testable.Element msg -> Testable.Element msg
80−el =
81− Testable.El
90+el attrs =
91+ Testable.El (implicitWidthHeightShrink attrs)
8292
8393
8494row : List (Testable.Attr msg) -> List (Testable.Element msg) -> Testable.Element msg
85−row =
86− Testable.Row
95+row attrs =
96+ Testable.Row (implicitWidthHeightShrink attrs)
8797
8898
8999column : List (Testable.Attr msg) -> List (Testable.Element msg) -> Testable.Element msg
90−column =
91− Testable.Column
100+column attrs =
101+ Testable.Column (implicitWidthHeightShrink attrs)
92102
93103
94104none : Testable.Element msg
@@ -97,13 +107,60 @@ none =
97107
98108
99109paragraph : List (Testable.Attr msg) -> List (Testable.Element msg) -> Testable.Element msg
100−paragraph =
101− Testable.Paragraph
110+paragraph attrs =
111+ let
112+ withImplicits =
113+ implicitTest (widthHelper Nothing Nothing (Fill 1))
114+ :: implicitTest (heightHelper Nothing Nothing Shrink)
115+ :: attrs
116+ in
117+ Testable.Paragraph (skipOverridden withImplicits)
102118
103119
104120textColumn : List (Testable.Attr msg) -> List (Testable.Element msg) -> Testable.Element msg
105−textColumn =
106− Testable.TextColumn
121+textColumn attrs =
122+ let
123+ withImplicits =
124+ implicitTest (widthHelper (Just 500) (Just 750) (Fill 1))
125+ :: implicitTest (heightHelper Nothing Nothing Shrink)
126+ :: attrs
127+ in
128+ Testable.TextColumn (skipOverridden withImplicits)
129+
130+
131+link :
132+ List (Testable.Attr msg)
133+ ->
134+ { url : String
135+ , label : Testable.Element msg
136+ }
137+ -> Testable.Element msg
138+link attrs details =
139+ Testable.Link details.url
140+ (implicitWidthHeightShrink attrs)
141+ details.label
142+
143+
144+clip =
145+ Testable.Attr Element.clip
146+
147+
148+{-| -}
149+scrollbars : Testable.Attr msg
150+scrollbars =
151+ Testable.Attr Element.scrollbars
152+
153+
154+{-| -}
155+scrollbarY : Testable.Attr msg
156+scrollbarY =
157+ Testable.Attr Element.scrollbarY
158+
159+
160+{-| -}
161+scrollbarX : Testable.Attr msg
162+scrollbarX =
163+ Testable.Attr Element.scrollbarX
107164
108165
109166{-| Old labeling mechanism that i removed to hastily
@@ -182,6 +239,7 @@ transparent on =
182239 else
183240 "opaque"
184241 , attr = Element.transparent on
242+ , id = Testable.NoId
185243 , test =
186244 \context ->
187245 let
@@ -204,9 +262,9 @@ transparent on =
204262{-| -}
205263isVisible : Testable.Attr msg
206264isVisible =
207− Testable.LabeledTest
265+ Testable.AttrTest
208266 { label = "is-visible"
209− , attr = Element.htmlAttribute (Html.Attributes.style "not" "applicable")
267+ , id = Testable.NoId
210268 , test =
211269 \context ->
212270 [ Testable.equal context.self.isVisible True ]
@@ -219,6 +277,7 @@ alpha a =
219277 Testable.LabeledTest
220278 { label = "alpha-" ++ String.fromFloat a
221279 , attr = Element.alpha a
280+ , id = Testable.NoId
222281 , test =
223282 \context ->
224283 let
@@ -237,6 +296,7 @@ padding pad =
237296 Testable.LabeledTest
238297 { label = "padding " ++ String.fromInt pad
239298 , attr = Element.padding pad
299+ , id = Testable.NoId
240300 , test =
241301 \found ->
242302 [ Testable.true ("Padding " ++ String.fromInt pad ++ " is present")
@@ -257,6 +317,7 @@ paddingXY x y =
257317 Testable.LabeledTest
258318 { label = "paddingXY " ++ String.fromInt x ++ ", " ++ String.fromInt y
259319 , attr = Element.paddingXY x y
320+ , id = Testable.NoId
260321 , test =
261322 \found ->
262323 [ Testable.true ("PaddingXY (" ++ String.fromInt x ++ ", " ++ String.fromInt y ++ ") is present")
@@ -273,6 +334,11 @@ paddingXY x y =
273334 }
274335
275336
337+listIf ls =
338+ List.filter Tuple.first ls
339+ |> List.map Tuple.second
340+
341+
276342widthHelper maybeMin maybeMax len =
277343 let
278344 addMin l =
@@ -332,6 +398,7 @@ widthHelper maybeMin maybeMax len =
332398 -- Pixel values should ignore min and max?
333399 Testable.LabeledTest
334400 { label = "width " ++ String.fromInt val ++ "px" ++ minLabel ++ maxLabel
401+ , id = Testable.IsWidth
335402 , attr =
336403 Element.width
337404 (Element.px val
@@ -340,7 +407,10 @@ widthHelper maybeMin maybeMax len =
340407 )
341408 , test =
342409 \found ->
343− [ Testable.true "exact width is exact" (floor found.self.bbox.width == val)
410+ [ expectRoundedEquality
411+ { expected = toFloat val
412+ , found = found.self.bbox.width
413+ }
344414 , Testable.true "min/max is upheld" (minMaxTest (floor found.self.bbox.width))
345415 ]
346416 }
@@ -353,6 +423,7 @@ widthHelper maybeMin maybeMax len =
353423
354424 else
355425 "width fill-" ++ String.fromInt portion ++ minLabel ++ maxLabel
426+ , id = Testable.IsWidth
356427 , attr =
357428 Element.width
358429 (Element.fillPortion portion
@@ -361,7 +432,7 @@ widthHelper maybeMin maybeMax len =
361432 )
362433 , test =
363434 \context ->
364− if List.member context.location [ Testable.IsNearby Testable.OnRight, Testable.IsNearby Testable.OnLeft ] then
435+ if List.member context.parentLayout [ Testable.IsNearby Testable.OnRight, Testable.IsNearby Testable.OnLeft ] then
365436 [ Testable.true "width fill doesn't apply to onright/onleft elements" True ]
366437
367438 else
@@ -369,33 +440,93 @@ widthHelper maybeMin maybeMax len =
369440 parentAvailableWidth =
370441 context.parent.bbox.width - (context.self.bbox.padding.left + context.self.bbox.padding.right)
371442 in
372− [ case context.location of
373− Testable.IsNearby _ ->
374− Testable.true "Nearby Element has fill width"
375− ((floor context.parent.bbox.width == floor context.self.bbox.width)
376− || minMaxTest (floor context.self.bbox.width)
377− )
378−
379− Testable.InColumn ->
380− Testable.true "Element within column has fill width"
381− ((floor parentAvailableWidth == floor context.self.bbox.width)
382− || minMaxTest (floor context.self.bbox.width)
383− )
384−
385− Testable.InEl ->
386− Testable.true "Element within element has fill width" <|
387− (floor parentAvailableWidth == floor context.self.bbox.width)
388− || minMaxTest (floor context.self.bbox.width)
389−
390− _ ->
391− let
392− spacePerPortion =
393− parentAvailableWidth / toFloat (List.length context.siblings + 1)
394− in
395− Testable.true "element has fill width" <|
396− (floor spacePerPortion == floor context.self.bbox.width)
397− || minMaxTest (floor context.self.bbox.width)
398− ]
443+ List.concat
444+ [ case context.parentLayout of
445+ Testable.IsNearby _ ->
446+ [ Testable.true "Nearby Element has fill width"
447+ ((floor context.parent.bbox.width == floor context.self.bbox.width)
448+ || minMaxTest (floor context.self.bbox.width)
449+ )
450+ ]
451+
452+ Testable.InColumn ->
453+ [ Testable.true "Element within column has fill width"
454+ ((floor parentAvailableWidth == floor context.self.bbox.width)
455+ || minMaxTest (floor context.self.bbox.width)
456+ )
457+ ]
458+
459+ Testable.InEl ->
460+ [ Testable.true "Element within element has fill width" <|
461+ (floor parentAvailableWidth == floor context.self.bbox.width)
462+ || minMaxTest (floor context.self.bbox.width)
463+ ]
464+
465+ _ ->
466+ let
467+ spacePerPortion =
468+ parentAvailableWidth / toFloat (List.length context.siblings + 1)
469+ in
470+ [ Testable.true "element has fill width" <|
471+ (floor spacePerPortion == floor context.self.bbox.width)
472+ || minMaxTest (floor context.self.bbox.width)
473+ ]
474+ , [ Testable.lessThanOrEqual "not larger than parent"
475+ context.self.bbox.width
476+ context.parent.bbox.width
477+ ]
478+ , case context.selfElement of
479+ Testable.Paragraph _ _ ->
480+ -- A paragraph with width fill
481+ -- we want to test for correct text wrapping here.
482+ --
483+ let
484+ childWidth child =
485+ child.bbox.width
486+
487+ totalChildren =
488+ context.children
489+ |> List.map childWidth
490+ |> List.append (List.map .width context.self.textMetrics)
491+ |> List.sum
492+
493+ horizontalPadding =
494+ context.self.bbox.padding.left + context.self.bbox.padding.right
495+
496+ totalCalculatedWidth =
497+ totalChildren + horizontalPadding
498+
499+ expectedLines =
500+ if boxChildrenHeight > 20 then
501+ ceiling (boxChildrenHeight / 20)
502+
503+ else
504+ ceiling (totalCalculatedWidth / context.self.bbox.width)
505+
506+ boxChildrenHeight =
507+ context.children
508+ |> List.map
509+ (\c ->
510+ c.bbox.height
511+ )
512+ |> List.sum
513+ in
514+ [ Testable.true "text wrapping, checking height"
515+ -- all we're doing here is testing if wrapping is occurring
516+ -- not the exact height, which is a little tricky to calculate perfectly without more information.
517+ (if expectedLines > 1 then
518+ context.self.bbox.height >= (20 * 2)
519+
520+ else
521+ -- then it's less than 2 ~ line heights
522+ -- there's some weird variance here which makes it hard to be exact.
523+ context.self.bbox.height < (20 * 2)
524+ )
525+ ]
526+
527+ _ ->
528+ []
529+ ]
399530 }
400531
401532 Shrink ->
@@ -407,33 +538,211 @@ widthHelper maybeMin maybeMax len =
407538 |> addMin
408539 |> addMax
409540 )
541+ , id = Testable.IsWidth
410542 , test =
411543 \context ->
412− let
413− childWidth child =
414− -- TODO: add margin values to widths
415− child.bbox.width
416−
417− totalChildren =
418− context.children
419− |> List.map childWidth
420− |> List.sum
421−
422− horizontalPadding =
423− context.self.bbox.padding.left + context.self.bbox.padding.right
424−
425− spacingValue =
426− toFloat context.parentSpacing * (toFloat (List.length context.children) - 1)
427− in
428− if totalChildren == 0 then
429− -- TODO: The issue is that we have a hard time measuring `text` elements
430− -- So if a element has a text child, then it's width isn't going to show up in the system.
431− [ expectRoundedEquality context.self.bbox.width context.self.bbox.width ]
544+ case context.selfElement of
545+ Testable.El _ _ ->
546+ let
547+ childWidth child =
548+ child.bbox.width
549+
550+ totalChildren =
551+ context.children
552+ |> List.map childWidth
553+ |> List.append (List.map .width context.self.textMetrics)
554+ |> List.sum
555+
556+ horizontalPadding =
557+ context.self.bbox.padding.left + context.self.bbox.padding.right
558+ in
559+ listIf
560+ [ ( (context.parentLayout /= Testable.InParagraph)
561+ && (context.parentLayout /= Testable.InTextCol)
562+ , Testable.rounded "equals children"
563+ { expected = totalChildren + horizontalPadding
564+ , found = context.self.bbox.width
565+ }
566+ )
567+ , ( context.parentLayout /= Testable.AtRoot
568+ , Testable.lessThanOrEqual "not larger than parent"
569+ context.self.bbox.width
570+ context.parent.bbox.width
571+ )
572+ ]
432573
433− else
434− -- This fails if this element is actually a column
435− -- So we need to capture what this element is in order to do this calculation.
436− [ expectRoundedEquality (totalChildren + horizontalPadding + spacingValue) context.self.bbox.width ]
574+ Testable.Link _ _ _ ->
575+ let
576+ childWidth child =
577+ child.bbox.width
578+
579+ totalChildren =
580+ context.children
581+ |> List.map childWidth
582+ |> List.append (List.map .width context.self.textMetrics)
583+ |> List.sum
584+
585+ horizontalPadding =
586+ context.self.bbox.padding.left + context.self.bbox.padding.right
587+ in
588+ listIf
589+ [ ( (context.parentLayout /= Testable.InParagraph)
590+ && (context.parentLayout /= Testable.InTextCol)
591+ , Testable.rounded "equals children"
592+ { expected = totalChildren + horizontalPadding
593+ , found = context.self.bbox.width
594+ }
595+ )
596+ , ( context.parentLayout /= Testable.AtRoot
597+ , Testable.lessThanOrEqual "not larger than parent"
598+ context.self.bbox.width
599+ context.parent.bbox.width
600+ )
601+ ]
602+
603+ Testable.Row rowAttrs _ ->
604+ -- width of row is the sum of all children widths
605+ -- both text elements and others.
606+ let
607+ childWidth child =
608+ child.bbox.width
609+
610+ totalChildren =
611+ context.children
612+ |> List.map childWidth
613+ |> List.append (List.map .width context.self.textMetrics)
614+ |> List.sum
615+
616+ horizontalPadding =
617+ context.self.bbox.padding.left + context.self.bbox.padding.right
618+
619+ spacingAmount =
620+ Testable.getSpacingFromAttributes rowAttrs
621+
622+ totalSpacing =
623+ toFloat spacingAmount * (toFloat (List.length context.children) - 1)
624+ in
625+ listIf
626+ [ ( True
627+ , expectRoundedEquality
628+ { expected = totalChildren + horizontalPadding + totalSpacing
629+ , found = context.self.bbox.width
630+ }
631+ )
632+ , ( context.parentLayout /= Testable.AtRoot
633+ , Testable.lessThanOrEqual "not larger than parent"
634+ context.self.bbox.width
635+ context.parent.bbox.width
636+ )
637+ ]
638+
639+ Testable.Column _ _ ->
640+ -- The width of the column is the width of the widest child.
641+ let
642+ childWidth child =
643+ child.bbox.width
644+ + context.self.bbox.padding.left
645+ + context.self.bbox.padding.right
646+
647+ textChildren =
648+ List.map
649+ (\txt ->
650+ txt.width
651+ + context.self.bbox.padding.left
652+ + context.self.bbox.padding.right
653+ )
654+ context.self.textMetrics
655+
656+ allChildren =
657+ context.children
658+ |> List.map childWidth
659+ |> List.append textChildren
660+ in
661+ listIf
662+ [ ( True
663+ , expectRoundedEquality
664+ { expected = Maybe.withDefault 0 (List.maximum allChildren)
665+ , found = context.self.bbox.width
666+ }
667+ )
668+ , ( context.parentLayout /= Testable.AtRoot
669+ , Testable.lessThanOrEqual "not larger than parent"
670+ context.self.bbox.width
671+ context.parent.bbox.width
672+ )
673+ ]
674+
675+ Testable.TextColumn _ _ ->
676+ -- The width of the column is the width of the widest child.
677+ let
678+ childWidth child =
679+ child.bbox.width
680+ + context.self.bbox.padding.left
681+ + context.self.bbox.padding.right
682+
683+ textChildren =
684+ List.map
685+ (\txt ->
686+ txt.width
687+ + context.self.bbox.padding.left
688+ + context.self.bbox.padding.right
689+ )
690+ context.self.textMetrics
691+
692+ allChildren =
693+ context.children
694+ |> List.map childWidth
695+ |> List.append textChildren
696+ in
697+ listIf
698+ [ ( True
699+ , expectRoundedEquality
700+ { expected = Maybe.withDefault 0 (List.maximum allChildren)
701+ , found = context.self.bbox.width
702+ }
703+ )
704+ , ( context.parentLayout /= Testable.AtRoot
705+ , Testable.lessThanOrEqual "not larger than parent"
706+ context.self.bbox.width
707+ context.parent.bbox.width
708+ )
709+ ]
710+
711+ Testable.Paragraph _ _ ->
712+ -- This should be the size it's text,
713+ -- unless it takes up all available space, in which case it should wrap.
714+ let
715+ childWidth child =
716+ child.bbox.width
717+
718+ totalChildren =
719+ context.children
720+ |> List.map childWidth
721+ |> List.append (List.map .width context.self.textMetrics)
722+ |> List.sum
723+
724+ horizontalPadding =
725+ context.self.bbox.padding.left + context.self.bbox.padding.right
726+ in
727+ listIf
728+ [ ( True
729+ , expectRoundedEquality
730+ { expected = totalChildren + horizontalPadding
731+ , found = context.self.bbox.width
732+ }
733+ )
734+ , ( context.parentLayout /= Testable.AtRoot
735+ , Testable.lessThanOrEqual "not larger than parent"
736+ context.self.bbox.width
737+ context.parent.bbox.width
738+ )
739+ ]
740+
741+ Testable.Text _ ->
742+ []
743+
744+ Testable.Empty ->
745+ []
437746 }
438747
439748
@@ -502,10 +811,13 @@ heightHelper maybeMin maybeMax len =
502811 |> addMin
503812 |> addMax
504813 )
814+ , id = Testable.IsHeight
505815 , test =
506816 \found ->
507− [ Testable.true ("exact height is exact: " ++ String.fromInt (floor found.self.bbox.height) ++ "," ++ String.fromInt val)
508− (floor found.self.bbox.height == val)
817+ [ expectRoundedEquality
818+ { expected = toFloat val
819+ , found = found.self.bbox.height
820+ }
509821 , Testable.true "min/max holds true"
510822 (minMaxTest (floor found.self.bbox.height))
511823 ]
@@ -520,9 +832,10 @@ heightHelper maybeMin maybeMax len =
520832 |> addMin
521833 |> addMax
522834 )
835+ , id = Testable.IsHeight
523836 , test =
524837 \context ->
525− [ if List.member context.location [ Testable.IsNearby Testable.Above, Testable.IsNearby Testable.Below ] then
838+ [ if List.member context.parentLayout [ Testable.IsNearby Testable.Above, Testable.IsNearby Testable.Below ] then
526839 Testable.true "height fill doesn't apply to above/below elements" True
527840
528841 else
@@ -530,7 +843,7 @@ heightHelper maybeMin maybeMax len =
530843 parentAvailableHeight =
531844 context.parent.bbox.height - (context.self.bbox.padding.top + context.self.bbox.padding.bottom)
532845 in
533− case context.location of
846+ case context.parentLayout of
534847 Testable.IsNearby _ ->
535848 Testable.true "Nearby Element has fill height"
536849 ((floor context.parent.bbox.height == floor context.self.bbox.height)
@@ -568,33 +881,134 @@ heightHelper maybeMin maybeMax len =
568881 |> addMin
569882 |> addMax
570883 )
884+ , id = Testable.IsHeight
571885 , test =
572886 \context ->
573− let
574− childWidth child =
575− -- TODO: add margin values to heights
576− child.bbox.height
577−
578− totalChildren =
579− context.children
580− |> List.map childWidth
581− |> List.sum
582−
583− verticalPadding =
584− context.self.bbox.padding.top + context.self.bbox.padding.bottom
585−
586− spacingValue =
587− toFloat context.parentSpacing * (toFloat (List.length context.children) - 1)
588− in
589− if totalChildren == 0 then
590− -- TODO: The issue is that we have a hard time measuring `text` elements
591− -- So if a element has a text child, then it's height isn't going to show up in the system.
592− [ expectRoundedEquality context.self.bbox.height context.self.bbox.height ]
887+ case context.selfElement of
888+ Testable.El _ _ ->
889+ let
890+ childHeight child =
891+ child.bbox.height
892+ in
893+ if List.isEmpty context.children then
894+ -- context.self.textMetrics
895+ -- |> List.map Testable.textHeight
896+ -- |> List.sum
897+ -- TODO: apparently the font metrics we have are for the literal characters rendered
898+ -- not for the font itself.
899+ [ Testable.todo "calculate height from actual text metrics"
900+ ]
593901
594− else
595− -- This fails if this element is actually a column
596− -- So we need to capture what this element is in order to do this calculation.
597− [ expectRoundedEquality (totalChildren + verticalPadding + spacingValue) context.self.bbox.height ]
902+ else
903+ [ expectRoundedEquality
904+ { expected =
905+ context.children
906+ |> List.map childHeight
907+ |> List.sum
908+ |> (\h -> h + context.self.bbox.padding.top + context.self.bbox.padding.bottom)
909+ , found = context.self.bbox.height
910+ }
911+ , Testable.lessThanOrEqual "not larger than parent"
912+ context.self.bbox.height
913+ context.parent.bbox.height
914+ ]
915+
916+ Testable.Link _ _ _ ->
917+ let
918+ childHeight child =
919+ child.bbox.height
920+ in
921+ if List.isEmpty context.children then
922+ -- context.self.textMetrics
923+ -- |> List.map Testable.textHeight
924+ -- |> List.sum
925+ -- TODO: apparently the font metrics we have are for the literal characters rendered
926+ -- not for the font itself.
927+ [ Testable.todo "calculate height from actual text metrics"
928+ ]
929+
930+ else
931+ [ expectRoundedEquality
932+ { expected =
933+ context.children
934+ |> List.map childHeight
935+ |> List.sum
936+ |> (\h -> h + context.self.bbox.padding.top + context.self.bbox.padding.bottom)
937+ , found = context.self.bbox.height
938+ }
939+ , Testable.lessThanOrEqual "not larger than parent"
940+ context.self.bbox.height
941+ context.parent.bbox.height
942+ ]
943+
944+ Testable.Row _ _ ->
945+ let
946+ childHeight child =
947+ child.bbox.height
948+ in
949+ if List.isEmpty context.children then
950+ -- context.self.textMetrics
951+ -- |> List.map Testable.textHeight
952+ -- |> List.sum
953+ -- TODO: apparently the font metrics we have are for the literal characters rendered
954+ -- not for the font itself.
955+ [ Testable.todo "calculate height from actual text metrics" ]
956+
957+ else
958+ [ expectRoundedEquality
959+ { expected =
960+ context.children
961+ |> List.map childHeight
962+ |> List.maximum
963+ |> Maybe.withDefault 0
964+ |> (\h -> h + context.self.bbox.padding.top + context.self.bbox.padding.bottom)
965+ , found = context.self.bbox.height
966+ }
967+ , Testable.lessThanOrEqual "not larger than parent"
968+ context.self.bbox.height
969+ context.parent.bbox.height
970+ ]
971+
972+ Testable.Column colAttrs _ ->
973+ let
974+ childHeight child =
975+ child.bbox.height
976+
977+ totalChildren =
978+ context.children
979+ |> List.map childHeight
980+ |> List.append (List.map Testable.textHeight context.self.textMetrics)
981+ |> List.sum
982+
983+ verticalPadding =
984+ context.self.bbox.padding.top + context.self.bbox.padding.bottom
985+
986+ spacingAmount =
987+ Testable.getSpacingFromAttributes colAttrs
988+
989+ totalSpacing =
990+ toFloat spacingAmount * (toFloat (List.length context.children) - 1)
991+ in
992+ [ expectRoundedEquality
993+ { expected = totalChildren + verticalPadding + totalSpacing
994+ , found = context.self.bbox.height
995+ }
996+ , Testable.lessThanOrEqual "not larger than parent"
997+ context.self.bbox.height
998+ context.parent.bbox.height
999+ ]
1000+
1001+ Testable.TextColumn _ _ ->
1002+ []
1003+
1004+ Testable.Paragraph _ _ ->
1005+ []
1006+
1007+ Testable.Text _ ->
1008+ []
1009+
1010+ Testable.Empty ->
1011+ []
5981012 }
5991013
6001014
@@ -615,6 +1029,7 @@ spacing space =
6151029 , Testable.LabeledTest
6161030 { label = "spacing: " ++ String.fromInt space
6171031 , attr = Element.spacing space
1032+ , id = Testable.NoId
6181033 , test =
6191034 \found ->
6201035 let
@@ -693,13 +1108,14 @@ alignLeft =
6931108 Testable.LabeledTest
6941109 { label = "alignLeft"
6951110 , attr = Element.alignLeft
1111+ , id = Testable.NoId
6961112 , test =
6971113 \found ->
698− [ if List.member found.location [ Testable.IsNearby Testable.OnLeft, Testable.IsNearby Testable.OnRight ] then
1114+ [ if List.member found.parentLayout [ Testable.IsNearby Testable.OnLeft, Testable.IsNearby Testable.OnRight ] then
6991115 Testable.true "alignLeft doesn't apply to elements that are onLeft or onRight" True
7001116
7011117 else if
702− List.member found.location
1118+ List.member found.parentLayout
7031119 [ Testable.IsNearby Testable.InFront
7041120 , Testable.IsNearby Testable.Behind
7051121 , Testable.IsNearby Testable.Above
@@ -707,16 +1123,18 @@ alignLeft =
7071123 ]
7081124 then
7091125 expectRoundedEquality
710− found.self.bbox.left
711− found.parent.bbox.left
1126+ { found = found.self.bbox.left
1127+ , expected = found.parent.bbox.left
1128+ }
7121129
7131130 else if List.length found.siblings == 0 then
7141131 expectRoundedEquality
715− found.self.bbox.left
716− (found.parent.bbox.left + found.parent.bbox.padding.left)
1132+ { found = found.self.bbox.left
1133+ , expected = found.parent.bbox.left + found.parent.bbox.padding.left
1134+ }
7171135
7181136 else
719− case found.location of
1137+ case found.parentLayout of
7201138 Testable.InRow ->
7211139 let
7221140 siblingsOnLeft =
@@ -731,13 +1149,15 @@ alignLeft =
7311149 |> List.sum
7321150 in
7331151 expectRoundedEquality
734− found.self.bbox.left
735− (found.parent.bbox.left + (found.parent.bbox.padding.left + widthsOnLeft + spacings))
1152+ { found = found.self.bbox.left
1153+ , expected = found.parent.bbox.left + (found.parent.bbox.padding.left + widthsOnLeft + spacings)
1154+ }
7361155
7371156 _ ->
7381157 expectRoundedEquality
739− found.self.bbox.left
740− (found.parent.bbox.left + found.parent.bbox.padding.left)
1158+ { found = found.self.bbox.left
1159+ , expected = found.parent.bbox.left + found.parent.bbox.padding.left
1160+ }
7411161 ]
7421162 }
7431163
@@ -748,6 +1168,7 @@ centerX =
7481168 Testable.LabeledTest
7491169 { label = "centerX"
7501170 , attr = Element.centerX
1171+ , id = Testable.NoId
7511172 , test =
7521173 \found ->
7531174 let
@@ -759,17 +1180,18 @@ centerX =
7591180 parentCenter =
7601181 found.parent.bbox.left + (found.parent.bbox.width / 2)
7611182 in
762− if List.member found.location [ Testable.IsNearby Testable.OnRight, Testable.IsNearby Testable.OnLeft ] then
1183+ if List.member found.parentLayout [ Testable.IsNearby Testable.OnRight, Testable.IsNearby Testable.OnLeft ] then
7631184 [ Testable.true "centerX doesn't apply to elements that are onLeft or onRight" True ]
7641185
7651186 else if List.length found.siblings == 0 then
7661187 [ expectRoundedEquality
767− selfCenter
768− parentCenter
1188+ { found = selfCenter
1189+ , expected = parentCenter
1190+ }
7691191 ]
7701192
7711193 else
772− case found.location of
1194+ case found.parentLayout of
7731195 Testable.InRow ->
7741196 let
7751197 siblingsOnLeft =
@@ -800,12 +1222,17 @@ centerX =
8001222 )
8011223 in
8021224 [ expectRoundedEquality
803− selfCenter
804− expectedCenter
1225+ { found = selfCenter
1226+ , expected = expectedCenter
1227+ }
8051228 ]
8061229
8071230 _ ->
808− [ expectRoundedEquality selfCenter parentCenter ]
1231+ [ expectRoundedEquality
1232+ { found = selfCenter
1233+ , expected = parentCenter
1234+ }
1235+ ]
8091236 }
8101237
8111238
@@ -815,13 +1242,14 @@ alignRight =
8151242 Testable.LabeledTest
8161243 { label = "alignRight"
8171244 , attr = Element.alignRight
1245+ , id = Testable.NoId
8181246 , test =
8191247 \found ->
820− if List.member found.location [ Testable.IsNearby Testable.OnLeft, Testable.IsNearby Testable.OnRight ] then
1248+ if List.member found.parentLayout [ Testable.IsNearby Testable.OnLeft, Testable.IsNearby Testable.OnRight ] then
8211249 [ Testable.true "alignRight doesn't apply to elements that are onLeft or onRight" True ]
8221250
8231251 else if
824− List.member found.location
1252+ List.member found.parentLayout
8251253 [ Testable.IsNearby Testable.InFront
8261254 , Testable.IsNearby Testable.Behind
8271255 , Testable.IsNearby Testable.Above
@@ -829,18 +1257,20 @@ alignRight =
8291257 ]
8301258 then
8311259 [ expectRoundedEquality
832− found.self.bbox.right
833− found.parent.bbox.right
1260+ { found = found.self.bbox.right
1261+ , expected = found.parent.bbox.right
1262+ }
8341263 ]
8351264
8361265 else if List.length found.siblings == 0 then
8371266 [ expectRoundedEquality
838− found.self.bbox.right
839− (found.parent.bbox.right + found.parent.bbox.padding.right)
1267+ { found = found.self.bbox.right
1268+ , expected = found.parent.bbox.right + found.parent.bbox.padding.right
1269+ }
8401270 ]
8411271
8421272 else
843− case found.location of
1273+ case found.parentLayout of
8441274 Testable.InRow ->
8451275 let
8461276 siblingsOnRight =
@@ -855,14 +1285,16 @@ alignRight =
8551285 |> List.sum
8561286 in
8571287 [ expectRoundedEquality
858− found.self.bbox.right
859− (found.parent.bbox.right - (found.parent.bbox.padding.right + widthsOnRight + spacings))
1288+ { found = found.self.bbox.right
1289+ , expected = found.parent.bbox.right - (found.parent.bbox.padding.right + widthsOnRight + spacings)
1290+ }
8601291 ]
8611292
8621293 _ ->
8631294 [ expectRoundedEquality
864− found.self.bbox.right
865− (found.parent.bbox.right + found.parent.bbox.padding.right)
1295+ { found = found.self.bbox.right
1296+ , expected = found.parent.bbox.right + found.parent.bbox.padding.right
1297+ }
8661298 ]
8671299 }
8681300
@@ -873,13 +1305,14 @@ alignTop =
8731305 Testable.LabeledTest
8741306 { label = "alignTop"
8751307 , attr = Element.alignTop
1308+ , id = Testable.NoId
8761309 , test =
8771310 \found ->
878− if List.member found.location [ Testable.IsNearby Testable.Above, Testable.IsNearby Testable.Below ] then
1311+ if List.member found.parentLayout [ Testable.IsNearby Testable.Above, Testable.IsNearby Testable.Below ] then
8791312 [ Testable.true "alignTop doesn't apply to elements that are above or below" True ]
8801313
8811314 else if
882− List.member found.location
1315+ List.member found.parentLayout
8831316 [ Testable.IsNearby Testable.InFront
8841317 , Testable.IsNearby Testable.Behind
8851318 , Testable.IsNearby Testable.OnRight
@@ -887,18 +1320,20 @@ alignTop =
8871320 ]
8881321 then
8891322 [ expectRoundedEquality
890− found.self.bbox.top
891− found.parent.bbox.top
1323+ { found = found.self.bbox.top
1324+ , expected = found.parent.bbox.top
1325+ }
8921326 ]
8931327
8941328 else if List.length found.siblings == 0 then
8951329 [ expectRoundedEquality
896− found.self.bbox.top
897− (found.parent.bbox.top + found.parent.bbox.padding.top)
1330+ { found = found.self.bbox.top
1331+ , expected = found.parent.bbox.top + found.parent.bbox.padding.top
1332+ }
8981333 ]
8991334
9001335 else
901− case found.location of
1336+ case found.parentLayout of
9021337 Testable.InColumn ->
9031338 let
9041339 siblingsAbove =
@@ -913,14 +1348,16 @@ alignTop =
9131348 |> List.sum
9141349 in
9151350 [ expectRoundedEquality
916− found.self.bbox.top
917− (found.parent.bbox.top + (found.parent.bbox.padding.top + heightsAbove + spacings))
1351+ { found = found.self.bbox.top
1352+ , expected = found.parent.bbox.top + (found.parent.bbox.padding.top + heightsAbove + spacings)
1353+ }
9181354 ]
9191355
9201356 _ ->
9211357 [ expectRoundedEquality
922− found.self.bbox.top
923− found.parent.bbox.top
1358+ { found = found.self.bbox.top
1359+ , expected = found.parent.bbox.top
1360+ }
9241361 ]
9251362 }
9261363
@@ -931,13 +1368,14 @@ alignBottom =
9311368 Testable.LabeledTest
9321369 { label = "alignBottom"
9331370 , attr = Element.alignBottom
1371+ , id = Testable.NoId
9341372 , test =
9351373 \found ->
936− if List.member found.location [ Testable.IsNearby Testable.Above, Testable.IsNearby Testable.Below ] then
1374+ if List.member found.parentLayout [ Testable.IsNearby Testable.Above, Testable.IsNearby Testable.Below ] then
9371375 [ Testable.true "alignBottom doesn't apply to elements that are above or below" True ]
9381376
9391377 else if
940− List.member found.location
1378+ List.member found.parentLayout
9411379 [ Testable.IsNearby Testable.InFront
9421380 , Testable.IsNearby Testable.Behind
9431381 , Testable.IsNearby Testable.OnRight
@@ -945,18 +1383,20 @@ alignBottom =
9451383 ]
9461384 then
9471385 [ expectRoundedEquality
948− found.self.bbox.bottom
949− found.parent.bbox.bottom
1386+ { found = found.self.bbox.bottom
1387+ , expected = found.parent.bbox.bottom
1388+ }
9501389 ]
9511390
9521391 else if List.length found.siblings == 0 then
9531392 [ expectRoundedEquality
954− found.self.bbox.bottom
955− (found.parent.bbox.bottom + found.parent.bbox.padding.bottom)
1393+ { found = found.self.bbox.bottom
1394+ , expected = found.parent.bbox.bottom + found.parent.bbox.padding.bottom
1395+ }
9561396 ]
9571397
9581398 else
959− case found.location of
1399+ case found.parentLayout of
9601400 Testable.InColumn ->
9611401 let
9621402 siblingsBelow =
@@ -971,22 +1411,25 @@ alignBottom =
9711411 |> List.sum
9721412 in
9731413 [ expectRoundedEquality
974− found.self.bbox.bottom
975− (found.parent.bbox.bottom - (found.parent.bbox.padding.bottom + heightsBelow + spacings))
1414+ { found = found.self.bbox.bottom
1415+ , expected = found.parent.bbox.bottom - (found.parent.bbox.padding.bottom + heightsBelow + spacings)
1416+ }
9761417 ]
9771418
9781419 _ ->
9791420 [ expectRoundedEquality
980− found.self.bbox.bottom
981− (found.parent.bbox.bottom + found.parent.bbox.padding.bottom)
1421+ { found = found.self.bbox.bottom
1422+ , expected = found.parent.bbox.bottom + found.parent.bbox.padding.bottom
1423+ }
9821424 ]
9831425 }
9841426
9851427
986−expectRoundedEquality x y =
1428+expectRoundedEquality : { expected : Float, found : Float } -> Testable.LayoutExpectation
1429+expectRoundedEquality { expected, found } =
9871430 Testable.true
988− ("within 1 of each other " ++ floatToString x ++ ", " ++ floatToString y)
989− (abs (x - y) < 1)
1431+ ("expected " ++ floatToString expected ++ ", found " ++ floatToString found)
1432+ (abs (expected - found) < 1)
9901433
9911434
9921435floatToString : Float -> String
@@ -1000,6 +1443,7 @@ centerY =
10001443 Testable.LabeledTest
10011444 { label = "centerY"
10021445 , attr = Element.centerY
1446+ , id = Testable.NoId
10031447 , test =
10041448 \found ->
10051449 let
@@ -1009,17 +1453,18 @@ centerY =
10091453 parentCenter =
10101454 found.parent.bbox.top + (found.parent.bbox.height / 2)
10111455 in
1012− if List.member found.location [ Testable.IsNearby Testable.Above, Testable.IsNearby Testable.Below ] then
1456+ if List.member found.parentLayout [ Testable.IsNearby Testable.Above, Testable.IsNearby Testable.Below ] then
10131457 [ Testable.true "centerY doesn't apply to elements that are above or below" True ]
10141458
10151459 else if List.length found.siblings == 0 then
10161460 [ expectRoundedEquality
1017− selfCenter
1018− parentCenter
1461+ { found = selfCenter
1462+ , expected = parentCenter
1463+ }
10191464 ]
10201465
10211466 else
1022− case found.location of
1467+ case found.parentLayout of
10231468 Testable.InColumn ->
10241469 let
10251470 siblingsOnTop =
@@ -1050,12 +1495,17 @@ centerY =
10501495 )
10511496 in
10521497 [ expectRoundedEquality
1053− selfCenter
1054− expectedCenter
1498+ { found = selfCenter
1499+ , expected = expectedCenter
1500+ }
10551501 ]
10561502
10571503 _ ->
1058− [ expectRoundedEquality selfCenter parentCenter ]
1504+ [ expectRoundedEquality
1505+ { found = selfCenter
1506+ , expected = parentCenter
1507+ }
1508+ ]
10591509 }
10601510
10611511
@@ -1068,7 +1518,11 @@ above element =
10681518 , label = "above"
10691519 , test =
10701520 \found ->
1071− [ expectRoundedEquality found.self.bbox.bottom found.parent.bbox.top ]
1521+ [ expectRoundedEquality
1522+ { found = found.self.bbox.bottom
1523+ , expected = found.parent.bbox.top
1524+ }
1525+ ]
10721526 }
10731527
10741528
@@ -1081,7 +1535,11 @@ below element =
10811535 , label = "below"
10821536 , test =
10831537 \found ->
1084− [ expectRoundedEquality found.self.bbox.top found.parent.bbox.bottom ]
1538+ [ expectRoundedEquality
1539+ { found = found.self.bbox.top
1540+ , expected = found.parent.bbox.bottom
1541+ }
1542+ ]
10851543 }
10861544
10871545
@@ -1094,7 +1552,11 @@ onRight element =
10941552 , label = "onRight"
10951553 , test =
10961554 \found ->
1097− [ expectRoundedEquality found.self.bbox.left found.parent.bbox.right ]
1555+ [ expectRoundedEquality
1556+ { found = found.self.bbox.left
1557+ , expected = found.parent.bbox.right
1558+ }
1559+ ]
10981560 }
10991561
11001562
@@ -1107,7 +1569,11 @@ onLeft element =
11071569 , label = "onLeft"
11081570 , test =
11091571 \found ->
1110− [ expectRoundedEquality found.self.bbox.right found.parent.bbox.left ]
1572+ [ expectRoundedEquality
1573+ { found = found.self.bbox.right
1574+ , expected = found.parent.bbox.left
1575+ }
1576+ ]
11111577 }
11121578
11131579
@@ -1173,3 +1639,85 @@ behindContent element =
11731639 \found ->
11741640 [ withinHelper found ]
11751641 }
1642+
1643+
1644+
1645+{- Implicit width/height calcualtions -}
1646+
1647+
1648+implicitWidthHeightShrink attrs =
1649+ let
1650+ withImplicits =
1651+ implicitTest (widthHelper Nothing Nothing Shrink)
1652+ :: implicitTest (heightHelper Nothing Nothing Shrink)
1653+ :: attrs
1654+ in
1655+ skipOverridden withImplicits
1656+
1657+
1658+attrId attr =
1659+ case attr of
1660+ Testable.LabeledTest details ->
1661+ details.id
1662+
1663+ Testable.AttrTest details ->
1664+ details.id
1665+
1666+ _ ->
1667+ Testable.NoId
1668+
1669+
1670+skipOverridden ls =
1671+ List.foldr
1672+ (\attr ( found, caught ) ->
1673+ let
1674+ ( skip, has ) =
1675+ case attrId attr of
1676+ Testable.NoId ->
1677+ ( False, found )
1678+
1679+ Testable.IsWidth ->
1680+ ( found.hasWidth
1681+ , { hasWidth = True
1682+ , hasHeight = found.hasHeight
1683+ }
1684+ )
1685+
1686+ Testable.IsHeight ->
1687+ ( found.hasHeight
1688+ , { hasWidth = found.hasWidth
1689+ , hasHeight = True
1690+ }
1691+ )
1692+ in
1693+ ( has
1694+ , if skip then
1695+ caught
1696+
1697+ else
1698+ attr :: caught
1699+ )
1700+ )
1701+ ( { hasWidth = False
1702+ , hasHeight = False
1703+ }
1704+ , []
1705+ )
1706+ ls
1707+ |> Tuple.second
1708+ |> List.reverse
1709+
1710+
1711+{-| This is taking a normal test and rmoving its ability to attach a real `Element` attribute.
1712+-}
1713+implicitTest attr =
1714+ case attr of
1715+ Testable.LabeledTest details ->
1716+ Testable.AttrTest
1717+ { test = details.test
1718+ , label = "Implicit -> " ++ details.label
1719+ , id = details.id
1720+ }
1721+
1722+ otherwise ->
1723+ otherwise