summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/largest-contentful-paint/image-upscaling.html
blob: a4f7d8079d3b9a75f79b896743cbc018cc81c9ce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
<!DOCTYPE HTML>
<meta charset=utf-8>
<title>Largest Contentful Paint: largest image is reported.</title>
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/largest-contentful-paint-helpers.js"></script>
<script src="/common/utils.js"></script>
<script>
    setup(() =>
        assert_implements(window.LargestContentfulPaint, "LargestContentfulPaint is not implemented"));

    const imageURL = `${window.location.origin}/images/blue.png`;
    async function load_image_and_get_lcp_size(t, imageStyle = {}, containerStyle = {}) {
        const popup = window.open('about:blank');
        t.add_cleanup(() => popup.close());
        const image = popup.document.createElement('img');
        image.src = imageURL;

        // We decode the image to get the natural size (though it's a constant)
        await image.decode();
        const naturalSize = image.width * image.height;

        const container = popup.document.createElement('div');
        container.appendChild(image);
        const applyStyle = (el, style = {}) =>
            Object.entries(style).forEach(([k, v]) => el.style.setProperty(k, v));

        applyStyle(image, imageStyle);
        applyStyle(container, containerStyle);
        image.id = token();
        const entryReported = new Promise(resolve => new popup.PerformanceObserver(entryList => {
            entryList.getEntries().forEach(entry => {
                if (entry.id === image.id)
                    resolve(entry.size);
            });
        }).observe({type: 'largest-contentful-paint'}));
        popup.document.body.appendChild(container);
        const timeout = new Promise(resolve => t.step_timeout(() => resolve('not reported'), 1000));
        return {lcpSize: (await Promise.any([entryReported, timeout])), naturalSize};
    }

    // We set the image to display: none when testing background, so that only the background is reported
    // and not the image itself
    const load_background_image_and_get_lcp_size = (t, style) =>
        load_image_and_get_lcp_size(t, {display: 'none'},
            {
                position: 'absolute',
                'background-image': `url(${imageURL})`,
                ...style,
            });

    promise_test(async t => {
        const {naturalSize, lcpSize} = await load_image_and_get_lcp_size(t);
        assert_equals(lcpSize, naturalSize);
    }, 'Non-scaled image should report the natural size');

    promise_test(async t => {
        const {naturalSize, lcpSize} = await load_image_and_get_lcp_size(t, {width: '50px', height: '50px'});
        assert_equals(lcpSize, 50 * 50);
    }, 'A downscaled image (width/height) should report the displayed size');

    promise_test(async t => {
        const {naturalSize, lcpSize} = await load_image_and_get_lcp_size(t, {transform: 'scale(0.5)'});
        assert_equals(Math.floor(lcpSize), Math.floor(naturalSize / 4));
    }, 'A downscaled image (using scale) should report the displayed size');

    promise_test(async t => {
        const {naturalSize, lcpSize} = await load_image_and_get_lcp_size(t, {width: '500px', height: '500px'});
        assert_equals(lcpSize, naturalSize);
    }, 'An upscaled image (width/height) should report the natural size');

    promise_test(async t => {
        const {naturalSize, lcpSize} = await load_image_and_get_lcp_size(t, {transform: 'scale(2)'});
        assert_equals(Math.floor(lcpSize), Math.floor(naturalSize));
    }, 'An upscaled image (using scale) should report the natural size');

    promise_test(async t => {
        const {naturalSize, lcpSize} = await load_image_and_get_lcp_size(t, {'object-size': '300px 300px'});
        assert_equals(Math.floor(lcpSize), Math.floor(naturalSize));
    }, 'An upscaled image (using object-size) should report the natural size');

    promise_test(async t => {
        const {naturalSize, lcpSize} = await load_image_and_get_lcp_size(t, {'object-position': '-100px 0'});
        assert_equals(lcpSize, 3498);
    }, 'An intersecting element with a partial-intersecting image (object-position) should report the image intersection');

    promise_test(async t => {
        const {naturalSize, lcpSize} = await load_background_image_and_get_lcp_size(t, {width: '50px', height: '50px'});
        assert_equals(lcpSize, 50 * 50);
    }, 'A background image larger than the container should report the container size');

    promise_test(async t => {
        const {naturalSize, lcpSize} = await load_background_image_and_get_lcp_size(t, {width: '300px', height: '300px'});
        assert_equals(lcpSize, naturalSize);
    }, 'A background image smaller than the container should report the natural size');

    promise_test(async t => {
        const {naturalSize, lcpSize} = await load_background_image_and_get_lcp_size(t, {width: '300px', height: '300px', 'background-size': '10px 10x'});
        assert_equals(lcpSize, 100);
    }, 'A scaled-down background image should report the background size');
</script>
</body>