@@ -10,6 +10,7 @@ module Testable.Element exposing
1010 , below
1111 , centerX
1212 , centerY
13+ , clip
1314 , column
1415 , el
1516 , expectRoundedEquality
@@ -19,8 +20,14 @@ module Testable.Element exposing
1920 , inFront
2021 , isVisible
2122 , label
23+ , layout
24+ , link
2225 , maximum
2326 , minimum
27+ , moveDown
28+ , moveLeft
29+ , moveRight
30+ , moveUp
2431 , none
2532 , onLeft
2633 , onRight
@@ -28,11 +35,17 @@ module Testable.Element exposing
2835 , paddingXY
2936 , paragraph
3037 , px
38+ , rgb
39+ , rgba
3140 , row
41+ , scrollbarX
42+ , scrollbarY
43+ , scrollbars
3244 , shrink
3345 , spacing
3446 , text
3547 , textColumn
48+ , toProgram
3649 , transparent
3750 , width
3851 )
@@ -51,9 +64,21 @@ In order to run the test:
5164
5265import Dict
5366import Element
54−import Expect
5567import Html.Attributes
5668import Testable
69+import Testable.Runner
70+
71+
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
80+layout attrs elem =
81+ Testable.Runner.testable "Test" elem
5782
5883
5984text : String -> Testable.Element msg
@@ -62,18 +87,18 @@ text =
6287
6388
6489el : List (Testable.Attr msg) -> Testable.Element msg -> Testable.Element msg
65−el =
66− Testable.El
90+el attrs =
91+ Testable.El (implicitWidthHeightShrink attrs)
6792
6893
6994row : List (Testable.Attr msg) -> List (Testable.Element msg) -> Testable.Element msg
70−row =
71− Testable.Row
95+row attrs =
96+ Testable.Row (implicitWidthHeightShrink attrs)
7297
7398
7499column : List (Testable.Attr msg) -> List (Testable.Element msg) -> Testable.Element msg
75−column =
76− Testable.Column
100+column attrs =
101+ Testable.Column (implicitWidthHeightShrink attrs)
77102
78103
79104none : Testable.Element msg
@@ -82,13 +107,82 @@ none =
82107
83108
84109paragraph : List (Testable.Attr msg) -> List (Testable.Element msg) -> Testable.Element msg
85−paragraph =
86− 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)
87118
88119
89120textColumn : List (Testable.Attr msg) -> List (Testable.Element msg) -> Testable.Element msg
90−textColumn =
91− 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
164+
165+
166+{-| Old labeling mechanism that i removed to hastily
167+-}
168+label str =
169+ Testable.Batch []
170+
171+
172+moveUp x =
173+ Testable.Attr (Element.moveUp x)
174+
175+
176+moveDown x =
177+ Testable.Attr (Element.moveDown x)
178+
179+
180+moveRight x =
181+ Testable.Attr (Element.moveRight x)
182+
183+
184+moveLeft x =
185+ Testable.Attr (Element.moveLeft x)
92186
93187
94188type Length
@@ -107,6 +201,14 @@ maximum =
107201 Maximum
108202
109203
204+rgb =
205+ Element.rgb
206+
207+
208+rgba =
209+ Element.rgba
210+
211+
110212px : Int -> Length
111213px =
112214 Px
@@ -127,11 +229,6 @@ fillPortion =
127229 Fill
128230
129231
130−label : String -> Testable.Attr msg
131−label =
132− Testable.Label
133−
134−
135232transparent : Bool -> Testable.Attr msg
136233transparent on =
137234 Testable.LabeledTest
@@ -142,8 +239,9 @@ transparent on =
142239 else
143240 "opaque"
144241 , attr = Element.transparent on
242+ , id = Testable.NoId
145243 , test =
146− \context _ ->
244+ \context ->
147245 let
148246 selfTransparency =
149247 context.self.style
@@ -157,19 +255,19 @@ transparent on =
157255 else
158256 "1"
159257 in
160− Expect.equal value selfTransparency
258+ [ Testable.equal value selfTransparency ]
161259 }
162260
163261
164262{-| -}
165263isVisible : Testable.Attr msg
166264isVisible =
167− Testable.LabeledTest
265+ Testable.AttrTest
168266 { label = "is-visible"
169− , attr = Element.htmlAttribute (Html.Attributes.style "not" "applicable")
267+ , id = Testable.NoId
170268 , test =
171− \context _ ->
172− Expect.equal context.self.isVisible True
269+ \context ->
270+ [ Testable.equal context.self.isVisible True ]
173271 }
174272
175273
@@ -179,15 +277,16 @@ alpha a =
179277 Testable.LabeledTest
180278 { label = "alpha-" ++ String.fromFloat a
181279 , attr = Element.alpha a
280+ , id = Testable.NoId
182281 , test =
183− \context _ ->
282+ \context ->
184283 let
185284 selfTransparency =
186285 context.self.style
187286 |> Dict.get "opacity"
188287 |> Maybe.withDefault "notfound"
189288 in
190− Expect.equal (String.fromFloat a) selfTransparency
289+ [ Testable.equal (String.fromFloat a) selfTransparency ]
191290 }
192291
193292
@@ -197,9 +296,10 @@ padding pad =
197296 Testable.LabeledTest
198297 { label = "padding " ++ String.fromInt pad
199298 , attr = Element.padding pad
299+ , id = Testable.NoId
200300 , test =
201− \found _ ->
202− Expect.true ("Padding " ++ String.fromInt pad ++ " is present")
301+ \found ->
302+ [ Testable.true ("Padding " ++ String.fromInt pad ++ " is present")
203303 (List.all ((==) pad)
204304 [ floor found.self.bbox.padding.left
205305 , floor found.self.bbox.padding.right
@@ -207,6 +307,7 @@ padding pad =
207307 , floor found.self.bbox.padding.bottom
208308 ]
209309 )
310+ ]
210311 }
211312
212313
@@ -216,9 +317,10 @@ paddingXY x y =
216317 Testable.LabeledTest
217318 { label = "paddingXY " ++ String.fromInt x ++ ", " ++ String.fromInt y
218319 , attr = Element.paddingXY x y
320+ , id = Testable.NoId
219321 , test =
220− \found _ ->
221− Expect.true ("PaddingXY (" ++ String.fromInt x ++ ", " ++ String.fromInt y ++ ") is present")
322+ \found ->
323+ [ Testable.true ("PaddingXY (" ++ String.fromInt x ++ ", " ++ String.fromInt y ++ ") is present")
222324 (List.all ((==) x)
223325 [ floor found.self.bbox.padding.left
224326 , floor found.self.bbox.padding.right
@@ -228,9 +330,15 @@ paddingXY x y =
228330 , floor found.self.bbox.padding.bottom
229331 ]
230332 )
333+ ]
231334 }
232335
233336
337+listIf ls =
338+ List.filter Tuple.first ls
339+ |> List.map Tuple.second
340+
341+
234342widthHelper maybeMin maybeMax len =
235343 let
236344 addMin l =
@@ -290,6 +398,7 @@ widthHelper maybeMin maybeMax len =
290398 -- Pixel values should ignore min and max?
291399 Testable.LabeledTest
292400 { label = "width " ++ String.fromInt val ++ "px" ++ minLabel ++ maxLabel
401+ , id = Testable.IsWidth
293402 , attr =
294403 Element.width
295404 (Element.px val
@@ -297,18 +406,24 @@ widthHelper maybeMin maybeMax len =
297406 |> addMax
298407 )
299408 , 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− ()
409+ \found ->
410+ [ expectRoundedEquality
411+ { expected = toFloat val
412+ , found = found.self.bbox.width
413+ }
414+ , Testable.true "min/max is upheld" (minMaxTest (floor found.self.bbox.width))
415+ ]
307416 }
308417
309418 Fill portion ->
310419 Testable.LabeledTest
311− { label = "width fill-" ++ String.fromInt portion ++ minLabel ++ maxLabel
420+ { label =
421+ if portion == 1 then
422+ "width fill" ++ minLabel ++ maxLabel
423+
424+ else
425+ "width fill-" ++ String.fromInt portion ++ minLabel ++ maxLabel
426+ , id = Testable.IsWidth
312427 , attr =
313428 Element.width
314429 (Element.fillPortion portion
@@ -316,41 +431,102 @@ widthHelper maybeMin maybeMax len =
316431 |> addMax
317432 )
318433 , 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
434+ \context ->
435+ if List.member context.parentLayout [ Testable.IsNearby Testable.OnRight, Testable.IsNearby Testable.OnLeft ] then
436+ [ Testable.true "width fill doesn't apply to onright/onleft elements" True ]
322437
323438 else
324439 let
325440 parentAvailableWidth =
326441 context.parent.bbox.width - (context.self.bbox.padding.left + context.self.bbox.padding.right)
327442 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− )
334−
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− )
340−
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)
345−
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)
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+ ]
354530 }
355531
356532 Shrink ->
@@ -362,33 +538,211 @@ widthHelper maybeMin maybeMax len =
362538 |> addMin
363539 |> addMax
364540 )
541+ , id = Testable.IsWidth
365542 , test =
366− \context _ ->
367− let
368− childWidth child =
369− -- TODO: add margin values to widths
370− child.bbox.width
371−
372− totalChildren =
373− context.children
374− |> List.map childWidth
375− |> List.sum
376−
377− horizontalPadding =
378− context.self.bbox.padding.left + context.self.bbox.padding.right
379−
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
543+ \context ->
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+ ]
387573
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
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+ []
392746 }
393747
394748
@@ -457,17 +811,16 @@ heightHelper maybeMin maybeMax len =
457811 |> addMin
458812 |> addMax
459813 )
814+ , id = Testable.IsHeight
460815 , 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− ()
816+ \found ->
817+ [ expectRoundedEquality
818+ { expected = toFloat val
819+ , found = found.self.bbox.height
820+ }
821+ , Testable.true "min/max holds true"
822+ (minMaxTest (floor found.self.bbox.height))
823+ ]
471824 }
472825
473826 Fill portion ->
@@ -479,31 +832,32 @@ heightHelper maybeMin maybeMax len =
479832 |> addMin
480833 |> addMax
481834 )
835+ , id = Testable.IsHeight
482836 , 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
837+ \context ->
838+ [ if List.member context.parentLayout [ Testable.IsNearby Testable.Above, Testable.IsNearby Testable.Below ] then
839+ Testable.true "height fill doesn't apply to above/below elements" True
486840
487− else
841+ else
488842 let
489843 parentAvailableHeight =
490844 context.parent.bbox.height - (context.self.bbox.padding.top + context.self.bbox.padding.bottom)
491845 in
492− case context.location of
846+ case context.parentLayout of
493847 Testable.IsNearby _ ->
494− Expect.true "Nearby Element has fill height"
848+ Testable.true "Nearby Element has fill height"
495849 ((floor context.parent.bbox.height == floor context.self.bbox.height)
496850 || minMaxTest (floor context.self.bbox.height)
497851 )
498852
499853 Testable.InColumn ->
500− Expect.true "Element within column has fill height"
854+ Testable.true "Element within column has fill height"
501855 ((floor parentAvailableHeight == floor context.self.bbox.height)
502856 || minMaxTest (floor context.self.bbox.height)
503857 )
504858
505859 Testable.InEl ->
506− Expect.true "Element within el has fill height" <|
860+ Testable.true "Element within el has fill height" <|
507861 (floor parentAvailableHeight == floor context.self.bbox.height)
508862 || minMaxTest (floor context.self.bbox.height)
509863
@@ -512,9 +866,10 @@ heightHelper maybeMin maybeMax len =
512866 spacePerPortion =
513867 parentAvailableHeight / toFloat (List.length context.siblings + 1)
514868 in
515− Expect.true "el has fill height" <|
869+ Testable.true "el has fill height" <|
516870 (floor spacePerPortion == floor context.self.bbox.height)
517871 || minMaxTest (floor context.self.bbox.height)
872+ ]
518873 }
519874
520875 Shrink ->
@@ -526,33 +881,134 @@ heightHelper maybeMin maybeMax len =
526881 |> addMin
527882 |> addMax
528883 )
884+ , id = Testable.IsHeight
529885 , test =
530− \context _ ->
531− let
532− childWidth child =
533− -- TODO: add margin values to heights
534− child.bbox.height
535−
536− totalChildren =
537− context.children
538− |> List.map childWidth
539− |> List.sum
540−
541− verticalPadding =
542− context.self.bbox.padding.top + context.self.bbox.padding.bottom
543−
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
886+ \context ->
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+ ]
551901
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
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+ []
5561012 }
5571013
5581014
@@ -573,8 +1029,9 @@ spacing space =
5731029 , Testable.LabeledTest
5741030 { label = "spacing: " ++ String.fromInt space
5751031 , attr = Element.spacing space
1032+ , id = Testable.NoId
5761033 , test =
577− \found _ ->
1034+ \found ->
5781035 let
5791036 findDistance child total =
5801037 List.concatMap
@@ -620,7 +1077,7 @@ spacing space =
6201077 []
6211078 distances
6221079 in
623− Expect.true
1080+ [ Testable.true
6241081 ("All children are at least "
6251082 ++ String.fromInt space
6261083 ++ " pixels apart."
@@ -628,6 +1085,7 @@ spacing space =
6281085 ++ " are not though"
6291086 )
6301087 (allAreSpaced == [])
1088+ ]
6311089 }
6321090 ]
6331091
@@ -650,30 +1108,33 @@ alignLeft =
6501108 Testable.LabeledTest
6511109 { label = "alignLeft"
6521110 , attr = Element.alignLeft
1111+ , id = Testable.NoId
6531112 , 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
1113+ \found ->
1114+ [ if List.member found.parentLayout [ Testable.IsNearby Testable.OnLeft, Testable.IsNearby Testable.OnRight ] then
1115+ Testable.true "alignLeft doesn't apply to elements that are onLeft or onRight" True
6571116
658− else if
659− List.member found.location
1117+ else if
1118+ List.member found.parentLayout
6601119 [ Testable.IsNearby Testable.InFront
6611120 , Testable.IsNearby Testable.Behind
6621121 , Testable.IsNearby Testable.Above
6631122 , Testable.IsNearby Testable.Below
6641123 ]
665− then
1124+ then
6661125 expectRoundedEquality
667− found.self.bbox.left
668− found.parent.bbox.left
1126+ { found = found.self.bbox.left
1127+ , expected = found.parent.bbox.left
1128+ }
6691129
670− else if List.length found.siblings == 0 then
1130+ else if List.length found.siblings == 0 then
6711131 expectRoundedEquality
672− found.self.bbox.left
673− (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+ }
6741135
675− else
676− case found.location of
1136+ else
1137+ case found.parentLayout of
6771138 Testable.InRow ->
6781139 let
6791140 siblingsOnLeft =
@@ -688,13 +1149,16 @@ alignLeft =
6881149 |> List.sum
6891150 in
6901151 expectRoundedEquality
691− found.self.bbox.left
692− (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+ }
6931155
6941156 _ ->
6951157 expectRoundedEquality
696− found.self.bbox.left
697− (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+ }
1161+ ]
6981162 }
6991163
7001164
@@ -704,8 +1168,9 @@ centerX =
7041168 Testable.LabeledTest
7051169 { label = "centerX"
7061170 , attr = Element.centerX
1171+ , id = Testable.NoId
7071172 , test =
708− \found _ ->
1173+ \found ->
7091174 let
7101175 selfCenter : Float
7111176 selfCenter =
@@ -715,16 +1180,18 @@ centerX =
7151180 parentCenter =
7161181 found.parent.bbox.left + (found.parent.bbox.width / 2)
7171182 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
1183+ if List.member found.parentLayout [ Testable.IsNearby Testable.OnRight, Testable.IsNearby Testable.OnLeft ] then
1184+ [ Testable.true "centerX doesn't apply to elements that are onLeft or onRight" True ]
7201185
7211186 else if List.length found.siblings == 0 then
722− expectRoundedEquality
723− selfCenter
724− parentCenter
1187+ [ expectRoundedEquality
1188+ { found = selfCenter
1189+ , expected = parentCenter
1190+ }
1191+ ]
7251192
7261193 else
727− case found.location of
1194+ case found.parentLayout of
7281195 Testable.InRow ->
7291196 let
7301197 siblingsOnLeft =
@@ -754,12 +1221,18 @@ centerX =
7541221 / 2
7551222 )
7561223 in
757− expectRoundedEquality
758− selfCenter
759− expectedCenter
1224+ [ expectRoundedEquality
1225+ { found = selfCenter
1226+ , expected = expectedCenter
1227+ }
1228+ ]
7601229
7611230 _ ->
762− expectRoundedEquality selfCenter parentCenter
1231+ [ expectRoundedEquality
1232+ { found = selfCenter
1233+ , expected = parentCenter
1234+ }
1235+ ]
7631236 }
7641237
7651238
@@ -769,30 +1242,35 @@ alignRight =
7691242 Testable.LabeledTest
7701243 { label = "alignRight"
7711244 , attr = Element.alignRight
1245+ , id = Testable.NoId
7721246 , 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
1247+ \found ->
1248+ if List.member found.parentLayout [ Testable.IsNearby Testable.OnLeft, Testable.IsNearby Testable.OnRight ] then
1249+ [ Testable.true "alignRight doesn't apply to elements that are onLeft or onRight" True ]
7761250
7771251 else if
778− List.member found.location
1252+ List.member found.parentLayout
7791253 [ Testable.IsNearby Testable.InFront
7801254 , Testable.IsNearby Testable.Behind
7811255 , Testable.IsNearby Testable.Above
7821256 , Testable.IsNearby Testable.Below
7831257 ]
7841258 then
785− expectRoundedEquality
786− found.self.bbox.right
787− found.parent.bbox.right
1259+ [ expectRoundedEquality
1260+ { found = found.self.bbox.right
1261+ , expected = found.parent.bbox.right
1262+ }
1263+ ]
7881264
7891265 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)
1266+ [ expectRoundedEquality
1267+ { found = found.self.bbox.right
1268+ , expected = found.parent.bbox.right + found.parent.bbox.padding.right
1269+ }
1270+ ]
7931271
7941272 else
795− case found.location of
1273+ case found.parentLayout of
7961274 Testable.InRow ->
7971275 let
7981276 siblingsOnRight =
@@ -806,14 +1284,18 @@ alignRight =
8061284 |> List.map (.width << .bbox)
8071285 |> List.sum
8081286 in
809− expectRoundedEquality
810− found.self.bbox.right
811− (found.parent.bbox.right - (found.parent.bbox.padding.right + widthsOnRight + spacings))
1287+ [ expectRoundedEquality
1288+ { found = found.self.bbox.right
1289+ , expected = found.parent.bbox.right - (found.parent.bbox.padding.right + widthsOnRight + spacings)
1290+ }
1291+ ]
8121292
8131293 _ ->
814− expectRoundedEquality
815− found.self.bbox.right
816− (found.parent.bbox.right + found.parent.bbox.padding.right)
1294+ [ expectRoundedEquality
1295+ { found = found.self.bbox.right
1296+ , expected = found.parent.bbox.right + found.parent.bbox.padding.right
1297+ }
1298+ ]
8171299 }
8181300
8191301
@@ -823,30 +1305,35 @@ alignTop =
8231305 Testable.LabeledTest
8241306 { label = "alignTop"
8251307 , attr = Element.alignTop
1308+ , id = Testable.NoId
8261309 , 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
1310+ \found ->
1311+ if List.member found.parentLayout [ Testable.IsNearby Testable.Above, Testable.IsNearby Testable.Below ] then
1312+ [ Testable.true "alignTop doesn't apply to elements that are above or below" True ]
8301313
8311314 else if
832− List.member found.location
1315+ List.member found.parentLayout
8331316 [ Testable.IsNearby Testable.InFront
8341317 , Testable.IsNearby Testable.Behind
8351318 , Testable.IsNearby Testable.OnRight
8361319 , Testable.IsNearby Testable.OnLeft
8371320 ]
8381321 then
839− expectRoundedEquality
840− found.self.bbox.top
841− found.parent.bbox.top
1322+ [ expectRoundedEquality
1323+ { found = found.self.bbox.top
1324+ , expected = found.parent.bbox.top
1325+ }
1326+ ]
8421327
8431328 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)
1329+ [ expectRoundedEquality
1330+ { found = found.self.bbox.top
1331+ , expected = found.parent.bbox.top + found.parent.bbox.padding.top
1332+ }
1333+ ]
8471334
8481335 else
849− case found.location of
1336+ case found.parentLayout of
8501337 Testable.InColumn ->
8511338 let
8521339 siblingsAbove =
@@ -860,14 +1347,18 @@ alignTop =
8601347 |> List.map (.height << .bbox)
8611348 |> List.sum
8621349 in
863− expectRoundedEquality
864− found.self.bbox.top
865− (found.parent.bbox.top + (found.parent.bbox.padding.top + heightsAbove + spacings))
1350+ [ expectRoundedEquality
1351+ { found = found.self.bbox.top
1352+ , expected = found.parent.bbox.top + (found.parent.bbox.padding.top + heightsAbove + spacings)
1353+ }
1354+ ]
8661355
8671356 _ ->
868− expectRoundedEquality
869− found.self.bbox.top
870− found.parent.bbox.top
1357+ [ expectRoundedEquality
1358+ { found = found.self.bbox.top
1359+ , expected = found.parent.bbox.top
1360+ }
1361+ ]
8711362 }
8721363
8731364
@@ -877,30 +1368,35 @@ alignBottom =
8771368 Testable.LabeledTest
8781369 { label = "alignBottom"
8791370 , attr = Element.alignBottom
1371+ , id = Testable.NoId
8801372 , 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
1373+ \found ->
1374+ if List.member found.parentLayout [ Testable.IsNearby Testable.Above, Testable.IsNearby Testable.Below ] then
1375+ [ Testable.true "alignBottom doesn't apply to elements that are above or below" True ]
8841376
8851377 else if
886− List.member found.location
1378+ List.member found.parentLayout
8871379 [ Testable.IsNearby Testable.InFront
8881380 , Testable.IsNearby Testable.Behind
8891381 , Testable.IsNearby Testable.OnRight
8901382 , Testable.IsNearby Testable.OnLeft
8911383 ]
8921384 then
893− expectRoundedEquality
894− found.self.bbox.bottom
895− found.parent.bbox.bottom
1385+ [ expectRoundedEquality
1386+ { found = found.self.bbox.bottom
1387+ , expected = found.parent.bbox.bottom
1388+ }
1389+ ]
8961390
8971391 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)
1392+ [ expectRoundedEquality
1393+ { found = found.self.bbox.bottom
1394+ , expected = found.parent.bbox.bottom + found.parent.bbox.padding.bottom
1395+ }
1396+ ]
9011397
9021398 else
903− case found.location of
1399+ case found.parentLayout of
9041400 Testable.InColumn ->
9051401 let
9061402 siblingsBelow =
@@ -914,20 +1410,31 @@ alignBottom =
9141410 |> List.map (.height << .bbox)
9151411 |> List.sum
9161412 in
917− expectRoundedEquality
918− found.self.bbox.bottom
919− (found.parent.bbox.bottom - (found.parent.bbox.padding.bottom + heightsBelow + spacings))
1413+ [ expectRoundedEquality
1414+ { found = found.self.bbox.bottom
1415+ , expected = found.parent.bbox.bottom - (found.parent.bbox.padding.bottom + heightsBelow + spacings)
1416+ }
1417+ ]
9201418
9211419 _ ->
922− expectRoundedEquality
923− found.self.bbox.bottom
924− (found.parent.bbox.bottom + found.parent.bbox.padding.bottom)
1420+ [ expectRoundedEquality
1421+ { found = found.self.bbox.bottom
1422+ , expected = found.parent.bbox.bottom + found.parent.bbox.padding.bottom
1423+ }
1424+ ]
9251425 }
9261426
9271427
928−expectRoundedEquality x y =
929− Expect.true ("within 1 of each other " ++ String.fromFloat x ++ ":" ++ String.fromFloat y)
930− (abs (x - y) < 1)
1428+expectRoundedEquality : { expected : Float, found : Float } -> Testable.LayoutExpectation
1429+expectRoundedEquality { expected, found } =
1430+ Testable.true
1431+ ("expected " ++ floatToString expected ++ ", found " ++ floatToString found)
1432+ (abs (expected - found) < 1)
1433+
1434+
1435+floatToString : Float -> String
1436+floatToString x =
1437+ String.fromFloat (toFloat (round (x * 100)) / 100)
9311438
9321439
9331440{-| -}
@@ -936,8 +1443,9 @@ centerY =
9361443 Testable.LabeledTest
9371444 { label = "centerY"
9381445 , attr = Element.centerY
1446+ , id = Testable.NoId
9391447 , test =
940− \found _ ->
1448+ \found ->
9411449 let
9421450 selfCenter =
9431451 found.self.bbox.top + (found.self.bbox.height / 2)
@@ -945,16 +1453,18 @@ centerY =
9451453 parentCenter =
9461454 found.parent.bbox.top + (found.parent.bbox.height / 2)
9471455 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
1456+ if List.member found.parentLayout [ Testable.IsNearby Testable.Above, Testable.IsNearby Testable.Below ] then
1457+ [ Testable.true "centerY doesn't apply to elements that are above or below" True ]
9501458
9511459 else if List.length found.siblings == 0 then
952− expectRoundedEquality
953− selfCenter
954− parentCenter
1460+ [ expectRoundedEquality
1461+ { found = selfCenter
1462+ , expected = parentCenter
1463+ }
1464+ ]
9551465
9561466 else
957− case found.location of
1467+ case found.parentLayout of
9581468 Testable.InColumn ->
9591469 let
9601470 siblingsOnTop =
@@ -984,12 +1494,18 @@ centerY =
9841494 / 2
9851495 )
9861496 in
987− expectRoundedEquality
988− selfCenter
989− expectedCenter
1497+ [ expectRoundedEquality
1498+ { found = selfCenter
1499+ , expected = expectedCenter
1500+ }
1501+ ]
9901502
9911503 _ ->
992− expectRoundedEquality selfCenter parentCenter
1504+ [ expectRoundedEquality
1505+ { found = selfCenter
1506+ , expected = parentCenter
1507+ }
1508+ ]
9931509 }
9941510
9951511
@@ -1001,8 +1517,12 @@ above element =
10011517 , element = element
10021518 , label = "above"
10031519 , test =
1004− \found _ ->
1005− expectRoundedEquality found.self.bbox.bottom found.parent.bbox.top
1520+ \found ->
1521+ [ expectRoundedEquality
1522+ { found = found.self.bbox.bottom
1523+ , expected = found.parent.bbox.top
1524+ }
1525+ ]
10061526 }
10071527
10081528
@@ -1014,8 +1534,12 @@ below element =
10141534 , element = element
10151535 , label = "below"
10161536 , test =
1017− \found _ ->
1018− expectRoundedEquality found.self.bbox.top found.parent.bbox.bottom
1537+ \found ->
1538+ [ expectRoundedEquality
1539+ { found = found.self.bbox.top
1540+ , expected = found.parent.bbox.bottom
1541+ }
1542+ ]
10191543 }
10201544
10211545
@@ -1027,8 +1551,12 @@ onRight element =
10271551 , element = element
10281552 , label = "onRight"
10291553 , test =
1030− \found _ ->
1031− expectRoundedEquality found.self.bbox.left found.parent.bbox.right
1554+ \found ->
1555+ [ expectRoundedEquality
1556+ { found = found.self.bbox.left
1557+ , expected = found.parent.bbox.right
1558+ }
1559+ ]
10321560 }
10331561
10341562
@@ -1040,8 +1568,12 @@ onLeft element =
10401568 , element = element
10411569 , label = "onLeft"
10421570 , test =
1043− \found _ ->
1044− expectRoundedEquality found.self.bbox.right found.parent.bbox.left
1571+ \found ->
1572+ [ expectRoundedEquality
1573+ { found = found.self.bbox.right
1574+ , expected = found.parent.bbox.left
1575+ }
1576+ ]
10451577 }
10461578
10471579
@@ -1057,11 +1589,12 @@ inFront element =
10571589 , element = element
10581590 , label = "inFront"
10591591 , test =
1060− withinHelper
1592+ \found ->
1593+ [ withinHelper found ]
10611594 }
10621595
10631596
1064−withinHelper found _ =
1597+withinHelper found =
10651598 let
10661599 horizontalCheck =
10671600 if found.self.bbox.width > found.parent.bbox.width then
@@ -1085,7 +1618,7 @@ withinHelper found _ =
10851618 , compare found.self.bbox.bottom (<=) found.parent.bbox.bottom
10861619 ]
10871620 in
1088− Expect.true "within the confines of the parent"
1621+ Testable.true "within the confines of the parent"
10891622 (List.all ((==) True)
10901623 (List.concat
10911624 [ horizontalCheck
@@ -1103,5 +1636,88 @@ behindContent element =
11031636 , element = element
11041637 , label = "behindContent"
11051638 , test =
1106− withinHelper
1639+ \found ->
1640+ [ withinHelper found ]
11071641 }
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