Quelle test_picture_mutations.html
Sprache: HTML
products/Sources/formale Sprachen/C/Firefox/dom/tests/mochitest/general/test_picture_mutations.html
<!
DOCTYPE HTML >
<
html >
<
head >
<
meta charset=
"utf-8" >
<
title >Image srcset mutations</
title >
<
script src=
"/tests/SimpleTest/SimpleTest.js" ></
script >
<
link rel=
"stylesheet" type=
"text/css" href=
"/tests/SimpleTest/test.css" />
</
head >
<
body >
<
script type=
"application/javascript" >
"use strict" ;
// Tests the relevant mutations part of the spec for <
img > inside <picture> tags
//
https:// style='color:red'>html .spec.whatwg.org/#relevant-mutations
SimpleTest.waitForExplicitFinish();
// 50x50 png
var testPNG50 = new URL("image_50.png" , location).href;
// 100x100 png
var testPNG100 = new URL("image_100.png" , location).href;
// 200x200 png
var testPNG200 = new URL("image_200.png" , location).href;
var tests = [];
var img ;
var picture;
var source1;
var source2;
var source3;
var expectingErrors = 0;
var expectingLoads = 0;
var afterExpectCallback;
function onImgLoad() {
ok(expectingLoads > 0, "expected load" );
if (expectingLoads > 0) {
expectingLoads--;
}
if (!expectingLoads && !expectingErrors) {
setTimeout(afterExpectCallback, 0);
}
}
function onImgError() {
ok(expectingErrors > 0, "expected error" );
if (expectingErrors > 0) {
expectingErrors--;
}
if (!expectingLoads && !expectingErrors) {
setTimeout(afterExpectCallback, 0);
}
}
function expectEvents(loads, errors, callback) {
if (!loads && !errors) {
setTimeout(callback, 0);
} else {
expectingLoads += loads;
expectingErrors += errors;
info("Waiting for " + expectingLoads + " load and " + expectingErrors + " error events" );
afterExpectCallback = callback;
}
}
// Setup image outside the tree dom, make sure it loads
tests.push(function() {
info("test 1" );
img .srcset = testPNG100;
img .src = testPNG50;
is(img .currentSrc, '' , "Should not have synchronously selected source" );
// No events should have fired synchronously, now we should get just one load (and no 404 error)
expectEvents(1, 0, nextTest);
});
// Binding to an empty picture should trigger an event, even if source doesn't change
tests.push(function() {
info("test 2" );
is(img .currentSrc, testPNG100, "Should have loaded testPNG100" );
document.body .appendChild(picture);
picture.appendChild(img );
is(img .currentSrc, testPNG100, "Should still have testPNG100" );
expectEvents(1, 0, nextTest);
});
// inserting and removing an empty source before the image should both trigger a no-op reload
tests.push(function() {
info("test 3" );
is(img .currentSrc, testPNG100, "Should still have testPNG100" );
picture.insertBefore(source1, img );
is(img .currentSrc, testPNG100, "Should still have testPNG100" );
// should fire one event, not change source
expectEvents(1, 0, function() {
is(img .currentSrc, testPNG100, "Should still have testPNG100" );
picture.removeChild(source1);
is(img .currentSrc, testPNG100, "Should still have testPNG100" );
// Should also no-op fire
expectEvents(1, 0, nextTest);
});
});
// insert and remove valid source before
tests.push(function() {
info("test 4" );
is(img .currentSrc, testPNG100, "Should still have testPNG100" );
// Insert source1 before img with valid candidate
source1.srcset = testPNG50;
picture.insertBefore(source1, img );
is(img .currentSrc, testPNG100, "Should still have testPNG100" );
// should fire one event, change to the source
expectEvents(1, 0, function() {
is(img .currentSrc, testPNG50, "Should have switched to testPNG50" );
picture.removeChild(source1);
is(img .currentSrc, testPNG50, "Should still have testPNG50" );
// Should also no-op fire
expectEvents(1, 0, function() {
is(img .currentSrc, testPNG100, "Should have returned to testPNG100" );
nextTest();
});
});
});
// insert and remove valid source after
tests.push(function() {
info("test 5" );
is(img .currentSrc, testPNG100, "Should still have testPNG100" );
// Insert source1 before img with valid candidate
source1.srcset = testPNG50;
picture.appendChild(source1);
is(img .currentSrc, testPNG100, "Should still have testPNG100" );
// should fire nothing, no action
expectEvents(0, 0, function() {
is(img .currentSrc, testPNG100, "Should still have testPNG100" );
// Same with removing
picture.removeChild(source1);
expectEvents(0, 0, function() {
is(img .currentSrc, testPNG100, "Should still have testPNG100" );
nextTest();
});
});
});
// Should re-consider earlier sources when a load event occurs.
tests.push(function() {
info("test 6" );
// Insert two valid sources, with MQ causing us to select the second
source1.srcset = testPNG50 + " 1x" ;
source1.media = "(min-resolution: 2dppx)" ; // Wont match, test starts at 1x
source2.srcset = testPNG200;
picture.insertBefore(source1, img );
picture.insertBefore(source2, img );
is(img .currentSrc, testPNG100, "Should still have testPNG100" );
// should get one load, selecting source2
expectEvents(1, 0, function() {
is(img .currentSrc, testPNG200, "Should have selected testPNG200" );
expectEvents(1, 0, function() {
is(img .currentSrc, testPNG50, "Should have switched to testPNG50" );
// Now add a source *also* wanting that DPI *just before* the
// selected source . Properly re-running the algorithm should
// re-consider all sources and thus go back to the first
// source , not just the valid source just inserted before us.
source3.media = source1.media;
source3.srcset = testPNG100;
picture.insertBefore(source3, source2);
// This should trigger a reload, but we should re-consider
// source1 and remain with that, not just the newly added source2
expectEvents(1, 0, function() {
is(img .currentSrc, testPNG50, "Should have remained on testPNG50" );
expectEvents(0, 0, nextTest);
});
});
// Switch DPI to match the first source .
SpecialPowers.pushPrefEnv({'set' : [ ["layout.css.devPixelsPerPx" , "2.0" ] ] });
});
});
// insert and remove valid source after our current source should
// trigger a reload, but not switch source
tests.push(function() {
info("test 7" );
// Should be using source1 from last test
is(img .currentSrc, testPNG50, "Should still have testPNG50" );
// Remove source2, should trigger an event even though we would
// not switch
picture.removeChild(source2);
expectEvents(1, 0, function() {
is(img .currentSrc, testPNG50, "Should still have testPNG50" );
// Same with re-adding
picture.insertBefore(source2, img );
expectEvents(1, 0, function() {
is(img .currentSrc, testPNG50, "Should still have testPNG50" );
expectEvents(0, 0, nextTest);
});
});
});
// Changing source attributes should trigger updates
tests.push(function() {
info("test 8" );
// Should be using source1 from last test
is(img .currentSrc, testPNG50, "Should still have testPNG50" );
// Reconfigure source1 to have empty srcset. Should switch to
// next source due to becoming invalid.
source1.srcset = "" ;
is(img .currentSrc, testPNG50, "Should still have testPNG50" );
expectEvents(1, 0, function() {
is(img .currentSrc, testPNG100, "Should have switched to testPNG100" );
// Give source1 valid sizes. Should trigger an event but not switch anywhere.
source1.sizes = "100vw" ;
expectEvents(1, 0, function() {
is(img .currentSrc, testPNG100, "Should still have testPNG100" );
// And a valid MQ
source1.media = "(min-resolution: 1dppx)" ;
expectEvents(1, 0, function() {
// And a valid type...
source1.type = "image/png" ;
expectEvents(1, 0, function() {
// Finally restore srcset, should trigger load and re-consider source1 which is valid again
source1.srcset = testPNG50;
expectEvents(1, 0, function() {
is(img .currentSrc, testPNG50, "Should have selected testPNG50" );
expectEvents(0, 0, nextTest);
});
});
});
});
});
});
// Inserting a source after <img > and touching its attributes should all be no-ops
tests.push(function() {
info("test 9" );
// Setup: source2
picture.removeChild(source2);
expectEvents(1, 0, function() {
is(img .currentSrc, testPNG50, "Should still have testPNG50" );
source2.srcset = testPNG200;
source2.media = "" ;
source2.sizes = "100vw" ;
source2.type = "image/png" ;
// Append valid source
picture.appendChild(source2);
// Touch all the things (but keep it valid)
source2.srcset = testPNG100;
source2.media = "(min-resolution: 2dppx)" ;
source2.sizes = "50vw" ;
source2.type = "image/png" ;
// No event should fire. Source should not change.
expectEvents(0, 0, function() {
is(img .currentSrc, testPNG50, "Should still have testPNG50" );
expectEvents(0, 0, nextTest);
});
});
});
function nextTest() {
if (tests.length) {
// Spin event loop to make sure no unexpected image events are
// pending (unexpected events will assert in the handlers)
setTimeout(function() {
(tests.shift())();
}, 0);
} else {
// We'll get a flood of load events due to prefs being popped while cleaning up.
// Ignore it all.
img .removeEventListener("load" , onImgLoad);
img .removeEventListener("error" , onImgError);
SimpleTest.finish();
}
}
addEventListener("load" , function() {
SpecialPowers.pushPrefEnv({'set' : [["layout.css.devPixelsPerPx" , "1.0" ]] },
function() {
// Create these after the pref is set, as it is guarding webIDL attributes
img = document.createElement("img" );
img .addEventListener("load" , onImgLoad);
img .addEventListener("error" , onImgError);
picture = document.createElement("picture" );
source1 = document.createElement("source" );
source2 = document.createElement("source" );
source3 = document.createElement("source" );
setTimeout(nextTest, 0);
});
});
</script >
</body >
</html >
Messung V0.5 in Prozent C=100 H=100 G=100
¤ Dauer der Verarbeitung: 0.14 Sekunden
(vorverarbeitet am 2026-04-25)
¤
*© Formatika GbR, Deutschland
2026-05-26