blob: b5bc721b78c07d36d077118b73bec2f9f396683f [file] [edit]
<!DOCTYPE html> <!-- webkit-test-runner [ ModelElementEnabled=true ] -->
<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", 10000);
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);
const reason = await model.ready.then(
value => assert_unreached("Unexpected ready promise resolution."),
).catch(e => e);
assert_true(reason.toString().includes("AbortError"), "The ready promise is rejected with an AbortError.");
const failedState = internals.modelElementState(model);
assert_true(failedState !== "Loaded", `Model should not be loaded after failure, got: ${failedState}`);
}, `<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");
const firstLoadTransform = await waitForEntityTransform(model);
assert_not_equals(firstLoadTransform, null, "entityTransform should not be null after first load");
window.scrollTo(0, 0);
await waitForModelState(model, "Unloaded", 10000);
assert_false(internals.isModelElementIntersectingViewport(model), "first unload viewport check");
scrollElementIntoView(model);
await waitForModelState(model, "Loaded");
assert_true(internals.isModelElementIntersectingViewport(model), "second load viewport check");
const secondLoadTransform = await waitForEntityTransform(model);
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", 10000);
assert_false(internals.isModelElementIntersectingViewport(model), "second unload viewport check");
scrollElementIntoView(model);
await waitForModelState(model, "Loaded");
assert_true(internals.isModelElementIntersectingViewport(model), "third load viewport check");
const thirdLoadTransform = await waitForEntityTransform(model);
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`);
promise_test(async t => {
const [model, source] = createModelAndSource(t, "resources/heart.usdz");
model.className = "model-element";
scrollElementIntoView(model);
await waitForModelState(model, "Loaded");
await model.ready;
const loadedTransform = model.entityTransform.rotate(0, 45, 0).scale(2, 2, 2);
model.entityTransform = loadedTransform;
assert_3d_matrix_equals(model.entityTransform, loadedTransform);
window.scrollTo(0, 0);
await waitForModelState(model, "Unloaded", 10000);
const unloadedTransform = model.entityTransform.translate(0, 0, -10).rotate(0, 30, 0).scale(0.5, 0.5, 0.5);
model.entityTransform = unloadedTransform;
assert_3d_matrix_equals(model.entityTransform, unloadedTransform);
scrollElementIntoView(model);
await waitForModelState(model, "Loaded");
await sleepForSeconds(0.1);
assert_3d_matrix_equals(model.entityTransform, unloadedTransform);
}, `<model> entityTransform can be set while unloaded`);
</script>
</body>