@editframe/elements 0.26.3-beta.0 → 0.26.4-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/scripts/build-css.js +3 -3
- package/tsdown.config.ts +1 -1
- package/src/elements/ContextProxiesController.ts +0 -124
- package/src/elements/CrossUpdateController.ts +0 -22
- package/src/elements/EFAudio.browsertest.ts +0 -706
- package/src/elements/EFAudio.ts +0 -56
- package/src/elements/EFCaptions.browsertest.ts +0 -1960
- package/src/elements/EFCaptions.ts +0 -823
- package/src/elements/EFImage.browsertest.ts +0 -120
- package/src/elements/EFImage.ts +0 -113
- package/src/elements/EFMedia/AssetIdMediaEngine.test.ts +0 -224
- package/src/elements/EFMedia/AssetIdMediaEngine.ts +0 -110
- package/src/elements/EFMedia/AssetMediaEngine.browsertest.ts +0 -140
- package/src/elements/EFMedia/AssetMediaEngine.ts +0 -385
- package/src/elements/EFMedia/BaseMediaEngine.browsertest.ts +0 -400
- package/src/elements/EFMedia/BaseMediaEngine.ts +0 -505
- package/src/elements/EFMedia/BufferedSeekingInput.browsertest.ts +0 -386
- package/src/elements/EFMedia/BufferedSeekingInput.ts +0 -430
- package/src/elements/EFMedia/JitMediaEngine.browsertest.ts +0 -226
- package/src/elements/EFMedia/JitMediaEngine.ts +0 -256
- package/src/elements/EFMedia/audioTasks/makeAudioBufferTask.browsertest.ts +0 -679
- package/src/elements/EFMedia/audioTasks/makeAudioBufferTask.ts +0 -117
- package/src/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.ts +0 -246
- package/src/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.browsertest.ts +0 -59
- package/src/elements/EFMedia/audioTasks/makeAudioInitSegmentFetchTask.ts +0 -27
- package/src/elements/EFMedia/audioTasks/makeAudioInputTask.browsertest.ts +0 -55
- package/src/elements/EFMedia/audioTasks/makeAudioInputTask.ts +0 -53
- package/src/elements/EFMedia/audioTasks/makeAudioSeekTask.chunkboundary.regression.browsertest.ts +0 -207
- package/src/elements/EFMedia/audioTasks/makeAudioSeekTask.ts +0 -72
- package/src/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.ts +0 -32
- package/src/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.ts +0 -29
- package/src/elements/EFMedia/audioTasks/makeAudioTasksVideoOnly.browsertest.ts +0 -95
- package/src/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.ts +0 -184
- package/src/elements/EFMedia/shared/AudioSpanUtils.ts +0 -129
- package/src/elements/EFMedia/shared/BufferUtils.ts +0 -342
- package/src/elements/EFMedia/shared/GlobalInputCache.ts +0 -77
- package/src/elements/EFMedia/shared/MediaTaskUtils.ts +0 -44
- package/src/elements/EFMedia/shared/PrecisionUtils.ts +0 -46
- package/src/elements/EFMedia/shared/RenditionHelpers.browsertest.ts +0 -246
- package/src/elements/EFMedia/shared/RenditionHelpers.ts +0 -56
- package/src/elements/EFMedia/shared/ThumbnailExtractor.ts +0 -227
- package/src/elements/EFMedia/tasks/makeMediaEngineTask.browsertest.ts +0 -167
- package/src/elements/EFMedia/tasks/makeMediaEngineTask.ts +0 -88
- package/src/elements/EFMedia/videoTasks/MainVideoInputCache.ts +0 -76
- package/src/elements/EFMedia/videoTasks/ScrubInputCache.ts +0 -61
- package/src/elements/EFMedia/videoTasks/makeScrubVideoBufferTask.ts +0 -114
- package/src/elements/EFMedia/videoTasks/makeScrubVideoInitSegmentFetchTask.ts +0 -35
- package/src/elements/EFMedia/videoTasks/makeScrubVideoInputTask.ts +0 -52
- package/src/elements/EFMedia/videoTasks/makeScrubVideoSeekTask.ts +0 -124
- package/src/elements/EFMedia/videoTasks/makeScrubVideoSegmentFetchTask.ts +0 -44
- package/src/elements/EFMedia/videoTasks/makeScrubVideoSegmentIdTask.ts +0 -32
- package/src/elements/EFMedia/videoTasks/makeUnifiedVideoSeekTask.ts +0 -370
- package/src/elements/EFMedia/videoTasks/makeVideoBufferTask.ts +0 -109
- package/src/elements/EFMedia.browsertest.ts +0 -872
- package/src/elements/EFMedia.ts +0 -341
- package/src/elements/EFSourceMixin.ts +0 -60
- package/src/elements/EFSurface.browsertest.ts +0 -151
- package/src/elements/EFSurface.ts +0 -142
- package/src/elements/EFTemporal.browsertest.ts +0 -215
- package/src/elements/EFTemporal.ts +0 -800
- package/src/elements/EFThumbnailStrip.browsertest.ts +0 -585
- package/src/elements/EFThumbnailStrip.media-engine.browsertest.ts +0 -714
- package/src/elements/EFThumbnailStrip.ts +0 -906
- package/src/elements/EFTimegroup.browsertest.ts +0 -934
- package/src/elements/EFTimegroup.ts +0 -882
- package/src/elements/EFVideo.browsertest.ts +0 -1482
- package/src/elements/EFVideo.ts +0 -564
- package/src/elements/EFWaveform.ts +0 -547
- package/src/elements/FetchContext.browsertest.ts +0 -401
- package/src/elements/FetchMixin.ts +0 -38
- package/src/elements/SampleBuffer.ts +0 -94
- package/src/elements/TargetController.browsertest.ts +0 -230
- package/src/elements/TargetController.ts +0 -224
- package/src/elements/TimegroupController.ts +0 -26
- package/src/elements/durationConverter.ts +0 -35
- package/src/elements/parseTimeToMs.ts +0 -9
- package/src/elements/printTaskStatus.ts +0 -16
- package/src/elements/renderTemporalAudio.ts +0 -108
- package/src/elements/updateAnimations.browsertest.ts +0 -1884
- package/src/elements/updateAnimations.ts +0 -217
- package/src/elements/util.ts +0 -24
- package/src/gui/ContextMixin.browsertest.ts +0 -860
- package/src/gui/ContextMixin.ts +0 -562
- package/src/gui/Controllable.browsertest.ts +0 -258
- package/src/gui/Controllable.ts +0 -41
- package/src/gui/EFConfiguration.ts +0 -40
- package/src/gui/EFControls.browsertest.ts +0 -389
- package/src/gui/EFControls.ts +0 -195
- package/src/gui/EFDial.browsertest.ts +0 -84
- package/src/gui/EFDial.ts +0 -172
- package/src/gui/EFFilmstrip.browsertest.ts +0 -712
- package/src/gui/EFFilmstrip.ts +0 -1349
- package/src/gui/EFFitScale.ts +0 -152
- package/src/gui/EFFocusOverlay.ts +0 -79
- package/src/gui/EFPause.browsertest.ts +0 -202
- package/src/gui/EFPause.ts +0 -73
- package/src/gui/EFPlay.browsertest.ts +0 -202
- package/src/gui/EFPlay.ts +0 -73
- package/src/gui/EFPreview.ts +0 -74
- package/src/gui/EFResizableBox.browsertest.ts +0 -79
- package/src/gui/EFResizableBox.ts +0 -898
- package/src/gui/EFScrubber.ts +0 -151
- package/src/gui/EFTimeDisplay.browsertest.ts +0 -237
- package/src/gui/EFTimeDisplay.ts +0 -55
- package/src/gui/EFToggleLoop.ts +0 -35
- package/src/gui/EFTogglePlay.ts +0 -70
- package/src/gui/EFWorkbench.ts +0 -115
- package/src/gui/PlaybackController.ts +0 -527
- package/src/gui/TWMixin.css +0 -6
- package/src/gui/TWMixin.ts +0 -61
- package/src/gui/TargetOrContextMixin.ts +0 -185
- package/src/gui/currentTimeContext.ts +0 -5
- package/src/gui/durationContext.ts +0 -3
- package/src/gui/efContext.ts +0 -6
- package/src/gui/fetchContext.ts +0 -5
- package/src/gui/focusContext.ts +0 -7
- package/src/gui/focusedElementContext.ts +0 -5
- package/src/gui/playingContext.ts +0 -5
- package/src/otel/BridgeSpanExporter.ts +0 -150
- package/src/otel/setupBrowserTracing.ts +0 -73
- package/src/otel/tracingHelpers.ts +0 -251
- package/src/transcoding/cache/RequestDeduplicator.test.ts +0 -170
- package/src/transcoding/cache/RequestDeduplicator.ts +0 -65
- package/src/transcoding/cache/URLTokenDeduplicator.test.ts +0 -182
- package/src/transcoding/cache/URLTokenDeduplicator.ts +0 -101
- package/src/transcoding/types/index.ts +0 -312
- package/src/transcoding/utils/MediaUtils.ts +0 -63
- package/src/transcoding/utils/UrlGenerator.ts +0 -68
- package/src/transcoding/utils/constants.ts +0 -36
- package/src/utils/LRUCache.test.ts +0 -274
- package/src/utils/LRUCache.ts +0 -696
|
@@ -1,934 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
html,
|
|
3
|
-
LitElement,
|
|
4
|
-
render as litRender,
|
|
5
|
-
type TemplateResult,
|
|
6
|
-
} from "lit";
|
|
7
|
-
import { assert, beforeEach, describe, test } from "vitest";
|
|
8
|
-
import { EFTimegroup } from "./EFTimegroup.js";
|
|
9
|
-
import "./EFTimegroup.js";
|
|
10
|
-
import { customElement } from "lit/decorators/custom-element.js";
|
|
11
|
-
import { ContextMixin } from "../gui/ContextMixin.js";
|
|
12
|
-
import { EFTemporal } from "./EFTemporal.js";
|
|
13
|
-
// Need workbench to make workbench wrapping occurs
|
|
14
|
-
import "../gui/EFWorkbench.js";
|
|
15
|
-
// Additional imports for sequence boundary test
|
|
16
|
-
import "./EFVideo.js";
|
|
17
|
-
import "../gui/EFConfiguration.js";
|
|
18
|
-
import { Task } from "@lit/task";
|
|
19
|
-
import type { MediaEngine } from "../transcoding/types/index.js";
|
|
20
|
-
import { EFMedia } from "./EFMedia.js";
|
|
21
|
-
|
|
22
|
-
beforeEach(() => {
|
|
23
|
-
for (let i = 0; i < localStorage.length; i++) {
|
|
24
|
-
const key = localStorage.key(i);
|
|
25
|
-
if (typeof key !== "string") continue;
|
|
26
|
-
localStorage.removeItem(key);
|
|
27
|
-
}
|
|
28
|
-
while (document.body.children.length) {
|
|
29
|
-
document.body.children[0]?.remove();
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
@customElement("test-context")
|
|
34
|
-
class TestContext extends ContextMixin(LitElement) {}
|
|
35
|
-
|
|
36
|
-
@customElement("timegroup-test-media")
|
|
37
|
-
class TimegroupTestMedia extends EFMedia {
|
|
38
|
-
mediaEngineTaskCount = 0;
|
|
39
|
-
mediaEngineTask = new Task(this, {
|
|
40
|
-
autoRun: false,
|
|
41
|
-
args: () => ["source", null] as const,
|
|
42
|
-
task: () => {
|
|
43
|
-
this.mediaEngineTaskCount++;
|
|
44
|
-
return Promise.resolve({} as unknown as MediaEngine);
|
|
45
|
-
},
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
@customElement("test-frame-task-a")
|
|
50
|
-
class TestFrameTaskA extends EFTemporal(LitElement) {
|
|
51
|
-
frameTaskCount = 0;
|
|
52
|
-
|
|
53
|
-
frameTask = new Task(this, {
|
|
54
|
-
autoRun: false,
|
|
55
|
-
args: () => [],
|
|
56
|
-
task: () => {
|
|
57
|
-
this.frameTaskCount++;
|
|
58
|
-
return Promise.resolve();
|
|
59
|
-
},
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
@customElement("test-frame-task-b")
|
|
64
|
-
class TestFrameTaskB extends EFTemporal(LitElement) {
|
|
65
|
-
frameTaskCount = 0;
|
|
66
|
-
|
|
67
|
-
frameTask = new Task(this, {
|
|
68
|
-
autoRun: false,
|
|
69
|
-
args: () => [],
|
|
70
|
-
task: () => {
|
|
71
|
-
this.frameTaskCount++;
|
|
72
|
-
return Promise.resolve();
|
|
73
|
-
},
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
@customElement("test-frame-task-c")
|
|
78
|
-
class TestFrameTaskC extends EFTemporal(LitElement) {
|
|
79
|
-
frameTaskCount = 0;
|
|
80
|
-
|
|
81
|
-
frameTask = new Task(this, {
|
|
82
|
-
autoRun: false,
|
|
83
|
-
args: () => [],
|
|
84
|
-
task: () => {
|
|
85
|
-
this.frameTaskCount++;
|
|
86
|
-
return Promise.resolve();
|
|
87
|
-
},
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
@customElement("test-temporal")
|
|
92
|
-
class TestTemporal extends EFTemporal(LitElement) {
|
|
93
|
-
get hasOwnDuration(): boolean {
|
|
94
|
-
return true;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
declare global {
|
|
99
|
-
interface HTMLElementTagNameMap {
|
|
100
|
-
"test-temporal": TestTemporal;
|
|
101
|
-
"test-context": TestContext;
|
|
102
|
-
"timegroup-test-media": TimegroupTestMedia;
|
|
103
|
-
"test-frame-task-a": TestFrameTaskA;
|
|
104
|
-
"test-frame-task-b": TestFrameTaskB;
|
|
105
|
-
"test-frame-task-c": TestFrameTaskC;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
const renderTimegroup = (result: TemplateResult) => {
|
|
110
|
-
const container = document.createElement("div");
|
|
111
|
-
litRender(result, container);
|
|
112
|
-
const firstChild = container.querySelector("ef-timegroup");
|
|
113
|
-
if (!firstChild) {
|
|
114
|
-
throw new Error("No first child found");
|
|
115
|
-
}
|
|
116
|
-
if (!(firstChild instanceof EFTimegroup)) {
|
|
117
|
-
throw new Error("First child is not an EFTimegroup");
|
|
118
|
-
}
|
|
119
|
-
document.body.appendChild(container);
|
|
120
|
-
return firstChild;
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
describe(`<ef-timegroup mode='fit'>`, () => {
|
|
124
|
-
test("duration is zero when there is no parent to fit into", () => {
|
|
125
|
-
const timegroup = renderTimegroup(
|
|
126
|
-
html`<ef-timegroup mode="fit"></ef-timegroup>`,
|
|
127
|
-
);
|
|
128
|
-
assert.equal(timegroup.durationMs, 0);
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
test("duration is zero when there is no parent to fit into, even if there are children with duration", () => {
|
|
132
|
-
const timegroup = renderTimegroup(
|
|
133
|
-
html`<ef-timegroup mode="fit">
|
|
134
|
-
<ef-timegroup mode="fixed" duration="5s"></ef-timegroup>
|
|
135
|
-
</ef-timegroup>`,
|
|
136
|
-
);
|
|
137
|
-
assert.equal(timegroup.durationMs, 0);
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
test("duration is the duration of the parent timegroup", () => {
|
|
141
|
-
const timegroup = renderTimegroup(
|
|
142
|
-
html`<ef-timegroup mode="fixed" duration="10s">
|
|
143
|
-
<ef-timegroup id="child" mode="fit"></ef-timegroup>
|
|
144
|
-
</ef-timegroup>`,
|
|
145
|
-
);
|
|
146
|
-
const child = timegroup.querySelector("#child") as EFTimegroup;
|
|
147
|
-
assert.equal(child.durationMs, 10_000);
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
test("fit mode items inside a sequence are given zero duration and do not factor into the duration of the sequence", () => {
|
|
151
|
-
const timegroup = renderTimegroup(
|
|
152
|
-
html`<ef-timegroup mode="sequence">
|
|
153
|
-
<ef-timegroup id="child" mode="fit"></ef-timegroup>
|
|
154
|
-
</ef-timegroup>`,
|
|
155
|
-
);
|
|
156
|
-
const child = timegroup.querySelector("#child") as EFTimegroup;
|
|
157
|
-
assert.equal(child.durationMs, 0);
|
|
158
|
-
assert.equal(timegroup.durationMs, 0);
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
test("fit mode can be used to constrain a 'background' timegroup into a 'foreground' sequence", async () => {
|
|
162
|
-
const timegroup = renderTimegroup(
|
|
163
|
-
html`
|
|
164
|
-
<ef-timegroup mode="contain">
|
|
165
|
-
<ef-timegroup id="foreground" mode="sequence">
|
|
166
|
-
<ef-timegroup mode="fixed" duration="10s"></ef-timegroup>
|
|
167
|
-
<ef-timegroup mode="fixed" duration="10s"></ef-timegroup>
|
|
168
|
-
</ef-timegroup>
|
|
169
|
-
<ef-timegroup id="background" mode="fit">
|
|
170
|
-
<ef-timegroup mode="fixed" duration="30s"></ef-timegroup>
|
|
171
|
-
</ef-timegroup>
|
|
172
|
-
</ef-timegroup>
|
|
173
|
-
`,
|
|
174
|
-
);
|
|
175
|
-
|
|
176
|
-
const foreground = timegroup.querySelector("#foreground") as EFTimegroup;
|
|
177
|
-
const background = timegroup.querySelector("#background") as EFTimegroup;
|
|
178
|
-
assert.equal(foreground.durationMs, 20_000);
|
|
179
|
-
assert.equal(background.durationMs, 20_000);
|
|
180
|
-
});
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
describe(`<ef-timegroup mode="fixed">`, () => {
|
|
184
|
-
test("can explicitly set a duration in seconds", async () => {
|
|
185
|
-
const timegroup = renderTimegroup(
|
|
186
|
-
html`<ef-timegroup mode="fixed" duration="10s"></ef-timegroup>`,
|
|
187
|
-
);
|
|
188
|
-
assert.equal(timegroup.durationMs, 10_000);
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
test("can explicitly set a duration in milliseconds", async () => {
|
|
192
|
-
const timegroup = renderTimegroup(
|
|
193
|
-
html`<ef-timegroup mode="fixed" duration="10ms"></ef-timegroup>`,
|
|
194
|
-
);
|
|
195
|
-
assert.equal(timegroup.durationMs, 10);
|
|
196
|
-
});
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
describe(`<ef-timegroup mode="sequence">`, () => {
|
|
200
|
-
test("fixed duration is ignored", () => {
|
|
201
|
-
const timegroup = renderTimegroup(
|
|
202
|
-
html`<ef-timegroup mode="sequence" duration="10s"></ef-timegroup>`,
|
|
203
|
-
);
|
|
204
|
-
assert.equal(timegroup.durationMs, 0);
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
test("duration is the sum of child time groups", async () => {
|
|
208
|
-
const timegroup = renderTimegroup(
|
|
209
|
-
html`
|
|
210
|
-
<ef-timegroup mode="sequence">
|
|
211
|
-
<ef-timegroup mode="fixed" duration="5s"></ef-timegroup>
|
|
212
|
-
<ef-timegroup mode="fixed" duration="5s"></ef-timegroup>
|
|
213
|
-
</ef-timegroup>
|
|
214
|
-
`,
|
|
215
|
-
);
|
|
216
|
-
assert.equal(timegroup.durationMs, 10_000);
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
test("duration can include any element with a durationMs value", async () => {
|
|
220
|
-
const timegroup = renderTimegroup(
|
|
221
|
-
html`
|
|
222
|
-
<ef-timegroup mode="sequence">
|
|
223
|
-
<ef-timegroup mode="fixed" duration="5s"></ef-timegroup>
|
|
224
|
-
<test-temporal duration="5s"></test-temporal>
|
|
225
|
-
</ef-timegroup>
|
|
226
|
-
`,
|
|
227
|
-
);
|
|
228
|
-
|
|
229
|
-
assert.equal(timegroup.durationMs, 10_000);
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
test("arbitrary html does not factor into the calculation of a sequence duration", () => {
|
|
233
|
-
const timegroup = renderTimegroup(
|
|
234
|
-
html`
|
|
235
|
-
<ef-timegroup mode="sequence">
|
|
236
|
-
<div>
|
|
237
|
-
<ef-timegroup mode="fixed" duration="5s"></ef-timegroup>
|
|
238
|
-
</div>
|
|
239
|
-
</ef-timegroup>
|
|
240
|
-
`,
|
|
241
|
-
);
|
|
242
|
-
assert.equal(timegroup.durationMs, 5_000);
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
test("nested time groups do not factor into the calculation of a sequence duration", async () => {
|
|
246
|
-
const timegroup = renderTimegroup(
|
|
247
|
-
html`
|
|
248
|
-
<ef-timegroup mode="sequence">
|
|
249
|
-
<ef-timegroup mode="fixed" duration="5s">
|
|
250
|
-
<ef-timegroup mode="fixed" duration="5s"></ef-timegroup>
|
|
251
|
-
</ef-timegroup>
|
|
252
|
-
</ef-timegroup>
|
|
253
|
-
`,
|
|
254
|
-
);
|
|
255
|
-
assert.equal(timegroup.durationMs, 5_000);
|
|
256
|
-
});
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
describe(`<ef-timegroup mode="contain">`, () => {
|
|
260
|
-
test("fixed duration is ignored", () => {
|
|
261
|
-
const timegroup = renderTimegroup(
|
|
262
|
-
html`<ef-timegroup mode="contain" duration="10s"></ef-timegroup>`,
|
|
263
|
-
);
|
|
264
|
-
assert.equal(timegroup.durationMs, 0);
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
test("duration is the maximum of it's child time groups", async () => {
|
|
268
|
-
const timegroup = renderTimegroup(
|
|
269
|
-
html`
|
|
270
|
-
<ef-timegroup mode="contain">
|
|
271
|
-
<ef-timegroup mode="fixed" duration="5s"></ef-timegroup>
|
|
272
|
-
<ef-timegroup mode="fixed" duration="10s"></ef-timegroup>
|
|
273
|
-
</ef-timegroup>
|
|
274
|
-
`,
|
|
275
|
-
);
|
|
276
|
-
assert.equal(timegroup.durationMs, 10_000);
|
|
277
|
-
});
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
describe("startTimeMs", () => {
|
|
281
|
-
test("is computed relative to the root time group", async () => {
|
|
282
|
-
const timegroup = renderTimegroup(
|
|
283
|
-
html`<ef-timegroup id="root" mode="sequence">
|
|
284
|
-
<ef-timegroup id="a" mode="fixed" duration="5s"></ef-timegroup>
|
|
285
|
-
<ef-timegroup id="b" mode="sequence">
|
|
286
|
-
<ef-timegroup id="c" mode="fixed" duration="5s"></ef-timegroup>
|
|
287
|
-
<ef-timegroup id="d" mode="contain">
|
|
288
|
-
<ef-timegroup id="e" mode="fixed" duration="5s"></ef-timegroup>
|
|
289
|
-
<ef-timegroup id="f" mode="fixed" duration="5s"></ef-timegroup>
|
|
290
|
-
</ef-timegroup>
|
|
291
|
-
</ef-timegroup>
|
|
292
|
-
</ef-timegroup>`,
|
|
293
|
-
);
|
|
294
|
-
|
|
295
|
-
const a = timegroup.querySelector("#a") as EFTimegroup;
|
|
296
|
-
const b = timegroup.querySelector("#b") as EFTimegroup;
|
|
297
|
-
const c = timegroup.querySelector("#c") as EFTimegroup;
|
|
298
|
-
const d = timegroup.querySelector("#d") as EFTimegroup;
|
|
299
|
-
const e = timegroup.querySelector("#e") as EFTimegroup;
|
|
300
|
-
const f = timegroup.querySelector("#f") as EFTimegroup;
|
|
301
|
-
|
|
302
|
-
assert.equal(a.startTimeMs, 0);
|
|
303
|
-
assert.equal(b.startTimeMs, 5_000);
|
|
304
|
-
assert.equal(c.startTimeMs, 5_000);
|
|
305
|
-
assert.equal(d.startTimeMs, 10_000);
|
|
306
|
-
assert.equal(e.startTimeMs, 10_000);
|
|
307
|
-
assert.equal(f.startTimeMs, 10_000);
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
// // TODO: Rethink offset math, it shouldn't effect the duration of a temporal item
|
|
311
|
-
// // but actually change the start and end time.
|
|
312
|
-
// litTest.skip("can be offset with offset attribute", async ({ container }) => {
|
|
313
|
-
// render(
|
|
314
|
-
// html`<ef-timegroup id="root" mode="contain">
|
|
315
|
-
// <test-temporal id="a" duration="5s" offset="5s"></test-temporal>
|
|
316
|
-
// </ef-timegroup> `,
|
|
317
|
-
// container,
|
|
318
|
-
// );
|
|
319
|
-
|
|
320
|
-
// const root = container.querySelector("#root") as EFTimegroup;
|
|
321
|
-
// const a = container.querySelector("#a") as TestTemporal;
|
|
322
|
-
|
|
323
|
-
// assert.equal(a.durationMs, 5_000);
|
|
324
|
-
// assert.equal(root.durationMs, 10_000);
|
|
325
|
-
// assert.equal(a.startTimeMs, 5_000);
|
|
326
|
-
// });
|
|
327
|
-
|
|
328
|
-
// litTest.skip(
|
|
329
|
-
// "offsets do not affect start time when in a sequence group",
|
|
330
|
-
// async ({ container }) => {
|
|
331
|
-
// render(
|
|
332
|
-
// html`<ef-timegroup id="root" mode="sequence">
|
|
333
|
-
// <test-temporal id="a" duration="5s"></test-temporal>
|
|
334
|
-
// <test-temporal id="b" duration="5s" offset="5s"></test-temporal>
|
|
335
|
-
// </ef-timegroup> `,
|
|
336
|
-
// container,
|
|
337
|
-
// );
|
|
338
|
-
|
|
339
|
-
// const root = container.querySelector("#root") as EFTimegroup;
|
|
340
|
-
// const a = container.querySelector("#a") as TestTemporal;
|
|
341
|
-
// const b = container.querySelector("#b") as TestTemporal;
|
|
342
|
-
|
|
343
|
-
// assert.equal(root.durationMs, 10_000);
|
|
344
|
-
// assert.equal(a.startTimeMs, 0);
|
|
345
|
-
// assert.equal(b.startTimeMs, 5_000);
|
|
346
|
-
// },
|
|
347
|
-
// );
|
|
348
|
-
|
|
349
|
-
test("temporal elements default to expand to fill a timegroup", async () => {
|
|
350
|
-
const timegroup = renderTimegroup(
|
|
351
|
-
html`<ef-timegroup id="root" mode="fixed" duration="10s">
|
|
352
|
-
<test-temporal id="a"></test-temporal>
|
|
353
|
-
</ef-timegroup> `,
|
|
354
|
-
);
|
|
355
|
-
|
|
356
|
-
const a = timegroup.querySelector("#a") as TestTemporal;
|
|
357
|
-
|
|
358
|
-
assert.equal(timegroup.durationMs, 10_000);
|
|
359
|
-
assert.equal(a.durationMs, 10_000);
|
|
360
|
-
});
|
|
361
|
-
|
|
362
|
-
test("element's parentTimegroup updates as they move", async () => {
|
|
363
|
-
const container = document.createElement("div");
|
|
364
|
-
document.body.appendChild(container);
|
|
365
|
-
const timegroup1 = document.createElement("ef-timegroup");
|
|
366
|
-
timegroup1.setAttribute("mode", "fixed");
|
|
367
|
-
timegroup1.setAttribute("duration", "5s");
|
|
368
|
-
|
|
369
|
-
const timegroup2 = document.createElement("ef-timegroup");
|
|
370
|
-
timegroup2.setAttribute("mode", "fixed");
|
|
371
|
-
timegroup2.setAttribute("duration", "5s");
|
|
372
|
-
|
|
373
|
-
container.appendChild(timegroup1);
|
|
374
|
-
container.appendChild(timegroup2);
|
|
375
|
-
|
|
376
|
-
const temporal = document.createElement("test-temporal");
|
|
377
|
-
|
|
378
|
-
timegroup1.appendChild(temporal);
|
|
379
|
-
|
|
380
|
-
assert.equal(temporal.parentTimegroup, timegroup1);
|
|
381
|
-
|
|
382
|
-
timegroup2.appendChild(temporal);
|
|
383
|
-
assert.equal(temporal.parentTimegroup, timegroup2);
|
|
384
|
-
});
|
|
385
|
-
|
|
386
|
-
test("elements can access their root temporal element", async () => {
|
|
387
|
-
const root = renderTimegroup(
|
|
388
|
-
html`<ef-timegroup id="root" mode="contain" duration="10s">
|
|
389
|
-
<ef-timegroup id="a" mode="contain">
|
|
390
|
-
<div>
|
|
391
|
-
<ef-timegroup id="b" mode="contain">
|
|
392
|
-
<div>
|
|
393
|
-
<test-temporal id="c" duration="5s"></test-temporal>
|
|
394
|
-
</div>
|
|
395
|
-
</ef-timegroup>
|
|
396
|
-
</div>
|
|
397
|
-
</ef-timegroup>
|
|
398
|
-
</ef-timegroup> `,
|
|
399
|
-
);
|
|
400
|
-
|
|
401
|
-
const a = root.querySelector("#a") as EFTimegroup;
|
|
402
|
-
const b = root.querySelector("#b") as EFTimegroup;
|
|
403
|
-
const c = root.querySelector("#c") as TestTemporal;
|
|
404
|
-
|
|
405
|
-
assert.equal(root.rootTimegroup, root);
|
|
406
|
-
|
|
407
|
-
assert.equal(a.rootTimegroup, root);
|
|
408
|
-
assert.equal(b.rootTimegroup, root);
|
|
409
|
-
assert.equal(c.rootTimegroup, root);
|
|
410
|
-
});
|
|
411
|
-
});
|
|
412
|
-
|
|
413
|
-
describe("setting currentTime", () => {
|
|
414
|
-
test("persists in localStorage if the timegroup has an id and is in the dom", async () => {
|
|
415
|
-
const timegroup = renderTimegroup(
|
|
416
|
-
html`<ef-timegroup id="localStorage-test" mode="fixed" duration="10s"></ef-timegroup>`,
|
|
417
|
-
);
|
|
418
|
-
localStorage.removeItem(timegroup.storageKey);
|
|
419
|
-
document.body.appendChild(timegroup);
|
|
420
|
-
await timegroup.updateComplete;
|
|
421
|
-
await timegroup.waitForMediaDurations();
|
|
422
|
-
|
|
423
|
-
// Use the new seek() method which ensures everything is ready
|
|
424
|
-
await timegroup.seek(5_000_000); // 5000 seconds in ms, should clamp to 10s
|
|
425
|
-
|
|
426
|
-
const storedValue = localStorage.getItem(timegroup.storageKey);
|
|
427
|
-
assert.equal(storedValue, "10"); // Should store 10 (clamped from 5000 to duration)
|
|
428
|
-
timegroup.remove();
|
|
429
|
-
});
|
|
430
|
-
|
|
431
|
-
test("root timegroup remains visible when currentTime equals duration exactly", async () => {
|
|
432
|
-
const timegroup = renderTimegroup(
|
|
433
|
-
html`<ef-timegroup id="end-time-test" mode="fixed" duration="10s"></ef-timegroup>`,
|
|
434
|
-
);
|
|
435
|
-
await timegroup.waitForMediaDurations();
|
|
436
|
-
|
|
437
|
-
// Set currentTime to exactly the duration
|
|
438
|
-
timegroup.currentTime = 10; // 10 seconds
|
|
439
|
-
await timegroup.seekTask.taskComplete;
|
|
440
|
-
await timegroup.frameTask.taskComplete;
|
|
441
|
-
|
|
442
|
-
// The root timegroup should still be visible at the exact end time
|
|
443
|
-
assert.notEqual(
|
|
444
|
-
timegroup.style.display,
|
|
445
|
-
"none",
|
|
446
|
-
"Root timegroup should be visible at exact end time",
|
|
447
|
-
);
|
|
448
|
-
});
|
|
449
|
-
|
|
450
|
-
test("root timegroup becomes hidden only after currentTime exceeds duration", async () => {
|
|
451
|
-
const timegroup = renderTimegroup(
|
|
452
|
-
html`<ef-timegroup id="beyond-end-test" mode="fixed" duration="10s"></ef-timegroup>`,
|
|
453
|
-
);
|
|
454
|
-
await timegroup.waitForMediaDurations();
|
|
455
|
-
|
|
456
|
-
// Set currentTime beyond the duration (should be clamped to duration)
|
|
457
|
-
timegroup.currentTime = 15; // 15 seconds, should clamp to 10s
|
|
458
|
-
await timegroup.seekTask.taskComplete;
|
|
459
|
-
await timegroup.frameTask.taskComplete;
|
|
460
|
-
|
|
461
|
-
// Even when clamped, it should still be visible at the end
|
|
462
|
-
assert.notEqual(
|
|
463
|
-
timegroup.style.display,
|
|
464
|
-
"none",
|
|
465
|
-
"Root timegroup should be visible even when time is clamped to duration",
|
|
466
|
-
);
|
|
467
|
-
// Verify that the time was actually clamped
|
|
468
|
-
assert.equal(
|
|
469
|
-
timegroup.currentTime,
|
|
470
|
-
10,
|
|
471
|
-
"Time should be clamped to duration",
|
|
472
|
-
);
|
|
473
|
-
});
|
|
474
|
-
|
|
475
|
-
test("does not persist in localStorage if the timegroup has no id", async () => {
|
|
476
|
-
const timegroup = renderTimegroup(
|
|
477
|
-
html`<ef-timegroup mode="fixed" duration="10s"></ef-timegroup>`,
|
|
478
|
-
);
|
|
479
|
-
document.body.appendChild(timegroup);
|
|
480
|
-
timegroup.currentTime = 5_000;
|
|
481
|
-
timegroup.removeAttribute("id");
|
|
482
|
-
assert.throws(() => {
|
|
483
|
-
assert.isNull(localStorage.getItem(timegroup.storageKey));
|
|
484
|
-
}, "Timegroup must have an id to use localStorage");
|
|
485
|
-
timegroup.remove();
|
|
486
|
-
});
|
|
487
|
-
|
|
488
|
-
test("nested items derive their ownCurrentTimeMs", async () => {
|
|
489
|
-
const timegroup = renderTimegroup(
|
|
490
|
-
html`
|
|
491
|
-
<ef-timegroup id="root" mode="sequence">
|
|
492
|
-
<ef-timegroup id="a" mode="fixed" duration="5s"> </ef-timegroup>
|
|
493
|
-
<ef-timegroup id="b" mode="fixed" duration="5s"> </ef-timegroup>
|
|
494
|
-
</ef-timegroup>
|
|
495
|
-
`,
|
|
496
|
-
);
|
|
497
|
-
|
|
498
|
-
const root = timegroup;
|
|
499
|
-
const a = timegroup.querySelector("#a") as EFTimegroup;
|
|
500
|
-
const b = timegroup.querySelector("#b") as EFTimegroup;
|
|
501
|
-
|
|
502
|
-
assert.equal(a.ownCurrentTimeMs, 0);
|
|
503
|
-
assert.equal(b.ownCurrentTimeMs, 0);
|
|
504
|
-
|
|
505
|
-
root.currentTimeMs = 2_500;
|
|
506
|
-
|
|
507
|
-
assert.equal(a.ownCurrentTimeMs, 2_500);
|
|
508
|
-
assert.equal(b.ownCurrentTimeMs, 0);
|
|
509
|
-
|
|
510
|
-
// Wait for frame update to complete before next assignment
|
|
511
|
-
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
512
|
-
|
|
513
|
-
root.currentTimeMs = 7_500;
|
|
514
|
-
|
|
515
|
-
assert.equal(a.ownCurrentTimeMs, 5_000);
|
|
516
|
-
assert.equal(b.ownCurrentTimeMs, 2_500);
|
|
517
|
-
});
|
|
518
|
-
});
|
|
519
|
-
|
|
520
|
-
describe("shouldWrapWithWorkbench", () => {
|
|
521
|
-
test.skip("should not wrap if EF_INTERACTIVE is false", () => {
|
|
522
|
-
// TODO: need a way to define EF_INTERACTIVE in a test
|
|
523
|
-
});
|
|
524
|
-
|
|
525
|
-
test.skip("should wrap if root-most timegroup", () => {
|
|
526
|
-
// TODO: This test requires EF_INTERACTIVE to be true, which is a module-level constant
|
|
527
|
-
// that cannot be modified in tests. Need a way to test this behavior.
|
|
528
|
-
});
|
|
529
|
-
|
|
530
|
-
test("should not wrap if contained within a preview context", () => {
|
|
531
|
-
const timegorup = document.createElement("ef-timegroup");
|
|
532
|
-
const context = document.createElement("test-context");
|
|
533
|
-
context.append(timegorup);
|
|
534
|
-
assert.isFalse(timegorup.shouldWrapWithWorkbench());
|
|
535
|
-
});
|
|
536
|
-
});
|
|
537
|
-
|
|
538
|
-
describe("DOM nodes", () => {
|
|
539
|
-
test("can have mode and duration set as attributes", () => {
|
|
540
|
-
const timegroup = document.createElement("ef-timegroup");
|
|
541
|
-
timegroup.setAttribute("mode", "fixed");
|
|
542
|
-
timegroup.setAttribute("duration", "10s");
|
|
543
|
-
assert.equal(timegroup.mode, "fixed");
|
|
544
|
-
assert.equal(timegroup.durationMs, 10_000);
|
|
545
|
-
});
|
|
546
|
-
});
|
|
547
|
-
|
|
548
|
-
describe("Dynamic content updates", () => {
|
|
549
|
-
test("updates duration when new child temporal elements are added dynamically", async () => {
|
|
550
|
-
// Create a sequence timegroup with initial children
|
|
551
|
-
const timegroup = renderTimegroup(
|
|
552
|
-
html`<ef-timegroup mode="sequence">
|
|
553
|
-
<ef-timegroup mode="fixed" duration="3s"></ef-timegroup>
|
|
554
|
-
<ef-timegroup mode="fixed" duration="2s"></ef-timegroup>
|
|
555
|
-
</ef-timegroup>`,
|
|
556
|
-
);
|
|
557
|
-
|
|
558
|
-
// Initial duration should be 5 seconds (3s + 2s)
|
|
559
|
-
assert.equal(timegroup.durationMs, 5_000);
|
|
560
|
-
assert.equal(timegroup.childTemporals.length, 2);
|
|
561
|
-
|
|
562
|
-
// Dynamically add a new child element
|
|
563
|
-
const newChild = document.createElement("ef-timegroup");
|
|
564
|
-
newChild.setAttribute("mode", "fixed");
|
|
565
|
-
newChild.setAttribute("duration", "4s");
|
|
566
|
-
timegroup.appendChild(newChild);
|
|
567
|
-
|
|
568
|
-
// Wait for slot change event to process
|
|
569
|
-
await timegroup.updateComplete;
|
|
570
|
-
|
|
571
|
-
// Duration should now include the new child (3s + 2s + 4s = 9s)
|
|
572
|
-
assert.equal(timegroup.durationMs, 9_000);
|
|
573
|
-
assert.equal(timegroup.childTemporals.length, 3);
|
|
574
|
-
});
|
|
575
|
-
|
|
576
|
-
test("updates duration when child temporal elements are removed dynamically", async () => {
|
|
577
|
-
// Create a contain timegroup with initial children
|
|
578
|
-
const timegroup = renderTimegroup(
|
|
579
|
-
html`<ef-timegroup mode="contain">
|
|
580
|
-
<ef-timegroup id="child1" mode="fixed" duration="5s"></ef-timegroup>
|
|
581
|
-
<ef-timegroup id="child2" mode="fixed" duration="8s"></ef-timegroup>
|
|
582
|
-
<ef-timegroup id="child3" mode="fixed" duration="3s"></ef-timegroup>
|
|
583
|
-
</ef-timegroup>`,
|
|
584
|
-
);
|
|
585
|
-
|
|
586
|
-
// Initial duration should be max of children (8s)
|
|
587
|
-
assert.equal(timegroup.durationMs, 8_000);
|
|
588
|
-
assert.equal(timegroup.childTemporals.length, 3);
|
|
589
|
-
|
|
590
|
-
// Remove the longest duration child
|
|
591
|
-
const child2 = timegroup.querySelector("#child2");
|
|
592
|
-
child2?.remove();
|
|
593
|
-
|
|
594
|
-
// Wait for slot change event to process
|
|
595
|
-
await timegroup.updateComplete;
|
|
596
|
-
|
|
597
|
-
// Duration should now be max of remaining children (5s)
|
|
598
|
-
assert.equal(timegroup.durationMs, 5_000);
|
|
599
|
-
assert.equal(timegroup.childTemporals.length, 2);
|
|
600
|
-
});
|
|
601
|
-
|
|
602
|
-
describe("frameTask", () => {
|
|
603
|
-
test("executes all nested frame tasks", async () => {
|
|
604
|
-
const timegroup = renderTimegroup(
|
|
605
|
-
html`<ef-timegroup mode="sequence">
|
|
606
|
-
<test-frame-task-a duration="1s"></test-frame-task-a>
|
|
607
|
-
<div>
|
|
608
|
-
<test-frame-task-b duration="1s">
|
|
609
|
-
<test-frame-task-c duration="1s"></test-frame-task-c>
|
|
610
|
-
</test-frame-task-b>
|
|
611
|
-
</div>
|
|
612
|
-
</ef-timegroup>`,
|
|
613
|
-
);
|
|
614
|
-
const frameTaskA = timegroup.querySelector("test-frame-task-a")!;
|
|
615
|
-
const frameTaskB = timegroup.querySelector("test-frame-task-b")!;
|
|
616
|
-
const frameTaskC = timegroup.querySelector("test-frame-task-c")!;
|
|
617
|
-
|
|
618
|
-
// Following the initial update, frame tasks may run during initialization
|
|
619
|
-
await timegroup.updateComplete;
|
|
620
|
-
|
|
621
|
-
// frameTaskB should never run (not visible at time 0ms in sequence)
|
|
622
|
-
assert.equal(frameTaskB.frameTaskCount, 0);
|
|
623
|
-
|
|
624
|
-
// Then we run them manually.
|
|
625
|
-
await timegroup.frameTask.run();
|
|
626
|
-
|
|
627
|
-
// At timeline time 0ms:
|
|
628
|
-
// - frameTaskA (0-1000ms) should have run (visible)
|
|
629
|
-
// - frameTaskB (1000-2000ms) should NOT run (not visible at time 0)
|
|
630
|
-
// - frameTaskC (0-1000ms) should have run (inherits root positioning, visible)
|
|
631
|
-
|
|
632
|
-
// Verify visible tasks have run at least once
|
|
633
|
-
assert.ok(frameTaskA.frameTaskCount > 0, "frameTaskA should have run");
|
|
634
|
-
assert.ok(frameTaskC.frameTaskCount > 0, "frameTaskC should have run");
|
|
635
|
-
// Verify non-visible task has never run
|
|
636
|
-
assert.equal(frameTaskB.frameTaskCount, 0); // Not visible at time 0
|
|
637
|
-
});
|
|
638
|
-
});
|
|
639
|
-
|
|
640
|
-
describe("seekTask", () => {
|
|
641
|
-
test("does not execute if not the root timegroup", async () => {
|
|
642
|
-
const timegroup = renderTimegroup(
|
|
643
|
-
html`<ef-timegroup mode="sequence">
|
|
644
|
-
<ef-timegroup mode="fixed" duration="3s">
|
|
645
|
-
<test-frame-task-a></test-frame-task-a>
|
|
646
|
-
</ef-timegroup>
|
|
647
|
-
</ef-timegroup>`,
|
|
648
|
-
);
|
|
649
|
-
const nonRootTimegroup = timegroup.querySelector("ef-timegroup")!;
|
|
650
|
-
const frameTaskA = timegroup.querySelector("test-frame-task-a")!;
|
|
651
|
-
await timegroup.updateComplete;
|
|
652
|
-
assert.equal(frameTaskA.frameTaskCount, 1);
|
|
653
|
-
await nonRootTimegroup.seekTask.run();
|
|
654
|
-
assert.equal(frameTaskA.frameTaskCount, 1);
|
|
655
|
-
});
|
|
656
|
-
|
|
657
|
-
test("waits for media durations", async () => {
|
|
658
|
-
const timegroup = renderTimegroup(
|
|
659
|
-
html`
|
|
660
|
-
<ef-preview>
|
|
661
|
-
<ef-timegroup mode="sequence">
|
|
662
|
-
<timegroup-test-media></timegroup-test-media>
|
|
663
|
-
</ef-timegroup>
|
|
664
|
-
</ef-preview>`,
|
|
665
|
-
);
|
|
666
|
-
const media = timegroup.querySelector("timegroup-test-media")!;
|
|
667
|
-
assert.equal(media.mediaEngineTaskCount, 0);
|
|
668
|
-
await timegroup.seekTask.run();
|
|
669
|
-
assert.equal(media.mediaEngineTaskCount, 1);
|
|
670
|
-
});
|
|
671
|
-
});
|
|
672
|
-
|
|
673
|
-
describe("custom frame tasks", () => {
|
|
674
|
-
test("executes registered callback on frame update", async () => {
|
|
675
|
-
const timegroup = renderTimegroup(
|
|
676
|
-
html`<ef-timegroup mode="fixed" duration="5s"></ef-timegroup>`,
|
|
677
|
-
);
|
|
678
|
-
|
|
679
|
-
let callbackExecuted = false;
|
|
680
|
-
const callback = () => {
|
|
681
|
-
callbackExecuted = true;
|
|
682
|
-
};
|
|
683
|
-
|
|
684
|
-
timegroup.addFrameTask(callback);
|
|
685
|
-
await timegroup.seek(1000);
|
|
686
|
-
|
|
687
|
-
assert.equal(callbackExecuted, true);
|
|
688
|
-
}, 1000);
|
|
689
|
-
|
|
690
|
-
test("callback receives correct timing information", async () => {
|
|
691
|
-
const timegroup = renderTimegroup(
|
|
692
|
-
html`<ef-timegroup mode="fixed" duration="5000ms"></ef-timegroup>`,
|
|
693
|
-
);
|
|
694
|
-
|
|
695
|
-
let receivedInfo: any = null;
|
|
696
|
-
const callback = (info: any) => {
|
|
697
|
-
receivedInfo = info;
|
|
698
|
-
};
|
|
699
|
-
|
|
700
|
-
timegroup.addFrameTask(callback);
|
|
701
|
-
await timegroup.seek(2000);
|
|
702
|
-
|
|
703
|
-
assert.equal(receivedInfo.ownCurrentTimeMs, 2000);
|
|
704
|
-
assert.equal(receivedInfo.currentTimeMs, 2000);
|
|
705
|
-
assert.equal(receivedInfo.durationMs, 5000);
|
|
706
|
-
assert.equal(receivedInfo.percentComplete, 0.4);
|
|
707
|
-
assert.equal(receivedInfo.element, timegroup);
|
|
708
|
-
}, 1000);
|
|
709
|
-
|
|
710
|
-
test("executes multiple callbacks in parallel", async () => {
|
|
711
|
-
const timegroup = renderTimegroup(
|
|
712
|
-
html`<ef-timegroup mode="fixed" duration="5s"></ef-timegroup>`,
|
|
713
|
-
);
|
|
714
|
-
|
|
715
|
-
let callback1Executed = false;
|
|
716
|
-
let callback2Executed = false;
|
|
717
|
-
let callback3Executed = false;
|
|
718
|
-
|
|
719
|
-
timegroup.addFrameTask(() => {
|
|
720
|
-
callback1Executed = true;
|
|
721
|
-
});
|
|
722
|
-
timegroup.addFrameTask(() => {
|
|
723
|
-
callback2Executed = true;
|
|
724
|
-
});
|
|
725
|
-
timegroup.addFrameTask(() => {
|
|
726
|
-
callback3Executed = true;
|
|
727
|
-
});
|
|
728
|
-
|
|
729
|
-
await timegroup.seek(1000);
|
|
730
|
-
|
|
731
|
-
assert.equal(callback1Executed, true);
|
|
732
|
-
assert.equal(callback2Executed, true);
|
|
733
|
-
assert.equal(callback3Executed, true);
|
|
734
|
-
}, 1000);
|
|
735
|
-
|
|
736
|
-
test("async callbacks block frame pipeline", async () => {
|
|
737
|
-
const timegroup = renderTimegroup(
|
|
738
|
-
html`<ef-timegroup mode="fixed" duration="5s"></ef-timegroup>`,
|
|
739
|
-
);
|
|
740
|
-
|
|
741
|
-
let asyncCallbackCompleted = false;
|
|
742
|
-
const executionOrder: string[] = [];
|
|
743
|
-
|
|
744
|
-
const asyncCallback = async () => {
|
|
745
|
-
executionOrder.push("async-start");
|
|
746
|
-
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
747
|
-
asyncCallbackCompleted = true;
|
|
748
|
-
executionOrder.push("async-end");
|
|
749
|
-
};
|
|
750
|
-
|
|
751
|
-
timegroup.addFrameTask(asyncCallback);
|
|
752
|
-
|
|
753
|
-
const seekPromise = timegroup.seek(1000);
|
|
754
|
-
executionOrder.push("seek-called");
|
|
755
|
-
|
|
756
|
-
await seekPromise;
|
|
757
|
-
executionOrder.push("seek-complete");
|
|
758
|
-
|
|
759
|
-
assert.equal(asyncCallbackCompleted, true);
|
|
760
|
-
assert.deepEqual(executionOrder, [
|
|
761
|
-
"seek-called",
|
|
762
|
-
"async-start",
|
|
763
|
-
"async-end",
|
|
764
|
-
"seek-complete",
|
|
765
|
-
]);
|
|
766
|
-
}, 1000);
|
|
767
|
-
|
|
768
|
-
test("cleanup function removes callback", async () => {
|
|
769
|
-
const timegroup = renderTimegroup(
|
|
770
|
-
html`<ef-timegroup mode="fixed" duration="5s"></ef-timegroup>`,
|
|
771
|
-
);
|
|
772
|
-
|
|
773
|
-
let callbackExecutionCount = 0;
|
|
774
|
-
const cleanup = timegroup.addFrameTask(() => {
|
|
775
|
-
callbackExecutionCount++;
|
|
776
|
-
});
|
|
777
|
-
|
|
778
|
-
await timegroup.seek(1000);
|
|
779
|
-
assert.equal(callbackExecutionCount, 1);
|
|
780
|
-
|
|
781
|
-
cleanup();
|
|
782
|
-
await timegroup.seek(2000);
|
|
783
|
-
assert.equal(callbackExecutionCount, 1);
|
|
784
|
-
}, 1000);
|
|
785
|
-
|
|
786
|
-
test("removeFrameTask removes callback", async () => {
|
|
787
|
-
const timegroup = renderTimegroup(
|
|
788
|
-
html`<ef-timegroup mode="fixed" duration="5s"></ef-timegroup>`,
|
|
789
|
-
);
|
|
790
|
-
|
|
791
|
-
let callbackExecutionCount = 0;
|
|
792
|
-
const callback = () => {
|
|
793
|
-
callbackExecutionCount++;
|
|
794
|
-
};
|
|
795
|
-
|
|
796
|
-
timegroup.addFrameTask(callback);
|
|
797
|
-
await timegroup.seek(1000);
|
|
798
|
-
assert.equal(callbackExecutionCount, 1);
|
|
799
|
-
|
|
800
|
-
timegroup.removeFrameTask(callback);
|
|
801
|
-
await timegroup.seek(2000);
|
|
802
|
-
assert.equal(callbackExecutionCount, 1);
|
|
803
|
-
}, 1000);
|
|
804
|
-
|
|
805
|
-
test("addFrameTask throws error for non-function", () => {
|
|
806
|
-
const timegroup = renderTimegroup(
|
|
807
|
-
html`<ef-timegroup mode="fixed" duration="5s"></ef-timegroup>`,
|
|
808
|
-
);
|
|
809
|
-
|
|
810
|
-
assert.throws(() => {
|
|
811
|
-
timegroup.addFrameTask("not a function" as any);
|
|
812
|
-
}, "Frame task callback must be a function");
|
|
813
|
-
}, 1000);
|
|
814
|
-
|
|
815
|
-
test("custom frame tasks persist after disconnect and reconnect", async () => {
|
|
816
|
-
const container = document.createElement("div");
|
|
817
|
-
document.body.appendChild(container);
|
|
818
|
-
|
|
819
|
-
const timegroup = document.createElement("ef-timegroup") as EFTimegroup;
|
|
820
|
-
timegroup.setAttribute("mode", "fixed");
|
|
821
|
-
timegroup.setAttribute("duration", "5s");
|
|
822
|
-
container.appendChild(timegroup);
|
|
823
|
-
|
|
824
|
-
let callbackWorkedAfterReconnect = false;
|
|
825
|
-
const callback = () => {
|
|
826
|
-
callbackWorkedAfterReconnect = true;
|
|
827
|
-
};
|
|
828
|
-
|
|
829
|
-
timegroup.addFrameTask(callback);
|
|
830
|
-
|
|
831
|
-
// Disconnect and reconnect
|
|
832
|
-
container.removeChild(timegroup);
|
|
833
|
-
callbackWorkedAfterReconnect = false; // Reset after disconnect
|
|
834
|
-
container.appendChild(timegroup);
|
|
835
|
-
|
|
836
|
-
// Callback should still work after reconnect
|
|
837
|
-
await timegroup.seek(2000);
|
|
838
|
-
assert.equal(
|
|
839
|
-
callbackWorkedAfterReconnect,
|
|
840
|
-
true,
|
|
841
|
-
"Callback should still work after reconnect",
|
|
842
|
-
);
|
|
843
|
-
|
|
844
|
-
container.remove();
|
|
845
|
-
}, 1000);
|
|
846
|
-
|
|
847
|
-
test("sync and async callbacks execute together", async () => {
|
|
848
|
-
const timegroup = renderTimegroup(
|
|
849
|
-
html`<ef-timegroup mode="fixed" duration="5s"></ef-timegroup>`,
|
|
850
|
-
);
|
|
851
|
-
|
|
852
|
-
let syncExecuted = false;
|
|
853
|
-
let asyncExecuted = false;
|
|
854
|
-
|
|
855
|
-
timegroup.addFrameTask(() => {
|
|
856
|
-
syncExecuted = true;
|
|
857
|
-
});
|
|
858
|
-
|
|
859
|
-
timegroup.addFrameTask(async () => {
|
|
860
|
-
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
861
|
-
asyncExecuted = true;
|
|
862
|
-
});
|
|
863
|
-
|
|
864
|
-
await timegroup.seek(1000);
|
|
865
|
-
|
|
866
|
-
assert.equal(syncExecuted, true);
|
|
867
|
-
assert.equal(asyncExecuted, true);
|
|
868
|
-
}, 1000);
|
|
869
|
-
|
|
870
|
-
test("executes callbacks when currentTime is loaded from localStorage", async () => {
|
|
871
|
-
const timegroupId = "localStorage-frame-task-test";
|
|
872
|
-
const storageKey = `ef-timegroup-${timegroupId}`;
|
|
873
|
-
|
|
874
|
-
localStorage.setItem(storageKey, "2.5");
|
|
875
|
-
|
|
876
|
-
const container = document.createElement("div");
|
|
877
|
-
document.body.appendChild(container);
|
|
878
|
-
|
|
879
|
-
const timegroup = document.createElement("ef-timegroup") as EFTimegroup;
|
|
880
|
-
timegroup.setAttribute("id", timegroupId);
|
|
881
|
-
timegroup.setAttribute("mode", "fixed");
|
|
882
|
-
timegroup.setAttribute("duration", "5s");
|
|
883
|
-
|
|
884
|
-
let callbackExecutionCount = 0;
|
|
885
|
-
const receivedTimes: number[] = [];
|
|
886
|
-
|
|
887
|
-
timegroup.addFrameTask((info) => {
|
|
888
|
-
callbackExecutionCount++;
|
|
889
|
-
receivedTimes.push(info.currentTimeMs);
|
|
890
|
-
});
|
|
891
|
-
|
|
892
|
-
container.appendChild(timegroup);
|
|
893
|
-
|
|
894
|
-
await timegroup.updateComplete;
|
|
895
|
-
await timegroup.waitForMediaDurations();
|
|
896
|
-
|
|
897
|
-
await new Promise((resolve) => {
|
|
898
|
-
const checkComplete = async () => {
|
|
899
|
-
if (
|
|
900
|
-
timegroup.currentTime === 2.5 &&
|
|
901
|
-
receivedTimes[receivedTimes.length - 1] === 2500
|
|
902
|
-
) {
|
|
903
|
-
resolve(undefined);
|
|
904
|
-
} else if (timegroup.currentTime === 2.5) {
|
|
905
|
-
await new Promise((r) => setTimeout(r, 10));
|
|
906
|
-
checkComplete();
|
|
907
|
-
} else {
|
|
908
|
-
setTimeout(checkComplete, 10);
|
|
909
|
-
}
|
|
910
|
-
};
|
|
911
|
-
checkComplete();
|
|
912
|
-
});
|
|
913
|
-
|
|
914
|
-
assert.equal(
|
|
915
|
-
timegroup.currentTime,
|
|
916
|
-
2.5,
|
|
917
|
-
"Timegroup should have loaded time from localStorage",
|
|
918
|
-
);
|
|
919
|
-
assert.isAtLeast(
|
|
920
|
-
callbackExecutionCount,
|
|
921
|
-
1,
|
|
922
|
-
"Frame callback should be executed at least once",
|
|
923
|
-
);
|
|
924
|
-
assert.equal(
|
|
925
|
-
receivedTimes[receivedTimes.length - 1],
|
|
926
|
-
2500,
|
|
927
|
-
`Last callback execution should receive the time loaded from localStorage. Got: ${receivedTimes.join(", ")}`,
|
|
928
|
-
);
|
|
929
|
-
|
|
930
|
-
container.remove();
|
|
931
|
-
localStorage.removeItem(storageKey);
|
|
932
|
-
}, 1000);
|
|
933
|
-
});
|
|
934
|
-
});
|