1 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
2 /* vim: set ts=2 sw=2 sts=2 et: */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
9 * For the purposes of this test, flex items are specified as a hash with a
10 * hash-entry for each CSS property that is to be set. In these per-property
11 * entries, the key is the property-name, and the value can be either of the
13 * (a) the property's specified value (which indicates that we don't need to
14 * bother checking the computed value of this particular property)
16 * (b) an array with 2-3 entries...
17 * [specifiedValue, expectedComputedValue (, epsilon) ]
18 * ...which indicates that the property's computed value should be
19 * checked. The array's first entry (for the specified value) may be
20 * null; this means that no value should be explicitly specified for this
21 * property. The second entry is the property's expected computed
22 * value. The third (optional) entry is an epsilon value, which allows for
23 * fuzzy equality when testing the computed value.
25 * To allow these testcases to be re-used in both horizontal and vertical
26 * flex containers, we specify "width"/"min-width"/etc. using the aliases
27 * "_main-size", "_min-main-size", etc. The test code can map these
28 * placeholder names to their corresponding property-names using the maps
29 * defined below -- gRowPropertyMapping, gColumnPropertyMapping, etc.
31 * If the testcase needs to customize its flex container at all (e.g. by
32 * specifying a custom container-size), it can do so by including a hash
33 * called "container_properties", with propertyName:propertyValue mappings.
34 * (This hash can use aliased property-names like "_main-size" as well.)
37 // The standard main-size we'll use for our flex container when setting up
38 // the testcases defined below:
39 var gDefaultFlexContainerSize = "200px";
41 // Left-to-right versions of placeholder property-names used in
43 var gRowPropertyMapping = {
44 "_main-size": "width",
45 "_min-main-size": "min-width",
46 "_max-main-size": "max-width",
47 "_border-main-start-width": "border-left-width",
48 "_border-main-end-width": "border-right-width",
49 "_padding-main-start": "padding-left",
50 "_padding-main-end": "padding-right",
51 "_margin-main-start": "margin-left",
52 "_margin-main-end": "margin-right",
55 // Right-to-left versions of placeholder property-names used in
57 var gRowReversePropertyMapping = {
58 "_main-size": "width",
59 "_min-main-size": "min-width",
60 "_max-main-size": "max-width",
61 "_border-main-start-width": "border-right-width",
62 "_border-main-end-width": "border-left-width",
63 "_padding-main-start": "padding-right",
64 "_padding-main-end": "padding-left",
65 "_margin-main-start": "margin-right",
66 "_margin-main-end": "margin-left",
69 // Top-to-bottom versions of placeholder property-names used in
71 var gColumnPropertyMapping = {
72 "_main-size": "height",
73 "_min-main-size": "min-height",
74 "_max-main-size": "max-height",
75 "_border-main-start-width": "border-top-width",
76 "_border-main-end-width": "border-bottom-width",
77 "_padding-main-start": "padding-top",
78 "_padding-main-end": "padding-bottom",
79 "_margin-main-start": "margin-top",
80 "_margin-main-end": "margin-bottom",
83 // Bottom-to-top versions of placeholder property-names used in
85 var gColumnReversePropertyMapping = {
86 "_main-size": "height",
87 "_min-main-size": "min-height",
88 "_max-main-size": "max-height",
89 "_border-main-start-width": "border-bottom-width",
90 "_border-main-end-width": "border-top-width",
91 "_padding-main-start": "padding-bottom",
92 "_padding-main-end": "padding-top",
93 "_margin-main-start": "margin-bottom",
94 "_margin-main-end": "margin-top",
97 // The list of actual testcase definitions:
98 var gFlexboxTestcases = [
99 // No flex properties specified --> should just use 'width' for sizing
102 { "_main-size": ["40px", "40px"] },
103 { "_main-size": ["65px", "65px"] },
106 // flex-basis is specified:
109 { "flex-basis": "50px", "_main-size": [null, "50px"] },
111 "flex-basis": "20px",
112 "_main-size": [null, "20px"],
116 // flex-basis is *large* -- sum of flex-basis values is > flex container size:
117 // (w/ 0 flex-shrink so we don't shrink):
122 "_main-size": [null, "150px"],
126 "_main-size": [null, "90px"],
130 // flex-basis is *large* -- each flex-basis value is > flex container size:
131 // (w/ 0 flex-shrink so we don't shrink):
136 "_main-size": [null, "250px"],
140 "_main-size": [null, "400px"],
144 // flex-basis has percentage value:
149 "_main-size": [null, "60px"],
153 "_main-size": [null, "90px"],
157 // flex-basis has calc(percentage) value:
161 "flex-basis": "calc(20%)",
162 "_main-size": [null, "40px"],
165 "flex-basis": "calc(80%)",
166 "_main-size": [null, "160px"],
170 // flex-basis has calc(percentage +/- length) value:
174 "flex-basis": "calc(10px + 20%)",
175 "_main-size": [null, "50px"],
178 "flex-basis": "calc(60% - 1px)",
179 "_main-size": [null, "119px"],
183 // flex-grow is specified:
188 "_main-size": [null, "60px"],
192 "_main-size": [null, "120px"],
196 "_main-size": [null, "20px"],
200 // Same ratio as prev. testcase; making sure we handle float inaccuracy
205 "_main-size": [null, "60px"],
209 "_main-size": [null, "120px"],
212 flex: "0.000001 20px",
213 "_main-size": [null, "20px"],
217 // Same ratio as prev. testcase, but with items cycled and w/
218 // "flex: none" & explicit size instead of "flex: 0 20px"
223 "_main-size": ["20px", "20px"],
227 "_main-size": [null, "60px"],
231 "_main-size": [null, "120px"],
236 // ...and now with flex-grow:[huge] to be sure we handle infinite float values
241 flex: "9999999999999999999999999999999999999999999999999999999",
242 "_main-size": [null, "200px"],
249 flex: "9999999999999999999999999999999999999999999999999999999",
250 "_main-size": [null, "50px"],
253 flex: "9999999999999999999999999999999999999999999999999999999",
254 "_main-size": [null, "50px"],
257 flex: "9999999999999999999999999999999999999999999999999999999",
258 "_main-size": [null, "50px"],
261 flex: "9999999999999999999999999999999999999999999999999999999",
262 "_main-size": [null, "50px"],
269 flex: "99999999999999999999999999999999999",
270 "_main-size": [null, "50px"],
273 flex: "99999999999999999999999999999999999",
274 "_main-size": [null, "50px"],
277 flex: "99999999999999999999999999999999999",
278 "_main-size": [null, "50px"],
281 flex: "99999999999999999999999999999999999",
282 "_main-size": [null, "50px"],
287 // And now, some testcases to check that we handle float accumulation error
290 // First, a testcase with just a custom-sized huge container, to be sure we'll
291 // be able to handle content on that scale, in the subsequent more-complex
294 container_properties: {
295 "_main-size": "9000000px",
300 "_main-size": [null, "9000000px"],
304 // ...and now with two flex items dividing up that container's huge size:
306 container_properties: {
307 "_main-size": "9000000px",
312 "_main-size": [null, "6000000px"],
316 "_main-size": [null, "3000000px"],
321 // OK, now to actually test accumulation error. Below, we have six flex items
322 // splitting up the container's size, with huge differences between flex
323 // weights. For simplicity, I've set up the weights so that they sum exactly
324 // to the container's size in px. So 1 unit of flex *should* get you 1px.
326 // NOTE: The expected computed "_main-size" values for the flex items below
327 // appear to add up to more than their container's size, which would suggest
328 // that they overflow their container unnecessarily. But they don't actually
329 // overflow -- this discrepancy is simply because Gecko's code for reporting
330 // computed-sizes rounds to 6 significant figures (in particular, the method
331 // (nsTSubstring_CharT::AppendFloat() does this). Internally, in app-units,
332 // the child frames' main-sizes add up exactly to the container's main-size,
333 // as you'd hope & expect.
335 container_properties: {
336 "_main-size": "9000000px",
341 "_main-size": [null, "3000000px"],
345 "_main-size": [null, "1px"],
349 "_main-size": [null, "1px"],
353 // NOTE: Expected value is off slightly, from float error when
354 // resolving flexible lengths & when generating computed value string:
355 "_main-size": [null, "3000000px"],
359 // NOTE: Expected value is off slightly, from float error when
360 // resolving flexible lengths & when generating computed value string:
361 "_main-size": [null, "3000000px"],
365 "_main-size": [null, "1px", 0.2],
369 // Same flex items as previous testcase, but now reordered such that the items
370 // with tiny flex weights are all listed last:
372 container_properties: {
373 "_main-size": "9000000px",
378 "_main-size": [null, "3000000px"],
382 // NOTE: Expected value is off slightly, from float error when
383 // resolving flexible lengths & when generating computed value string:
384 "_main-size": [null, "3000000px"],
388 // NOTE: Expected value is off slightly, from float error when
389 // resolving flexible lengths & when generating computed value string:
390 "_main-size": [null, "3000000px"],
394 "_main-size": [null, "1px", 0.2],
398 "_main-size": [null, "1px", 0.2],
402 "_main-size": [null, "1px", 0.2],
406 // Same flex items as previous testcase, but now reordered such that the items
407 // with tiny flex weights are all listed first:
409 container_properties: {
410 "_main-size": "9000000px",
415 // NOTE: Expected value is off slightly, from float error when
416 // resolving flexible lengths:
417 "_main-size": [null, "1px", 0.2],
421 // NOTE: Expected value is off slightly, from float error when
422 // resolving flexible lengths:
423 "_main-size": [null, "1px", 0.2],
427 // NOTE: Expected value is off slightly, from float error when
428 // resolving flexible lengths:
429 "_main-size": [null, "1px", 0.2],
433 "_main-size": [null, "3000000px"],
437 // NOTE: Expected value is off slightly, from float error when
438 // resolving flexible lengths & when generating computed value string:
439 "_main-size": [null, "3000000px"],
443 // NOTE: Expected value is off slightly, from float error when
444 // resolving flexible lengths & when generating computed value string:
445 "_main-size": [null, "3000000px"],
450 // Trying "flex: auto" (== "1 1 auto") w/ a mix of flex-grow/flex-basis values
455 "_main-size": [null, "45px"],
459 "_main-size": [null, "90px"],
463 "_main-size": [null, "65px"],
467 // Same as previous, but with items cycled & different syntax
472 "_main-size": [null, "65px"],
476 "_main-size": [null, "45px"],
480 "_main-size": [null, "90px"],
488 "_main-size": [null, "100px"],
489 border: "0px dashed",
490 "_border-main-start-width": ["5px", "5px"],
491 "_border-main-end-width": ["15px", "15px"],
492 "_margin-main-start": ["22px", "22px"],
493 "_margin-main-end": ["8px", "8px"],
497 "_main-size": [null, "50px"],
498 "_margin-main-start": ["auto", "0px"],
499 "_padding-main-end": ["auto", "0px"],
503 // Test negative flexibility:
505 // Basic testcase: just 1 item (relying on initial "flex-shrink: 1") --
506 // should shrink to container size.
508 items: [{ "_main-size": ["400px", "200px"] }],
510 // ...and now with a "flex" specification and a different flex-shrink value:
515 "_main-size": [null, "200px"],
519 // ...and now with multiple items, which all shrink proportionally (by 50%)
520 // to fit to the container, since they have the same (initial) flex-shrink val
523 { "_main-size": ["80px", "40px"] },
524 { "_main-size": ["40px", "20px"] },
525 { "_main-size": ["30px", "15px"] },
526 { "_main-size": ["250px", "125px"] },
529 // ...and now with positive flexibility specified. (should have no effect, so
530 // everything still shrinks by the same proportion, since the flex-shrink
531 // values are all the same).
536 "_main-size": [null, "80px"],
540 "_main-size": [null, "40px"],
544 "_main-size": [null, "80px"],
548 // ...and now with *different* flex-shrink values:
553 "_main-size": [null, "30px"],
557 "_main-size": [null, "20px"],
561 "_main-size": [null, "150px"],
565 // Same ratio as prev. testcase; making sure we handle float inaccuracy
569 flex: "4 20000000 50px",
570 "_main-size": [null, "30px"],
573 flex: "5 30000000 50px",
574 "_main-size": [null, "20px"],
577 flex: "0 0.0000001 150px",
578 "_main-size": [null, "150px"],
582 // Another "different flex-shrink values" testcase:
587 "_main-size": [null, "69px"],
591 "_main-size": [null, "120px"],
595 "_main-size": [null, "6px"],
599 "_main-size": [null, "5px"],
604 // ...and now with min-size (clamping the effects of flex-shrink on one item):
609 "_min-main-size": "50px",
610 "_main-size": [null, "50px"],
614 "_main-size": [null, "62.5px"],
618 "_main-size": [null, "87.5px"],
623 // Test a min-size that's much larger than initial preferred size, but small
624 // enough that our flexed size pushes us over it:
629 "_min-main-size": "110px",
630 "_main-size": ["50px", "125px"],
634 "_main-size": [null, "75px"],
639 // Test a min-size that's much larger than initial preferred size, and is
640 // even larger than our positively-flexed size, so that we have to increase it
641 // (as a 'min violation') after we've flexed.
646 "_min-main-size": "150px",
647 "_main-size": ["50px", "150px"],
651 "_main-size": [null, "50px"],
656 // Test min-size on multiple items simultaneously:
661 "_min-main-size": "20px",
662 "_main-size": [null, "20px"],
666 "_min-main-size": "150px",
667 "_main-size": ["50px", "180px"],
675 "_min-main-size": "90px",
676 "_main-size": [null, "90px"],
680 "_min-main-size": "80px",
681 "_main-size": [null, "80px"],
685 "_main-size": [null, "30px"],
690 // Test a case where _min-main-size will be violated on different items in
691 // successive iterations of the "resolve the flexible lengths" loop
696 "_min-main-size": "90px",
697 "_main-size": [null, "90px"],
701 "_min-main-size": "70px",
702 "_main-size": [null, "70px"],
706 "_main-size": [null, "40px"],
711 // Test some cases that have a min-size violation on one item and a
712 // max-size violation on another:
714 // Here, both items initially grow to 100px. That violates both
715 // items' sizing constraints (it's smaller than the min-size and larger than
716 // the max-size), so we clamp both of them and sum the clamping-differences:
718 // (130px - 100px) + (50px - 100px) = (30px) + (-50px) = -20px
720 // This sum is negative, so (per spec) we freeze the item that had its
721 // max-size violated (the second one) and restart the algorithm. This time,
722 // all the available space (200px - 50px = 150px) goes to the not-yet-frozen
723 // first item, and that puts it above its min-size, so all is well.
728 "_min-main-size": "130px",
729 "_main-size": [null, "150px"],
733 "_max-main-size": "50px",
734 "_main-size": [null, "50px"],
739 // As above, both items initially grow to 100px, and that violates both items'
740 // constraints. However, now the sum of the clamping differences is:
742 // (130px - 100px) + (80px - 100px) = (30px) + (-20px) = 10px
744 // This sum is positive, so (per spec) we freeze the item that had its
745 // min-size violated (the first one) and restart the algorithm. This time,
746 // all the available space (200px - 130px = 70px) goes to the not-yet-frozen
747 // second item, and that puts it below its max-size, so all is well.
752 "_min-main-size": "130px",
753 "_main-size": [null, "130px"],
757 "_max-main-size": "80px",
758 "_main-size": [null, "70px"],
763 // As above, both items initially grow to 100px, and that violates both items'
764 // constraints. So we clamp both items and sum the clamping differences to
765 // see what to do next. The sum is:
767 // (80px - 100px) + (120px - 100px) = (-20px) + (20px) = 0px
769 // Per spec, if the sum is 0, we're done -- we leave both items at their
775 "_max-main-size": "80px",
776 "_main-size": [null, "80px"],
780 "_min-main-size": "120px",
781 "_main-size": [null, "120px"],
786 // Test cases where flex-grow sums to less than 1:
787 // ===============================================
788 // This makes us treat the flexibilities like "fraction of free space"
789 // instead of weights, so that e.g. a single item with "flex-grow: 0.1"
790 // will only get 10% of the free space instead of all of the free space.
792 // Basic cases where flex-grow sum is less than 1:
797 "_main-size": [null, "110px"], // +10% of free space
805 "_main-size": [null, "160px"], // +80% of free space
810 // ... and now with two flex items:
815 "_main-size": [null, "110px"], // +40% of free space
819 "_main-size": [null, "50px"], // +20% of free space
824 // ...and now with max-size modifying how much free space one item can take:
829 "_main-size": [null, "110px"], // +40% of free space
833 "_max-main-size": "35px",
834 "_main-size": [null, "35px"], // +20% free space, then clamped
838 // ...and now with a max-size smaller than our flex-basis:
839 // (This makes us freeze the second item right away, before we compute
840 // the initial free space.)
845 "_main-size": [null, "118px"], // +40% of 200px-70px-10px
849 "_max-main-size": "10px",
850 "_main-size": [null, "10px"], // immediately frozen
854 // ...and now with a max-size and a huge flex-basis, such that we initially
855 // have negative free space, which makes the "% of [original] free space"
856 // calculations a bit more subtle. We set the "original free space" after
857 // we've clamped the second item (the first time the free space is positive).
862 "_main-size": [null, "118px"], // +40% of free space _after freezing
867 "_max-main-size": "10px",
868 "_main-size": [null, "10px"], // clamped immediately
873 // Now with min-size modifying how much free space our items take:
878 "_main-size": [null, "110px"], // +40% of free space
882 "_min-main-size": "70px",
883 "_main-size": [null, "70px"], // +20% free space, then clamped
888 // ...and now with a large enough min-size that it prevents the other flex
889 // item from taking its full desired portion of the original free space:
894 "_main-size": [null, "80px"], // (Can't take my full +40% of
895 // free space due to other item's
900 "_min-main-size": "120px",
901 "_main-size": [null, "120px"], // +20% free space, then clamped
905 // ...and now with a large-enough min-size that it pushes the other flex item
906 // to actually shrink a bit (with default "flex-shrink:1"):
911 "_main-size": [null, "20px"], // -10px, instead of desired +45px
915 "_min-main-size": "180px",
916 "_main-size": [null, "180px"], // +160px, instead of desired +30px
921 // In this case, the items' flexibilities don't initially sum to < 1, but they
922 // do after we freeze the third item for violating its max-size.
927 "_main-size": [null, "75px"],
928 // 1st loop: desires (0.3 / 5) * 150px = 9px. Tentatively granted.
929 // 2nd loop: desires 0.3 * 150px = 45px. Tentatively granted.
930 // 3rd loop: desires 0.3 * 150px = 45px. Granted +45px.
934 "_max-main-size": "30px",
935 "_main-size": [null, "30px"],
936 // First loop: desires (0.2 / 5) * 150px = 6px. Tentatively granted.
937 // Second loop: desires 0.2 * 150px = 30px. Frozen at +10px.
941 "_max-main-size": "20px",
942 "_main-size": [null, "20px"],
943 // First loop: desires (4.5 / 5) * 150px = 135px. Frozen at +20px.
948 // Make sure we calculate "original free space" correctly when one of our
949 // flex items will be clamped right away, due to max-size preventing it from
952 // Here, the second flex item is effectively inflexible; it's
953 // immediately frozen at 40px since we're growing & this item's max size
954 // trivially prevents it from growing. This leaves us with an "original
955 // free space" of 60px. The first flex item takes half of that, due to
956 // its flex-grow value of 0.5.
960 "_main-size": [null, "130px"],
964 "_max-main-size": "40px",
965 "_main-size": [null, "40px"],
970 // Same as previous example, but with a larger flex-basis on the second
971 // element (which shouldn't ultimately matter, because its max size clamps
972 // its size immediately anyway).
976 "_main-size": [null, "130px"],
980 "_max-main-size": "40px",
981 "_main-size": [null, "40px"],
987 // Here, the third flex item is effectively inflexible; it's immediately
988 // frozen at 0px since we're growing & this item's max size trivially
989 // prevents it from growing. This leaves us with an "original free space" of
990 // 100px. The first flex item takes 40px, and the third takes 50px, due to
991 // their flex values of 0.4 and 0.5.
995 "_main-size": [null, "90px"],
999 "_main-size": [null, "100px"],
1003 "_max-main-size": "0px",
1004 "_main-size": [null, "0px"],
1009 // Same as previous example, but with slightly larger flex-grow values on
1010 // the first and second items, which sum to 1.0 and produce slightly larger
1011 // main sizes. This demonstrates that there's no discontinuity between the
1012 // "< 1.0 sum" to ">= 1.0 sum" behavior, in this situation at least.
1016 "_main-size": [null, "95px"],
1020 "_main-size": [null, "105px"],
1024 "_max-main-size": "0px",
1025 "_main-size": [null, "0px"],
1030 // Test cases where flex-shrink sums to less than 1:
1031 // =================================================
1032 // This makes us treat the flexibilities more like "fraction of (negative)
1033 // free space" instead of weights, so that e.g. a single item with
1034 // "flex-shrink: 0.1" will only shrink by 10% of amount that it overflows
1035 // its container by.
1037 // It gets a bit more complex when there are multiple flex items, because
1038 // flex-shrink is scaled by the flex-basis before it's used as a weight. But
1039 // even with that scaling, the general principal is that e.g. if the
1040 // flex-shrink values *sum* to 0.6, then the items will collectively only
1041 // shrink by 60% (and hence will still overflow).
1043 // Basic cases where flex-grow sum is less than 1:
1047 flex: "0 0.1 300px",
1048 "_main-size": [null, "290px"], // +10% of (negative) free space
1055 flex: "0 0.8 400px",
1056 "_main-size": [null, "240px"], // +80% of (negative) free space
1061 // ...now with two flex items, with the same flex-basis value:
1065 flex: "0 0.4 150px",
1066 "_main-size": [null, "110px"], // +40% of (negative) free space
1069 flex: "0 0.2 150px",
1070 "_main-size": [null, "130px"], // +20% of (negative) free space
1075 // ...now with two flex items, with different flex-basis values (and hence
1076 // differently-scaled flex factors):
1080 flex: "0 0.3 100px",
1081 "_main-size": [null, "76px"],
1084 flex: "0 0.1 200px",
1085 "_main-size": [null, "184px"],
1089 // - Free space: -100px
1090 // - Sum of flex-shrink factors: 0.3 + 0.1 = 0.4
1091 // - Since that sum ^ is < 1, we'll only distribute that fraction of
1092 // the free space. We'll distribute: -100px * 0.4 = -40px
1094 // - 1st item's scaled flex factor: 0.3 * 100px = 30
1095 // - 2nd item's scaled flex factor: 0.1 * 200px = 20
1096 // - 1st item's share of distributed free space: 30/(30+20) = 60%
1097 // - 2nd item's share of distributed free space: 20/(30+20) = 40%
1100 // - 1st item gets 60% * -40px = -24px. 100px-24px = 76px
1101 // - 2nd item gets 40% * -40px = -16px. 200px-16px = 184px
1104 // ...now with min-size modifying how much one item can shrink:
1108 flex: "0 0.3 100px",
1109 "_main-size": [null, "70px"],
1112 flex: "0 0.1 200px",
1113 "_min-main-size": "190px",
1114 "_main-size": [null, "190px"],
1118 // - We proceed as in previous testcase, but clamp the second flex item
1119 // at its min main size.
1120 // - After that point, we have a total flex-shrink of = 0.3, so we
1121 // distribute 0.3 * -100px = -30px to the remaining unfrozen flex
1122 // items. Since there's only one unfrozen item left, it gets all of it.
1125 // ...now with min-size larger than our flex-basis:
1126 // (This makes us freeze the second item right away, before we compute
1127 // the initial free space.)
1131 flex: "0 0.3 100px",
1132 "_main-size": [null, "55px"], // +30% of 200px-100px-250px
1135 flex: "0 0.1 200px",
1136 "_min-main-size": "250px",
1137 "_main-size": [null, "250px"], // immediately frozen
1140 // (Same as previous example, except the min-main-size prevents the
1141 // second item from shrinking at all)
1144 // ...and now with a min-size and a small flex-basis, such that we initially
1145 // have positive free space, which makes the "% of [original] free space"
1146 // calculations a bit more subtle. We set the "original free space" after
1147 // we've clamped the second item (the first time the free space is negative).
1151 flex: "0 0.3 100px",
1152 "_main-size": [null, "70px"],
1156 "_min-main-size": "200px",
1157 "_main-size": [null, "200px"],
1162 // Now with max-size making an item shrink more than its flex-shrink value
1167 flex: "0 0.3 100px",
1168 "_main-size": [null, "70px"],
1171 flex: "0 0.1 200px",
1172 "_max-main-size": "150px",
1173 "_main-size": [null, "150px"],
1177 // - We proceed as in an earlier testcase, but clamp the second flex item
1178 // at its max main size.
1179 // - After that point, we have a total flex-shrink of = 0.3, so we
1180 // distribute 0.3 * -100px = -30px to the remaining unfrozen flex
1181 // items. Since there's only one unfrozen item left, it gets all of it.
1184 // ...and now with a small enough max-size that it prevents the other flex
1185 // item from taking its full desired portion of the (negative) original free
1190 flex: "0 0.3 100px",
1191 "_main-size": [null, "90px"],
1194 flex: "0 0.1 200px",
1195 "_max-main-size": "110px",
1196 "_main-size": [null, "110px"],
1200 // - We proceed as in an earlier testcase, but clamp the second flex item
1201 // at its max main size.
1202 // - After that point, we have a total flex-shrink of 0.3, which would
1203 // have us distribute 0.3 * -100px = -30px to the (one) remaining
1204 // unfrozen flex item. But our remaining free space is only -10px at
1205 // that point, so we distribute that instead.
1208 // ...and now with a small enough max-size that it pushes the other flex item
1209 // to actually grow a bit (with custom "flex-grow: 1" for this testcase):
1213 flex: "1 0.3 100px",
1214 "_main-size": [null, "120px"],
1217 flex: "1 0.1 200px",
1218 "_max-main-size": "80px",
1219 "_main-size": [null, "80px"],
1224 // In this case, the items' flexibilities don't initially sum to < 1, but they
1225 // do after we freeze the third item for violating its min-size.
1229 flex: "0 0.3 100px",
1230 "_main-size": [null, "76px"],
1233 flex: "0 0.1 150px",
1234 "_main-size": [null, "138px"],
1238 "_min-main-size": "40px",
1239 "_main-size": [null, "40px"],
1243 // - We immediately freeze the 3rd item, since we're shrinking and its
1244 // min size obviously prevents it from shrinking at all. This leaves
1245 // 200px - 100px - 150px - 40px = -90px of "initial free space".
1247 // - Our remaining flexible items have a total flex-shrink of 0.4,
1248 // so we can distribute a total of 0.4 * -90px = -36px
1250 // - We distribute that space using *scaled* flex factors:
1251 // * 1st item's scaled flex factor: 0.3 * 100px = 30
1252 // * 2nd item's scaled flex factor: 0.1 * 150px = 15
1253 // ...which means...
1254 // * 1st item's share of distributed free space: 30/(30+15) = 2/3
1255 // * 2nd item's share of distributed free space: 15/(30+15) = 1/3
1258 // - 1st item gets 2/3 * -36px = -24px. 100px - 24px = 76px
1259 // - 2nd item gets 1/3 * -36px = -12px. 150px - 12px = 138px
1262 // In this case, the items' flexibilities sum to > 1, in part due to an item
1263 // that *can't actually shrink* due to its 0 flex-basis (which gives it a
1264 // "scaled flex factor" of 0). This prevents us from triggering the special
1265 // behavior for flexibilities that sum to less than 1, and as a result, the
1266 // first item ends up absorbing all of the free space.
1271 "_main-size": [null, "200px"],
1275 "_main-size": [null, "0px"],
1280 // This case is similar to the one above, but with a *barely* nonzero base
1281 // size for the second item. This should produce a result similar to the case
1282 // above. (In particular, we should first distribute a very small amount of
1283 // negative free space to the second item, getting it to approximately zero,
1284 // and distribute the bulk of the negative free space to the first item,
1285 // getting it to approximately 200px.)
1290 "_main-size": [null, "200px"],
1294 "_main-size": [null, "0px"],
1298 // This case is similar to the ones above, but now we've increased the
1299 // flex-shrink value on the second-item so that it claims enough of the
1300 // negative free space to go below its min-size (0px). So, it triggers a min
1301 // violation & is frozen. For the loop *after* the min violation, the sum of
1302 // the remaining flex items' flex-shrink values is less than 1, so we trigger
1303 // the special <1 behavior and only distribute half of the remaining
1304 // (negative) free space to the first item (instead of all of it).
1309 "_main-size": [null, "250px"],
1313 "_main-size": [null, "0px"],