// (TEST 1) Some miscellaneous tests for FontFaceSet and FontFace.
ok(window.FontFaceSet, "FontFaceSet interface object should be present (TEST 1)");
is(Object.getPrototypeOf(FontFaceSet.prototype), EventTarget.prototype, "FontFaceSet should inherit from EventTarget (TEST 1)");
ok(document.fonts instanceof FontFaceSet, "document.fonts should be a a FontFaceSet (TEST 1)");
ok(window.FontFace, "FontFace interface object should be present (TEST 1)");
is(Object.getPrototypeOf(FontFace.prototype), Object.prototype, "FontFace should inherit from Object (TEST 1)");
// (TEST 2) Some miscellaneous tests for CSSFontFaceLoadEvent.
ok(window.CSSFontFaceLoadEvent, "CSSFontFaceLoadEvent interface object should be present (TEST 2)");
is(Object.getPrototypeOf(CSSFontFaceLoadEvent.prototype), Event.prototype, "CSSFontFaceLoadEvent should inherit from Event (TEST 2)");
}).then(function() {
// (TEST 3) Test that document.fonts.ready starts out resolved with the
// FontFaceSet.
return is_resolved_with(document.fonts.ready, document.fonts, "initial value of document.fonts", "(TEST 3)");
}).then(function() {
// (TEST 4) Test that document.fonts in this test document starts out with no
// FontFace objects in it.
is(Array.from(document.fonts).length, 0, "initial number of FontFace objects in document.fonts (TEST 4)");
// (TEST 5) Test that document.fonts.status starts off as loaded.
is(document.fonts.status, "loaded", "initial value of document.fonts.status (TEST 5)");
// (TEST 6) Test initial value of FontFace.status when a url() source is
// used.
is(new FontFace("test", "url(x)").status, "unloaded", "initial value of FontFace.status when a url() source is used (TEST 6)");
// (TEST 7) Test initial value of FontFace.status when an invalid
// ArrayBuffer source is used.
is(new FontFace("test", new ArrayBuffer(0)).status, "unloaded", "initial value of FontFace.status when an invalid ArrayBuffer source is used (TEST 7)");
// (TEST 8) Test initial value of FontFace.status when a valid ArrayBuffer
// source is used.
is(new FontFace("test", fontData).status, "unloaded", "initial value of FontFace.status when a valid ArrayBuffer source is used (TEST 8)");
// (TEST 9) Test initial value of FontFace.loaded when an invalid url()
// source is used.
return is_pending(new FontFace("test", "").loaded, "initial value of FontFace.loaded when an invalid url() source is used", "(TEST 9)");
}).then(function() {
// (TEST 10) Test initial value of FontFace.loaded when a valid url()
// source is used.
return is_pending(new FontFace("test", "url(x)").loaded, "initial value of FontFace.loaded when a valid url() source is used", "(TEST 10)");
}).then(function() {
// (TEST 11) Test initial value of FontFace.loaded when an invalid
// ArrayBuffer source is used.
return is_pending(new FontFace("test", new ArrayBuffer(0)).loaded, "initial value of FontFace.loaded when an invalid ArrayBuffer source is used", "(TEST 11)");
}).then(function() {
// (TEST 12) Test initial value of FontFace.loaded when a valid ArrayBuffer
// source is used.
return is_pending(new FontFace("test", fontData).loaded, "initial value of FontFace.loaded when a valid ArrayBuffer source is used", "(TEST 12)");
}).then(function() {
// (TEST 13) Test initial values of the descriptor attributes on FontFace
// objects.
var face = new FontFace("test", fontData);
// XXX Spec issue: what values do the descriptor attributes have before the
// constructor's dictionary argument is parsed?
for (var desc in defaultValues) {
is(face[desc], defaultValues[desc], "initial value of FontFace." + desc + " (TEST 13)");
}
// (TEST 14) Test default values of the FontFaceDescriptors dictionary.
return face.loaded.then(function() {
for (var desc in defaultValues) {
is(face[desc], defaultValues[desc], "default value of FontFace." + desc + " (TEST 14)");
}
}, function(aError) {
ok(false, "FontFace should have loaded succesfully (TEST 14)");
});
}).then(function() {
// (TEST 15) Test passing non-default descriptor values to the FontFace
ok_todo(face[aDesc] == nonDefaultValues[aDesc][1], "specified valid non-default value of FontFace." + aDesc + " immediately after construction (TEST 15)");
return face.loaded.then(function() {
ok_todo(face[aDesc] == nonDefaultValues[aDesc][1], "specified valid non-default value of FontFace." + aDesc + " (TEST 15)");
}, function(aError) {
ok(false, "FontFace should have loaded succesfully (TEST 15)");
});
});
});
return descriptorTests;
}).then(function() {
// (TEST 16) Test passing invalid descriptor values to the FontFace
ok(false, "FontFace should not load with invalid url() src " + aSrc + " (TEST 19)");
}, function(aError) {
is(aError.name, "SyntaxError", "FontFace.ready should have been rejected with a SyntaxError when loaded with an invalid url() src " + aSrc + " (TEST 19)");
});
});
});
return srcTests;
}).then(function() {
// (TEST 20) Test that the status of a FontFace constructed with a valid
// ArrayBuffer source eventually becomes "loaded".
var face = new FontFace("test", fontData);
return face.loaded.then(function() {
is(face.status, "loaded", "status of FontFace constructed with a valid ArrayBuffer source should eventually be \"loaded\" (TEST 20)");
}, function(aError) {
ok(false, "FontFace constructed with a valid ArrayBuffer should eventually load (TEST 20)");
});
}).then(function() {
// (TEST 21) Test that the status of a FontFace constructed with an invalid
// ArrayBuffer source eventually becomes "error".
var face = new FontFace("test", new ArrayBuffer(0));
return face.loaded.then(function() {
ok(false, "FontFace constructed with an invalid ArrayBuffer should not load (TEST 21)");
}, function(aError) {
is(aError.name, "SyntaxError", "loaded of FontFace constructed with an invalid ArrayBuffer source should be rejected with TypeError (TEST 21)");
is(face.status, "error", "status of FontFace constructed with an invalid ArrayBuffer source should eventually be \"error\" (TEST 21)");
});
}).then(function() {
// (TEST 22) Test assigning non-default descriptor values on the FontFace.
ok_todo(exceptionName == "SyntaxError", "assigning invalid value to FontFace." + aDesc + " should throw a SyntaxError (TEST 23)");
}, function(aError) {
ok(false, "FontFace should have loaded succesfully (TEST 23)");
});
});
});
return descriptorTests;
}).then(function() {
// (TEST 24) Test that the status of a FontFace with a non-existing url()
// source is set to "loading" right after load() is called, that its .loaded
// Promise is returned, and that the Promise is eventually rejected with a
// NetworkError and its status is set to "error".
var face = new FontFace("test", "url(x)");
var result = face.load();
is(face.status, "loading", "FontFace.status should be \"loading\" right after load() is called (TEST 24)");
is(result, face.loaded, "FontFace.load() should return the .loaded Promise (TEST 24)");
return result.then(function() {
ok(false, "FontFace with a non-existing url() source should not load (TEST 24)");
}, function(aError) {
is(aError.name, "NetworkError", "FontFace with a non-existing url() source should result in its .loaded Promise being rejected with a NetworkError (TEST 24)");
is(face.status, "error", "FontFace with a non-existing url() source should result in its .status being set to \"error\" (TEST 24)");
});
}).then(function() {
// (TEST 25) Test simple manipulation of the FontFaceSet.
var face, face2, all;
face = new FontFace("test", "url(x)");
face2 = new FontFace("test2", "url(x)");
ok(!document.fonts.has(face), "newly created FontFace should not be in document.fonts (TEST 25)");
document.fonts.add(face);
ok(document.fonts.has(face), "should be able to add a FontFace to document.fonts (TEST 25)");
document.fonts.add(face);
ok(document.fonts.has(face), "should be able to repeatedly add a FontFace to document.fonts (TEST 25)");
ok(document.fonts.delete(face), "FontFaceSet.delete should return true when it succeeds (TEST 25)");
ok(!document.fonts.has(face), "FontFace should be gone from document.fonts after delete is called (TEST 25)");
ok(!document.fonts.delete(face), "FontFaceSet.delete should return false when it fails (TEST 25)");
document.fonts.add(face);
document.fonts.add(face2);
ok(document.fonts.has(face2), "should be able to add a second FontFace to document.fonts (TEST 25)");
document.fonts.clear();
ok(!document.fonts.has(face) && !document.fonts.has(face2), "FontFaces should be gone from document.fonts after clear is called (TEST 25)");
document.fonts.add(face);
document.fonts.add(face2);
all = Array.from(document.fonts);
is(all[0], face, "FontFaces should be returned in the same order as insertion (TEST 25)");
is(all[1], face2, "FontFaces should be returned in the same order as insertion (TEST 25)");
document.fonts.add(face);
all = Array.from(document.fonts);
is(all[0], face, "FontFaces should be not be reordered when a duplicate entry is added (TEST 25)");
is(all[1], face2, "FontFaces should be not be reordered when a duplicate entry is added (TEST 25)");
document.fonts.clear();
return document.fonts.read;
}).then(function() {
// (TEST 26) Test that FontFaceSet.ready is replaced, .status is set to
// "loading", and a loading event is dispatched when a loading FontFace is
// added to it.
var awaitEvents = new Promise(function(aResolve, aReject) {
var onloadingTriggered = false, loadingDispatched = false;
ok_todo(face[aDesc] == nonDefaultValues[aDesc][1], "FontFace should have correct " + aDesc + " value (TEST 34)");
});
document.fonts.clear();
ok(document.fonts.has(face), "CSS-connected FontFace should not be removed from document.fonts when clear is called (TEST 34)");
var exceptionName = "";
try {
document.fonts.delete(face);
} catch (ex) {
exceptionName = ex.name;
}
ok(exceptionName == "InvalidModificationError", "attempting to remove CSS-connected FontFace from document.fonts should throw an InvalidModificationError (TEST 34)");
ok(document.fonts.has(face), "CSS-connected FontFace should not be removed from document.fonts when delete is called (TEST 34)");
style.textContent = "";
document.body.offsetTop;
ok(!document.fonts.has(face), "CSS-connected FontFace should be removed from document.fonts once the rule has been removed (TEST 34)");
document.fonts.add(face);
ok(document.fonts.has(face), "previously CSS-connected FontFace should be able to be added to document.fonts (TEST 34)");
document.fonts.delete(face);
ok(!document.fonts.has(face), "previously CSS-connected FontFace should be able to be removed from document.fonts (TEST 34)");
}).then(function() {
// (TEST 34) Test that a pending style sheet load prevents
// document.fonts.status from being set to "loaded".
// First, add a FontFace to document.fonts that will load soon.
var face = new FontFace("test", "url(BitPattern.woff)");
face.load();
document.fonts.add(face);
// Next, add a style sheet reference.
var link = document.createElement("link");
link.rel = "stylesheet";
link.href = "neverending_stylesheet_load.sjs";
link.type = "text/css";
document.head.appendChild(link);
return setTimeoutZero() // wait for the style sheet to start loading
.then(function() {
document.fonts.clear();
is(document.fonts.status, "loading", "FontFaceSet.status when the FontFaceSet has been cleared of loading FontFaces but there is a pending style sheet load (TEST 33)");
document.head.removeChild(link);
// XXX Removing the <link> element won't cancel the load of the
// style sheet, so we can't do that to test that
// document.fonts.ready is resolved once there are no more
// loading style sheets.
});
// NOTE: It is important that this style sheet test comes last in the file,
// as the neverending style sheet load will interfere with subsequent
// sub-tests.
}).then(function() {
// End of the tests.
SimpleTest.finish();
}, function(aError) {
// Something failed.
ok(false, "Something failed: " + aError);
SimpleTest.finish();
});
}
if (SpecialPowers.getBoolPref("layout.css.font-loading-api.enabled")) {