blob: 2cbd555e2738397b3a5cd98aaaa9298e06ada29f [file] [log] [blame] [edit]
<!DOCTYPE html>
<meta charset="utf-8">
<title>&lt;model> state transitions</title>
<script src="../resources/testharness.js"></script>
<script src="../resources/testharnessreport.js"></script>
<script src="resources/model-element-test-utils.js"></script>
<script src="resources/model-utils.js"></script>
<style>
.spacer {
height: 200vh;
}
.model-element {
width: 300px;
height: 300px;
}
</style>
<body>
<div class="spacer"></div>
<script>
'use strict';
promise_test(async t => {
const [model, source] = createModelAndSource(t, "resources/heart.usdz");
model.className = "model-element";
assert_equals(internals.modelElementState(model), "Deferred");
assert_false(internals.isModelElementIntersectingViewport(model));
scrollElementIntoView(model);
await waitForModelState(model, "Loaded");
assert_true(internals.isModelElementIntersectingViewport(model));
window.scrollTo(0, 0)
await waitForModelState(model, "Unloaded");
assert_false(internals.isModelElementIntersectingViewport(model));
}, `<model> main load/unload transitions`);
promise_test(async t => {
const [model, source] = createModelAndSource(t, "resources/heart.usdz");
model.className = "model-element";
assert_equals(internals.modelElementState(model), "Deferred");
assert_false(internals.isModelElementIntersectingViewport(model));
scrollElementIntoView(model);
const intermediateState = internals.modelElementState(model);
assert_true(intermediateState !== "Loaded");
window.scrollTo(0, 0)
await waitForModelState(model, "Deferred");
assert_false(internals.isModelElementIntersectingViewport(model));
}, `<model> jump back to deferred when quickly scrolled through`);
promise_test(async t => {
const [model, source] = createModelAndSource(t, "resources/does-not-exist.usdz");
model.className = "model-element";
assert_equals(internals.modelElementState(model), "Deferred");
assert_false(internals.isModelElementIntersectingViewport(model));
scrollElementIntoView(model);
await sleepForSeconds(2.0);
const failedState = internals.modelElementState(model);
assert_true(failedState !== "Loading" && failedState !== "Loaded", "Model should not be loaded");
assert_true(internals.isModelElementIntersectingViewport(model));
return model.ready.then(
value => assert_unreached("Unexpected ready promise resolution."),
reason => assert_true(reason.toString().includes("NetworkError"), "The ready promise is rejected with a NetworkError.")
);
}, `<model> invalid state if usdz does not exist`);
promise_test(async t => {
const [model, source] = createModelAndSource(t, "resources/error-case.usdz");
model.className = "model-element";
assert_equals(internals.modelElementState(model), "Deferred");
assert_false(internals.isModelElementIntersectingViewport(model));
scrollElementIntoView(model);
await sleepForSeconds(2.0);
const failedState = internals.modelElementState(model);
assert_true(failedState !== "Loaded", "Model should not be loaded");
assert_true(internals.isModelElementIntersectingViewport(model));
return model.ready.then(
value => assert_unreached("Unexpected ready promise resolution."),
reason => assert_true(reason.toString().includes("AbortError"), "The ready promise is rejected with an AbortError.")
);
}, `<model> invalid state for incorrect usdz file`);
promise_test(async t => {
const [model, source] = createModelAndSource(t, "resources/heart.usdz");
model.className = "model-element";
assert_equals(internals.modelElementState(model), "Deferred");
assert_false(internals.isModelElementIntersectingViewport(model));
scrollElementIntoView(model);
await model.ready;
source.src = "resources/cube.usdz";
await model.ready;
}, `<model> reload visible model after source change`);
promise_test(async t => {
const [model, source] = createModelAndSource(t, "resources/heart.usdz");
model.className = "model-element";
model.setAttribute("stage-mode", "orbit");
scrollElementIntoView(model);
await waitForModelState(model, "Loaded");
assert_true(internals.isModelElementIntersectingViewport(model), "first load viewport check");
await sleepForSeconds(0.5); // make sure entityTransform is synced
const firstLoadTransform = model.entityTransform;
assert_not_equals(firstLoadTransform, null, "entityTransform should not be null after first load");
window.scrollTo(0, 0);
await waitForModelState(model, "Unloaded");
assert_false(internals.isModelElementIntersectingViewport(model), "first unload viewport check");
scrollElementIntoView(model);
await waitForModelState(model, "Loaded");
assert_true(internals.isModelElementIntersectingViewport(model), "second load viewport check");
await sleepForSeconds(0.5); // make sure entityTransform is synced
const secondLoadTransform = model.entityTransform;
assert_not_equals(secondLoadTransform, null, "entityTransform should not be null after second load");
assert_equals(firstLoadTransform.toString(), secondLoadTransform.toString(), "entityTransform should be preserved after second load");
window.scrollTo(0, 0);
await waitForModelState(model, "Unloaded");
assert_false(internals.isModelElementIntersectingViewport(model), "second unload viewport check");
scrollElementIntoView(model);
await waitForModelState(model, "Loaded");
assert_true(internals.isModelElementIntersectingViewport(model), "third load viewport check");
await sleepForSeconds(0.5); // make sure entityTransform is synced
const thirdLoadTransform = model.entityTransform;
assert_not_equals(thirdLoadTransform, null, "entityTransform should not be null after third load");
assert_equals(firstLoadTransform.toString(), thirdLoadTransform.toString(), "entityTransform should be preserved after third load");
}, `<model> stage-mode orbit survives multiple unload-reload cycles`);
</script>
</body>