Wed, 31 Dec 2014 13:27:57 +0100
Ignore runtime configuration files generated during quality assurance.
1 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 sw=2 sts=2 et: */
4 /*
5 * This Source Code is subject to the terms of the Mozilla Public License
6 * version 2.0 (the "License"). You can obtain a copy of the License at
7 * http://mozilla.org/MPL/2.0/.
8 */
10 /**
11 * For the purposes of this test, flex items are specified as a hash with a
12 * hash-entry for each CSS property that is to be set. In these per-property
13 * entries, the key is the property-name, and the value can be either of the
14 * following:
15 * (a) the property's specified value (which indicates that we don't need to
16 * bother checking the computed value of this particular property)
17 * ...OR...
18 * (b) an array with 2-3 entries...
19 * [specifiedValue, expectedComputedValue (, epsilon) ]
20 * ...which indicates that the property's computed value should be
21 * checked. The array's first entry (for the specified value) may be
22 * null; this means that no value should be explicitly specified for this
23 * property. The second entry is the property's expected computed
24 * value. The third (optional) entry is an epsilon value, which allows for
25 * fuzzy equality when testing the computed value.
26 *
27 * To allow these testcases to be re-used in both horizontal and vertical
28 * flex containers, we specify "width"/"min-width"/etc. using the aliases
29 * "_main-size", "_min-main-size", etc. The test code can map these
30 * placeholder names to their corresponding property-names using the maps
31 * defined below -- gRowPropertyMapping, gColumnPropertyMapping, etc.
32 *
33 * If the testcase needs to customize its flex container at all (e.g. by
34 * specifying a custom container-size), it can do so by including a hash
35 * called "container_properties", with propertyName:propertyValue mappings.
36 * (This hash can use aliased property-names like "_main-size" as well.)
37 */
39 // The standard main-size we'll use for our flex container when setting up
40 // the testcases defined below:
41 var gDefaultFlexContainerSize = "200px";
43 // Left-to-right versions of placeholder property-names used in
44 // testcases below:
45 var gRowPropertyMapping =
46 {
47 "_main-size": "width",
48 "_min-main-size": "min-width",
49 "_max-main-size": "max-width",
50 "_border-main-start-width": "border-left-width",
51 "_border-main-end-width": "border-right-width",
52 "_padding-main-start": "padding-left",
53 "_padding-main-end": "padding-right",
54 "_margin-main-start": "margin-left",
55 "_margin-main-end": "margin-right"
56 };
58 // Right-to-left versions of placeholder property-names used in
59 // testcases below:
60 var gRowReversePropertyMapping =
61 {
62 "_main-size": "width",
63 "_min-main-size": "min-width",
64 "_max-main-size": "max-width",
65 "_border-main-start-width": "border-right-width",
66 "_border-main-end-width": "border-left-width",
67 "_padding-main-start": "padding-right",
68 "_padding-main-end": "padding-left",
69 "_margin-main-start": "margin-right",
70 "_margin-main-end": "margin-left"
71 };
73 // Top-to-bottom versions of placeholder property-names used in
74 // testcases below:
75 var gColumnPropertyMapping =
76 {
77 "_main-size": "height",
78 "_min-main-size": "min-height",
79 "_max-main-size": "max-height",
80 "_border-main-start-width": "border-top-width",
81 "_border-main-end-width": "border-bottom-width",
82 "_padding-main-start": "padding-top",
83 "_padding-main-end": "padding-bottom",
84 "_margin-main-start": "margin-top",
85 "_margin-main-end": "margin-bottom"
86 };
88 // Bottom-to-top versions of placeholder property-names used in
89 // testcases below:
90 var gColumnReversePropertyMapping =
91 {
92 "_main-size": "height",
93 "_min-main-size": "min-height",
94 "_max-main-size": "max-height",
95 "_border-main-start-width": "border-bottom-width",
96 "_border-main-end-width": "border-top-width",
97 "_padding-main-start": "padding-bottom",
98 "_padding-main-end": "padding-top",
99 "_margin-main-start": "margin-bottom",
100 "_margin-main-end": "margin-top"
101 };
103 // The list of actual testcase definitions:
104 var gFlexboxTestcases =
105 [
106 // No flex properties specified --> should just use 'width' for sizing
107 {
108 items:
109 [
110 { "_main-size": [ "40px", "40px" ] },
111 { "_main-size": [ "65px", "65px" ] },
112 ]
113 },
114 // flex-basis is specified:
115 {
116 items:
117 [
118 { "flex-basis": "50px",
119 "_main-size": [ null, "50px" ]
120 },
121 {
122 "flex-basis": "20px",
123 "_main-size": [ null, "20px" ]
124 },
125 ]
126 },
127 // flex-basis is *large* -- sum of flex-basis values is > flex container size:
128 // (w/ 0 flex-shrink so we don't shrink):
129 {
130 items:
131 [
132 {
133 "flex": "0 0 150px",
134 "_main-size": [ null, "150px" ]
135 },
136 {
137 "flex": "0 0 90px",
138 "_main-size": [ null, "90px" ]
139 },
140 ]
141 },
142 // flex-basis is *large* -- each flex-basis value is > flex container size:
143 // (w/ 0 flex-shrink so we don't shrink):
144 {
145 items:
146 [
147 {
148 "flex": "0 0 250px",
149 "_main-size": [ null, "250px" ]
150 },
151 {
152 "flex": "0 0 400px",
153 "_main-size": [ null, "400px" ]
154 },
155 ]
156 },
157 // flex-basis has percentage value:
158 {
159 items:
160 [
161 {
162 "flex-basis": "30%",
163 "_main-size": [ null, "60px" ]
164 },
165 {
166 "flex-basis": "45%",
167 "_main-size": [ null, "90px" ]
168 },
169 ]
170 },
171 // flex-basis has calc(percentage) value:
172 {
173 items:
174 [
175 {
176 "flex-basis": "calc(20%)",
177 "_main-size": [ null, "40px" ]
178 },
179 {
180 "flex-basis": "calc(80%)",
181 "_main-size": [ null, "160px" ]
182 },
183 ]
184 },
185 // flex-basis has calc(percentage +/- length) value:
186 {
187 items:
188 [
189 {
190 "flex-basis": "calc(10px + 20%)",
191 "_main-size": [ null, "50px" ]
192 },
193 {
194 "flex-basis": "calc(60% - 1px)",
195 "_main-size": [ null, "119px" ]
196 },
197 ]
198 },
199 // flex-grow is specified:
200 {
201 items:
202 [
203 {
204 "flex": "1",
205 "_main-size": [ null, "60px" ]
206 },
207 {
208 "flex": "2",
209 "_main-size": [ null, "120px" ]
210 },
211 {
212 "flex": "0 20px",
213 "_main-size": [ null, "20px" ]
214 }
215 ]
216 },
217 // Same ratio as prev. testcase; making sure we handle float inaccuracy
218 {
219 items:
220 [
221 {
222 "flex": "100000",
223 "_main-size": [ null, "60px" ]
224 },
225 {
226 "flex": "200000",
227 "_main-size": [ null, "120px" ]
228 },
229 {
230 "flex": "0.000001 20px",
231 "_main-size": [ null, "20px" ]
232 }
233 ]
234 },
235 // Same ratio as prev. testcase, but with items cycled and w/
236 // "flex: none" & explicit size instead of "flex: 0 20px"
237 {
238 items:
239 [
240 {
241 "flex": "none",
242 "_main-size": [ "20px", "20px" ]
243 },
244 {
245 "flex": "1",
246 "_main-size": [ null, "60px" ]
247 },
248 {
249 "flex": "2",
250 "_main-size": [ null, "120px" ]
251 }
252 ]
253 },
255 // ...and now with flex-grow:[huge] to be sure we handle infinite float values
256 // gracefully.
257 {
258 items:
259 [
260 {
261 "flex": "9999999999999999999999999999999999999999999999999999999",
262 "_main-size": [ null, "200px" ]
263 },
264 ]
265 },
266 {
267 items:
268 [
269 {
270 "flex": "9999999999999999999999999999999999999999999999999999999",
271 "_main-size": [ null, "50px" ]
272 },
273 {
274 "flex": "9999999999999999999999999999999999999999999999999999999",
275 "_main-size": [ null, "50px" ]
276 },
277 {
278 "flex": "9999999999999999999999999999999999999999999999999999999",
279 "_main-size": [ null, "50px" ]
280 },
281 {
282 "flex": "9999999999999999999999999999999999999999999999999999999",
283 "_main-size": [ null, "50px" ]
284 },
285 ]
286 },
287 {
288 items:
289 [
290 {
291 "flex": "99999999999999999999999999999999999",
292 "_main-size": [ null, "50px" ]
293 },
294 {
295 "flex": "99999999999999999999999999999999999",
296 "_main-size": [ null, "50px" ]
297 },
298 {
299 "flex": "99999999999999999999999999999999999",
300 "_main-size": [ null, "50px" ]
301 },
302 {
303 "flex": "99999999999999999999999999999999999",
304 "_main-size": [ null, "50px" ]
305 },
306 ]
307 },
309 // And now, some testcases to check that we handle float accumulation error
310 // gracefully.
312 // First, a testcase with just a custom-sized huge container, to be sure we'll
313 // be able to handle content on that scale, in the subsequent more-complex
314 // testcases:
315 {
316 container_properties:
317 {
318 "_main-size": "9000000px"
319 },
320 items:
321 [
322 {
323 "flex": "1",
324 "_main-size": [ null, "9000000px" ]
325 },
326 ]
327 },
328 // ...and now with two flex items dividing up that container's huge size:
329 {
330 container_properties:
331 {
332 "_main-size": "9000000px"
333 },
334 items:
335 [
336 {
337 "flex": "2",
338 "_main-size": [ null, "6000000px" ]
339 },
340 {
341 "flex": "1",
342 "_main-size": [ null, "3000000px" ]
343 },
344 ]
345 },
347 // OK, now to actually test accumulation error. Below, we have six flex items
348 // splitting up the container's size, with huge differences between flex
349 // weights. For simplicity, I've set up the weights so that they sum exactly
350 // to the container's size in px. So 1 unit of flex *should* get you 1px.
351 //
352 // NOTE: The expected computed "_main-size" values for the flex items below
353 // appear to add up to more than their container's size, which would suggest
354 // that they overflow their container unnecessarily. But they don't actually
355 // overflow -- this discrepancy is simply because Gecko's code for reporting
356 // computed-sizes rounds to 6 significant figures (in particular, the method
357 // (nsTSubstring_CharT::AppendFloat() does this). Internally, in app-units,
358 // the child frames' main-sizes add up exactly to the container's main-size,
359 // as you'd hope & expect.
360 {
361 container_properties:
362 {
363 "_main-size": "9000000px"
364 },
365 items:
366 [
367 {
368 "flex": "3000000",
369 "_main-size": [ null, "3000000px" ]
370 },
371 {
372 "flex": "1",
373 "_main-size": [ null, "1px" ]
374 },
375 {
376 "flex": "1",
377 "_main-size": [ null, "1px" ]
378 },
379 {
380 "flex": "2999999",
381 // NOTE: Expected value is off slightly, from float error when
382 // resolving flexible lengths & when generating computed value string:
383 "_main-size": [ null, "3000000px" ]
384 },
385 {
386 "flex": "2999998",
387 // NOTE: Expected value is off slightly, from float error when
388 // resolving flexible lengths & when generating computed value string:
389 "_main-size": [ null, "3000000px" ]
390 },
391 {
392 "flex": "1",
393 "_main-size": [ null, "1px", 0.2 ]
394 },
395 ]
396 },
397 // Same flex items as previous testcase, but now reordered such that the items
398 // with tiny flex weights are all listed last:
399 {
400 container_properties:
401 {
402 "_main-size": "9000000px"
403 },
404 items:
405 [
406 {
407 "flex": "3000000",
408 "_main-size": [ null, "3000000px" ]
409 },
410 {
411 "flex": "2999999",
412 // NOTE: Expected value is off slightly, from float error when
413 // resolving flexible lengths & when generating computed value string:
414 "_main-size": [ null, "3000000px" ]
415 },
416 {
417 "flex": "2999998",
418 // NOTE: Expected value is off slightly, from float error when
419 // resolving flexible lengths & when generating computed value string:
420 "_main-size": [ null, "3000000px" ]
421 },
422 {
423 "flex": "1",
424 "_main-size": [ null, "1px", 0.2 ]
425 },
426 {
427 "flex": "1",
428 "_main-size": [ null, "1px", 0.2 ]
429 },
430 {
431 "flex": "1",
432 "_main-size": [ null, "1px", 0.2 ]
433 },
434 ]
435 },
436 // Same flex items as previous testcase, but now reordered such that the items
437 // with tiny flex weights are all listed first:
438 {
439 container_properties:
440 {
441 "_main-size": "9000000px"
442 },
443 items:
444 [
445 {
446 "flex": "1",
447 // NOTE: Expected value is off slightly, from float error when
448 // resolving flexible lengths:
449 "_main-size": [ null, "1px", 0.2 ]
450 },
451 {
452 "flex": "1",
453 // NOTE: Expected value is off slightly, from float error when
454 // resolving flexible lengths:
455 "_main-size": [ null, "1px", 0.2 ]
456 },
457 {
458 "flex": "1",
459 // NOTE: Expected value is off slightly, from float error when
460 // resolving flexible lengths:
461 "_main-size": [ null, "1px", 0.2 ]
462 },
463 {
464 "flex": "3000000",
465 "_main-size": [ null, "3000000px" ]
466 },
467 {
468 "flex": "2999999",
469 // NOTE: Expected value is off slightly, from float error when
470 // resolving flexible lengths & when generating computed value string:
471 "_main-size": [ null, "3000000px" ]
472 },
473 {
474 "flex": "2999998",
475 // NOTE: Expected value is off slightly, from float error when
476 // resolving flexible lengths & when generating computed value string:
477 "_main-size": [ null, "3000000px" ]
478 },
479 ]
480 },
482 // Trying "flex: auto" (== "1 1 auto") w/ a mix of flex-grow/flex-basis values
483 {
484 items:
485 [
486 {
487 "flex": "auto",
488 "_main-size": [ null, "45px" ]
489 },
490 {
491 "flex": "2",
492 "_main-size": [ null, "90px" ]
493 },
494 {
495 "flex": "20px 1 0",
496 "_main-size": [ null, "65px" ]
497 }
498 ]
499 },
500 // Same as previous, but with items cycled & different syntax
501 {
502 items:
503 [
504 {
505 "flex": "20px",
506 "_main-size": [ null, "65px" ]
507 },
508 {
509 "flex": "1",
510 "_main-size": [ null, "45px" ]
511 },
512 {
513 "flex": "2",
514 "_main-size": [ null, "90px" ]
515 }
516 ]
517 },
518 {
519 items:
520 [
521 {
522 "flex": "2",
523 "_main-size": [ null, "100px" ],
524 "border": "0px dashed",
525 "_border-main-start-width": [ "5px", "5px" ],
526 "_border-main-end-width": [ "15px", "15px" ],
527 "_margin-main-start": [ "22px", "22px" ],
528 "_margin-main-end": [ "8px", "8px" ]
529 },
530 {
531 "flex": "1",
532 "_main-size": [ null, "50px" ],
533 "_margin-main-start": [ "auto", "0px" ],
534 "_padding-main-end": [ "auto", "0px" ],
535 }
536 ]
537 },
538 // Test negative flexibility:
540 // Basic testcase: just 1 item (relying on initial "flex-shrink: 1") --
541 // should shrink to container size.
542 {
543 items:
544 [
545 { "_main-size": [ "400px", "200px" ] },
546 ],
547 },
548 // ...and now with a "flex" specification and a different flex-shrink value:
549 {
550 items:
551 [
552 {
553 "flex": "4 2 250px",
554 "_main-size": [ null, "200px" ]
555 },
556 ],
557 },
558 // ...and now with multiple items, which all shrink proportionally (by 50%)
559 // to fit to the container, since they have the same (initial) flex-shrink val
560 {
561 items:
562 [
563 { "_main-size": [ "80px", "40px" ] },
564 { "_main-size": [ "40px", "20px" ] },
565 { "_main-size": [ "30px", "15px" ] },
566 { "_main-size": [ "250px", "125px" ] },
567 ]
568 },
569 // ...and now with positive flexibility specified. (should have no effect, so
570 // everything still shrinks by the same proportion, since the flex-shrink
571 // values are all the same).
572 {
573 items:
574 [
575 {
576 "flex": "4 3 100px",
577 "_main-size": [ null, "80px" ]
578 },
579 {
580 "flex": "5 3 50px",
581 "_main-size": [ null, "40px" ]
582 },
583 {
584 "flex": "0 3 100px",
585 "_main-size": [ null, "80px" ]
586 }
587 ]
588 },
589 // ...and now with *different* flex-shrink values:
590 {
591 items:
592 [
593 {
594 "flex": "4 2 50px",
595 "_main-size": [ null, "30px" ]
596 },
597 {
598 "flex": "5 3 50px",
599 "_main-size": [ null, "20px" ]
600 },
601 {
602 "flex": "0 0 150px",
603 "_main-size": [ null, "150px" ]
604 }
605 ]
606 },
607 // Same ratio as prev. testcase; making sure we handle float inaccuracy
608 {
609 items:
610 [
611 {
612 "flex": "4 20000000 50px",
613 "_main-size": [ null, "30px" ]
614 },
615 {
616 "flex": "5 30000000 50px",
617 "_main-size": [ null, "20px" ]
618 },
619 {
620 "flex": "0 0.0000001 150px",
621 "_main-size": [ null, "150px" ]
622 }
623 ]
624 },
625 // Another "different flex-shrink values" testcase:
626 {
627 items:
628 [
629 {
630 "flex": "4 2 115px",
631 "_main-size": [ null, "69px" ]
632 },
633 {
634 "flex": "5 1 150px",
635 "_main-size": [ null, "120px" ]
636 },
637 {
638 "flex": "1 4 30px",
639 "_main-size": [ null, "6px" ]
640 },
641 {
642 "flex": "1 0 5px",
643 "_main-size": [ null, "5px" ]
644 },
645 ]
646 },
648 // ...and now with min-size (clamping the effects of flex-shrink on one item):
649 {
650 items:
651 [
652 {
653 "flex": "4 5 75px",
654 "_min-main-size": "50px",
655 "_main-size": [ null, "50px" ],
656 },
657 {
658 "flex": "5 5 100px",
659 "_main-size": [ null, "62.5px" ]
660 },
661 {
662 "flex": "0 4 125px",
663 "_main-size": [ null, "87.5px" ]
664 }
665 ]
666 },
668 // Test a min-size that's much larger than initial preferred size, but small
669 // enough that our flexed size pushes us over it:
670 {
671 items:
672 [
673 {
674 "flex": "auto",
675 "_min-main-size": "110px",
676 "_main-size": [ "50px", "125px" ]
677 },
678 {
679 "flex": "auto",
680 "_main-size": [ null, "75px" ]
681 }
682 ]
683 },
685 // Test a min-size that's much larger than initial preferred size, and is
686 // even larger than our positively-flexed size, so that we have to increase it
687 // (as a 'min violation') after we've flexed.
688 {
689 items:
690 [
691 {
692 "flex": "auto",
693 "_min-main-size": "150px",
694 "_main-size": [ "50px", "150px" ]
695 },
696 {
697 "flex": "auto",
698 "_main-size": [ null, "50px" ]
699 }
700 ]
701 },
703 // Test min-size on multiple items simultaneously:
704 {
705 items:
706 [
707 {
708 "flex": "auto",
709 "_min-main-size": "20px",
710 "_main-size": [ null, "20px" ]
711 },
712 {
713 "flex": "9 auto",
714 "_min-main-size": "150px",
715 "_main-size": [ "50px", "180px" ]
716 },
717 ]
718 },
719 {
720 items:
721 [
722 {
723 "flex": "1 1 0px",
724 "_min-main-size": "90px",
725 "_main-size": [ null, "90px" ]
726 },
727 {
728 "flex": "1 1 0px",
729 "_min-main-size": "80px",
730 "_main-size": [ null, "80px" ]
731 },
732 {
733 "flex": "1 1 40px",
734 "_main-size": [ null, "30px" ]
735 }
736 ]
737 },
739 // Test a case where _min-main-size will be violated on different items in
740 // successive iterations of the "resolve the flexible lengths" loop
741 {
742 items:
743 [
744 {
745 "flex": "1 2 100px",
746 "_min-main-size": "90px",
747 "_main-size": [ null, "90px" ]
748 },
749 {
750 "flex": "1 1 100px",
751 "_min-main-size": "70px",
752 "_main-size": [ null, "70px" ]
753 },
754 {
755 "flex": "1 1 100px",
756 "_main-size": [ null, "40px" ]
757 }
758 ]
759 },
761 // Test some cases that have a min-size violation on one item and a
762 // max-size violation on another:
764 // Here, both items initially grow to 100px. That violates both
765 // items' sizing constraints (it's smaller than the min-size and larger than
766 // the max-size), so we clamp both of them and sum the clamping-differences:
767 //
768 // (130px - 100px) + (50px - 100px) = (30px) + (-50px) = -20px
769 //
770 // This sum is negative, so (per spec) we freeze the item that had its
771 // max-size violated (the second one) and restart the algorithm. This time,
772 // all the available space (200px - 50px = 150px) goes to the not-yet-frozen
773 // first item, and that puts it above its min-size, so all is well.
774 {
775 items:
776 [
777 {
778 "flex": "auto",
779 "_min-main-size": "130px",
780 "_main-size": [ null, "150px" ]
781 },
782 {
783 "flex": "auto",
784 "_max-main-size": "50px",
785 "_main-size": [ null, "50px" ]
786 },
787 ]
788 },
790 // As above, both items initially grow to 100px, and that violates both items'
791 // constraints. However, now the sum of the clamping differences is:
792 //
793 // (130px - 100px) + (80px - 100px) = (30px) + (-20px) = 10px
794 //
795 // This sum is positive, so (per spec) we freeze the item that had its
796 // min-size violated (the first one) and restart the algorithm. This time,
797 // all the available space (200px - 130px = 70px) goes to the not-yet-frozen
798 // second item, and that puts it below its max-size, so all is well.
799 {
800 items:
801 [
802 {
803 "flex": "auto",
804 "_min-main-size": "130px",
805 "_main-size": [ null, "130px" ]
806 },
807 {
808 "flex": "auto",
809 "_max-main-size": "80px",
810 "_main-size": [ null, "70px" ]
811 },
812 ]
813 },
815 // As above, both items initially grow to 100px, and that violates both items'
816 // constraints. So we clamp both items and sum the clamping differences to
817 // see what to do next. The sum is:
818 //
819 // (80px - 100px) + (120px - 100px) = (-20px) + (20px) = 0px
820 //
821 // Per spec, if the sum is 0, we're done -- we leave both items at their
822 // clamped sizes.
823 {
824 items:
825 [
826 {
827 "flex": "auto",
828 "_max-main-size": "80px",
829 "_main-size": [ null, "80px" ]
830 },
831 {
832 "flex": "auto",
833 "_min-main-size": "120px",
834 "_main-size": [ null, "120px" ]
835 },
836 ]
837 },
838 ];