testcommon.js (4412B)
1 'use strict'; 2 3 function assert_px_equals(observed, expected, description) { 4 assert_equals(observed.unit, 'px', 5 `Unexpected unit type for '${description}'`); 6 assert_approx_equals(observed.value, expected, 0.0001, 7 `Unexpected value for ${description}`); 8 } 9 10 function CreateViewTimelineOpacityAnimation(test, target, options) { 11 const timeline_options = { 12 subject: target, 13 axis: 'block' 14 }; 15 if (options && 'timeline' in options) { 16 for (let key in options.timeline) { 17 timeline_options[key] = options.timeline[key]; 18 } 19 } 20 const animation_options = { 21 timeline: new ViewTimeline(timeline_options) 22 }; 23 if (options && 'animation' in options) { 24 for (let key in options.animation) { 25 animation_options[key] = options.animation[key]; 26 } 27 } 28 29 const anim = 30 target.animate({ opacity: [0.3, 0.7] }, animation_options); 31 test.add_cleanup(() => { 32 anim.cancel(); 33 }); 34 return anim; 35 } 36 37 // Verify that range specified in the options aligns with the active range of 38 // the animation. 39 // 40 // Sample call: 41 // await runTimelineBoundsTest(t, { 42 // timeline: { inset: [ CSS.percent(0), CSS.percent(20)] }, 43 // timing: { fill: 'both' } 44 // startOffset: 600, 45 // endOffset: 900 46 // }); 47 async function runTimelineBoundsTest(t, options, message) { 48 const scrollOffsetProp = options.axis == 'block' ? 'scrollTop' : 'scrollLeft'; 49 container[scrollOffsetProp] = 0; 50 await waitForNextFrame(); 51 52 const anim = 53 options.anim || 54 CreateViewTimelineOpacityAnimation(t, target, options); 55 if (options.timing) 56 anim.effect.updateTiming(options.timing); 57 58 const timeline = anim.timeline; 59 await anim.ready; 60 61 // Advance to the start offset, which triggers entry to the active phase. 62 container[scrollOffsetProp] = options.startOffset; 63 await waitForNextFrame(); 64 assert_equals(getComputedStyle(target).opacity, '0.3', 65 `Effect at the start of the active phase: ${message}`); 66 67 // Advance to the midpoint of the animation. 68 container[scrollOffsetProp] = (options.startOffset + options.endOffset) / 2; 69 await waitForNextFrame(); 70 assert_equals(getComputedStyle(target).opacity,'0.5', 71 `Effect at the midpoint of the active range: ${message}`); 72 73 // Advance to the end of the animation. 74 container[scrollOffsetProp] = options.endOffset; 75 await waitForNextFrame(); 76 assert_equals(getComputedStyle(target).opacity, '0.7', 77 `Effect is in the active phase at effect end time: ${message}`); 78 79 // Return the animation so that we can continue testing with the same object. 80 return anim; 81 } 82 83 // Sets the start and end range for a view timeline and ensures that the 84 // range aligns with expected values. 85 // 86 // Sample call: 87 // await runTimelineRangeTest(t, { 88 // rangeStart: { rangeName: 'cover', offset: CSS.percent(0) } , 89 // rangeEnd: { rangeName: 'cover', offset: CSS.percent(100) }, 90 // startOffset: 600, 91 // endOffset: 900 92 // }); 93 async function runTimelineRangeTest(t, options) { 94 const rangeToString = range => { 95 const parts = []; 96 if (range.rangeName) 97 parts.push(range.rangeName); 98 if (range.offset) 99 parts.push(`${range.offset.value}%`); 100 return parts.join(' '); 101 }; 102 const range = 103 `${rangeToString(options.rangeStart)} to ` + 104 `${rangeToString(options.rangeEnd)}`; 105 106 options.timeline = { 107 axis: options.axis || 'inline' 108 }; 109 options.animation = { 110 rangeStart: options.rangeStart, 111 rangeEnd: options.rangeEnd, 112 }; 113 options.timing = { 114 // Set fill to accommodate floating point precision errors at the 115 // endpoints. 116 fill: 'both' 117 }; 118 119 return runTimelineBoundsTest(t, options, range); 120 } 121 122 // Sets the Inset for a view timeline and ensures that the range aligns with 123 // expected values. 124 // 125 // Sample call: 126 // await runTimelineInsetTest(t, { 127 // inset: [ CSS.px(20), CSS.px(40) ] 128 // startOffset: 600, 129 // endOffset: 900 130 // }); 131 async function runTimelineInsetTest(t, options) { 132 options.timeline = { 133 axis: 'inline', 134 inset: options.inset 135 }; 136 options.timing = { 137 // Set fill to accommodate floating point precision errors at the 138 // endpoints. 139 fill: 'both' 140 } 141 const length = options.inset.length; 142 const range = 143 (options.inset instanceof Array) ? options.inset.join(' ') 144 : options.inset; 145 return runTimelineBoundsTest(t, options, range); 146 }