@@ -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 )
@@ -63,11 +69,16 @@ import Testable
6369import Testable.Runner
6470
6571
66−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
6780layout attrs elem =
68− Testable.Runner.program
69− [ ( "Tests Run", elem )
70− ]
81+ Testable.Runner.testable "Test" elem
7182
7283
7384text : String -> Testable.Element msg
@@ -97,12 +108,59 @@ none =
97108
98109paragraph : List (Testable.Attr msg) -> List (Testable.Element msg) -> Testable.Element msg
99110paragraph attrs =
100− Testable.Paragraph (implicitWidthHeightShrink 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)
101118
102119
103120textColumn : List (Testable.Attr msg) -> List (Testable.Element msg) -> Testable.Element msg
104121textColumn attrs =
105− Testable.TextColumn (implicitWidthHeightShrink 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
106164
107165
108166{-| Old labeling mechanism that i removed to hastily
@@ -276,6 +334,11 @@ paddingXY x y =
276334 }
277335
278336
337+listIf ls =
338+ List.filter Tuple.first ls
339+ |> List.map Tuple.second
340+
341+
279342widthHelper maybeMin maybeMax len =
280343 let
281344 addMin l =
@@ -344,7 +407,10 @@ widthHelper maybeMin maybeMax len =
344407 )
345408 , test =
346409 \found ->
347− [ 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+ }
348414 , Testable.true "min/max is upheld" (minMaxTest (floor found.self.bbox.width))
349415 ]
350416 }
@@ -374,33 +440,93 @@ widthHelper maybeMin maybeMax len =
374440 parentAvailableWidth =
375441 context.parent.bbox.width - (context.self.bbox.padding.left + context.self.bbox.padding.right)
376442 in
377− [ case context.parentLayout of
378− Testable.IsNearby _ ->
379− Testable.true "Nearby Element has fill width"
380− ((floor context.parent.bbox.width == floor context.self.bbox.width)
381− || minMaxTest (floor context.self.bbox.width)
382− )
383−
384− Testable.InColumn ->
385− Testable.true "Element within column has fill width"
386− ((floor parentAvailableWidth == floor context.self.bbox.width)
387− || minMaxTest (floor context.self.bbox.width)
388− )
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+ ]
389451
390− Testable.InEl ->
391− Testable.true "Element within element has fill width" <|
392− (floor parentAvailableWidth == floor context.self.bbox.width)
393− || minMaxTest (floor context.self.bbox.width)
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+ ]
394526
395− _ ->
396− let
397− spacePerPortion =
398− parentAvailableWidth / toFloat (List.length context.siblings + 1)
399− in
400− Testable.true "element has fill width" <|
401− (floor spacePerPortion == floor context.self.bbox.width)
402− || minMaxTest (floor context.self.bbox.width)
403− ]
527+ _ ->
528+ []
529+ ]
404530 }
405531
406532 Shrink ->
@@ -430,11 +556,49 @@ widthHelper maybeMin maybeMax len =
430556 horizontalPadding =
431557 context.self.bbox.padding.left + context.self.bbox.padding.right
432558 in
433− [ expectRoundedEquality
434− { expected = totalChildren + horizontalPadding
435− , found = context.self.bbox.width
436− }
437− ]
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+ ]
573+
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+ ]
438602
439603 Testable.Row rowAttrs _ ->
440604 -- width of row is the sum of all children widths
@@ -458,11 +622,19 @@ widthHelper maybeMin maybeMax len =
458622 totalSpacing =
459623 toFloat spacingAmount * (toFloat (List.length context.children) - 1)
460624 in
461− [ expectRoundedEquality
462− { expected = totalChildren + horizontalPadding + totalSpacing
463− , found = context.self.bbox.width
464− }
465− ]
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+ ]
466638
467639 Testable.Column _ _ ->
468640 -- The width of the column is the width of the widest child.
@@ -486,14 +658,55 @@ widthHelper maybeMin maybeMax len =
486658 |> List.map childWidth
487659 |> List.append textChildren
488660 in
489− [ expectRoundedEquality
490− { expected = Maybe.withDefault 0 (List.maximum allChildren)
491− , found = context.self.bbox.width
492− }
493− ]
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+ ]
494674
495675 Testable.TextColumn _ _ ->
496− []
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+ ]
497710
498711 Testable.Paragraph _ _ ->
499712 -- This should be the size it's text,
@@ -511,11 +724,19 @@ widthHelper maybeMin maybeMax len =
511724 horizontalPadding =
512725 context.self.bbox.padding.left + context.self.bbox.padding.right
513726 in
514− [ expectRoundedEquality
515− { expected = totalChildren + horizontalPadding
516− , found = context.self.bbox.width
517− }
518− ]
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+ ]
519740
520741 Testable.Text _ ->
521742 []
@@ -593,8 +814,10 @@ heightHelper maybeMin maybeMax len =
593814 , id = Testable.IsHeight
594815 , test =
595816 \found ->
596− [ Testable.true ("exact height is exact: " ++ String.fromInt (floor found.self.bbox.height) ++ "," ++ String.fromInt val)
597− (floor found.self.bbox.height == val)
817+ [ expectRoundedEquality
818+ { expected = toFloat val
819+ , found = found.self.bbox.height
820+ }
598821 , Testable.true "min/max holds true"
599822 (minMaxTest (floor found.self.bbox.height))
600823 ]
@@ -665,47 +888,86 @@ heightHelper maybeMin maybeMax len =
665888 Testable.El _ _ ->
666889 let
667890 childHeight child =
668− -- TODO: add margin values to heights
669891 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+ ]
670901
671− totalChildren =
672− context.children
673− |> List.map childHeight
674− |> List.append (List.map Testable.textHeight context.self.textMetrics)
675− |> List.sum
676−
677− verticalPadding =
678− context.self.bbox.padding.top + context.self.bbox.padding.bottom
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+ ]
679915
680− spacingValue =
681− toFloat context.parentSpacing * (toFloat (List.length context.children) - 1)
916+ Testable.Link _ _ _ ->
917+ let
918+ childHeight child =
919+ child.bbox.height
682920 in
683− [ expectRoundedEquality
684− { expected = totalChildren + verticalPadding + spacingValue
685− , found = context.self.bbox.height
686− }
687− ]
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+ ]
688943
689944 Testable.Row _ _ ->
690945 let
691946 childHeight child =
692947 child.bbox.height
693−
694− totalChildren =
695− context.children
696− |> List.map childHeight
697− |> List.append (List.map Testable.textHeight context.self.textMetrics)
698− |> List.maximum
699− |> Maybe.withDefault 0
700−
701− verticalPadding =
702− context.self.bbox.padding.top + context.self.bbox.padding.bottom
703948 in
704− [ expectRoundedEquality
705− { expected = totalChildren + verticalPadding
706− , found = context.self.bbox.height
707− }
708− ]
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+ ]
709971
710972 Testable.Column colAttrs _ ->
711973 let
@@ -731,6 +993,9 @@ heightHelper maybeMin maybeMax len =
731993 { expected = totalChildren + verticalPadding + totalSpacing
732994 , found = context.self.bbox.height
733995 }
996+ , Testable.lessThanOrEqual "not larger than parent"
997+ context.self.bbox.height
998+ context.parent.bbox.height
734999 ]
7351000
7361001 Testable.TextColumn _ _ ->