summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/scroll-animations/view-timelines/testcommon.js
blob: 969f282e678b5f36781c37aa734bb832013766a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
'use strict';

function assert_px_equals(observed, expected, description) {
  assert_equals(observed.unit, 'px',
                `Unexpected unit type for '${description}'`);
  assert_approx_equals(observed.value, expected, 0.0001,
                       `Unexpected value for ${description}`);
}

function CreateViewTimelineOpacityAnimation(test, target, options) {
  const viewTimelineOptions = {
    subject: target,
    axis: 'block'
  };
  if (options) {
    for (let key in options) {
      viewTimelineOptions[key] = options[key];
    }
  }

  const anim =
      target.animate(
          { opacity: [0.3, 0.7] },
          { timeline: new ViewTimeline(viewTimelineOptions) });
  test.add_cleanup(() => {
    anim.cancel();
  });
  return anim;
}

// Verify that range specified in the options aligns with the active range of
// the animation.
//
// Sample call:
// await runTimelineRangeTest(t, {
//   timeline: { inset: [ CSS.percent(0), CSS.percent(20)] },
//   timing: { fill: 'both' }
//   rangeStart: 600,
//   rangeEnd: 900
// });
async function runTimelineRangeTest(t, options, message) {
  container.scrollLeft = 0;
  await waitForNextFrame();

  const anim =
      options.anim ||
      CreateViewTimelineOpacityAnimation(t, target, options.timeline);
  if (options.timing)
    anim.effect.updateTiming(options.timing);

  const timeline = anim.timeline;
  await anim.ready;

  // Advance to the start offset, which triggers entry to the active phase.
  container.scrollLeft = options.rangeStart;
  await waitForNextFrame();
  assert_equals(getComputedStyle(target).opacity, '0.3',
                `Effect at the start of the active phase: ${message}`);

  // Advance to the midpoint of the animation.
  container.scrollLeft = (options.rangeStart + options.rangeEnd) / 2;
  await waitForNextFrame();
  assert_equals(getComputedStyle(target).opacity,'0.5',
                `Effect at the midpoint of the active range: ${message}`);

  // Advance to the end of the animation.
  container.scrollLeft = options.rangeEnd;
  await waitForNextFrame();
  assert_equals(getComputedStyle(target).opacity, '0.7',
                `Effect is in the active phase at effect end time: ${message}`);

  // Return the animation so that we can continue testing with the same object.
  return anim;
}

// Sets the start and end delays for a view timeline and ensures that the
// range aligns with expected values.
//
// Sample call:
// await runTimelineDelayTest(t, {
//   delay: { phase: 'cover', percent: CSS.percent(0) } ,
//   endDelay: { phase: 'cover', percent: CSS.percent(100) },
//   rangeStart: 600,
//   rangeEnd: 900
// });
async function runTimelineDelayTest(t, options) {
  const delayToString = delay => {
    const parts = [];
    if (delay.phase)
      parts.push(delay.phase);
    if (delay.percent)
      parts.push(`${delay.percent.value}%`);
    return parts.join(' ');
  };
  const range =
     `${delayToString(options.delay)} to ` +
     `${delayToString(options.endDelay)}`;

  options.timeline = {
    axis: 'inline'
  };
  options.timing = {
    delay: options.delay,
    endDelay: options.endDelay,
    // Set fill to accommodate floating point precision errors at the
    // endpoints.
    fill: 'both'
  };

  return runTimelineRangeTest(t, options, range);
}

// Sets the Inset for a view timeline and ensures that the range aligns with
// expected values.
//
// Sample call:
// await runTimelineDelayTest(t, {
//   inset: [ CSS.px(20), CSS.px(40) ]
//   rangeStart: 600,
//   rangeEnd: 900
// });
async function runTimelineInsetTest(t, options) {
  options.timeline = {
    axis: 'inline',
    inset: options.inset
  };
  options.timing = {
    // Set fill to accommodate floating point precision errors at the
    // endpoints.
    fill: 'both'
  }
  const length = options.inset.length;
  const range =
      (options.inset instanceof Array) ? options.inset.join(' ')
                                       : options.inset;
  return runTimelineRangeTest(t, options, range);
}