Skip to content
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions examples/test/gltf-model-error/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>glTF Model</title>
<meta name="description" content="glTF Model - A-Frame">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it's misleading the test examples are not actually tests but simple examples that test very specific features. For this we should probably write a unit test

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK - I will have a go at a Unit Test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unit Tests now added.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we leave this in as well, or do you prefer me to delete it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would remove this so examples/test is consistent. It serves the purpose to test visually specific features. Your unit test handles the failure case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK - removed it.

<script src="../../../dist/aframe-master.js"></script>
</head>
<body>
<a-scene stats>
<a-assets>
<a-asset-item id="cityModel" src="invalid-file-name"></a-asset-item>
</a-assets>

<a-entity gltf-model="#cityModel"></a-entity>
</a-scene>
</body>
</html>
18 changes: 12 additions & 6 deletions src/core/a-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
var utils = require('../utils/');

var warn = utils.debug('core:a-node:warn');
var error = utils.debug('core:a-node:error');

var knownTags = {
'a-scene': true,
Expand Down Expand Up @@ -123,20 +122,27 @@ class ANode extends HTMLElement {
// Wait for children to load (if any), then load.
children = this.getChildren();
childrenLoaded = children.filter(childFilter).map(function (child) {
return new Promise(function waitForLoaded (resolve) {
return new Promise(function waitForLoaded (resolve, reject) {
if (child.hasLoaded) { return resolve(); }
child.addEventListener('loaded', resolve);
child.addEventListener('error', reject);
});
});

Promise.all(childrenLoaded).then(function emitLoaded () {
Promise.allSettled(childrenLoaded).then(function emitLoaded (results) {
results.forEach(function checkResultForError (result) {
if (result.status === 'rejected') {
// An "error" event has already been fired by THREE.js loader,
// so we don't need to fire another one.
// A warning explaining the consequences of the error is sufficient.
warn('Rendering scene with errors on node: ', result.reason.target);
}
});

self.hasLoaded = true;
if (cb) { cb(); }
self.setupMutationObserver();

self.emit('loaded', undefined, false);
}).catch(function (err) {
error('Failure loading node: ', err);
});
}

Expand Down
46 changes: 46 additions & 0 deletions tests/core/a-assets.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,24 @@ suite('a-assets', function () {
THREE.Cache.files = {};
});

test('loads even if one asset fails to load', function (done) {
var el = this.el;
var scene = this.scene;
var assetItem = document.createElement('a-asset-item');
assetItem.setAttribute('src', 'invalid-filename');
assetItem.addEventListener('error', function (evt) {
assert.ok(evt.detail.xhr !== undefined);
// Stop propagation of the event so it doesn't trigger
// mocha unhandled exception logic.
evt.stopPropagation();
});
scene.addEventListener('loaded', function () {
done();
});
el.appendChild(assetItem);
document.body.appendChild(scene);
});

test('throws error if not in a-scene', function () {
var div = document.createElement('div');
var assets = document.createElement('a-assets');
Expand Down Expand Up @@ -235,6 +253,7 @@ suite('a-asset-item', function () {
});

test('emits progress event', function (done) {
THREE.Cache.remove(XHR_SRC);
var assetItem = document.createElement('a-asset-item');
assetItem.setAttribute('src', XHR_SRC);
assetItem.addEventListener('progress', function (evt) {
Expand Down Expand Up @@ -262,6 +281,33 @@ suite('a-asset-item', function () {
document.body.appendChild(this.sceneEl);
});

test('waits for valid assets to load, even when some assets are invalid', function (done) {
var scene = this.sceneEl;
var assetItem1 = document.createElement('a-asset-item');
assetItem1.setAttribute('src', 'doesntexist');
var assetItem2 = document.createElement('a-asset-item');
assetItem2.setAttribute('src', XHR_SRC);

// Remove cache data to not load from it.
THREE.Cache.remove(XHR_SRC);

assetItem1.addEventListener('error', function (evt) {
assert.ok(evt.detail.xhr !== undefined);
evt.stopPropagation();
});
// To pass the test, we must get the 'loaded' event on asset 2 first,
// and only then on the scene.
assetItem2.addEventListener('loaded', function () {
scene.addEventListener('loaded', function () {
done();
});
});

this.assetsEl.appendChild(assetItem1);
this.assetsEl.appendChild(assetItem2);
document.body.appendChild(this.sceneEl);
});

test('loads as text without responseType attribute', function (done) {
var assetItem = document.createElement('a-asset-item');
// Remove cache data to not load from it.
Expand Down
4 changes: 4 additions & 0 deletions tests/core/scene/a-scene.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,10 @@ suite('a-scene (without renderer)', function () {

// mock canvas
sceneEl.canvas = {
classList: {
add: function () {},
remove: function () {}
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@diarmidmackenzie now that #5176 is merged, you should remove first those 4 lines and then merge changes from master to fix the conflict.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course - sorry, didn't immediately register the implications of your comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those updates are done.

addEventListener: function () {},
removeEventListener: function () {},
requestFullscreen: function () {}
Expand Down