<!DOCTYPE html>
<html>
<head>
<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
<script src="resources/audit-utilities.js"></script>
<script src="resources/sample-resource.js"></script>
<link rel="stylesheet" href="resources/sample-resource.css">
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAAXNSR0IArs4c6QAAABNJREFUCB1j/M/AAEQMDEwgAgQAHxcCAmtAm/sAAAAASUVORK5CYII=">
<script>
function test()
{
    InspectorTest.debug();

    let suite = InspectorTest.Audit.createSuite("Audit.run.Resources");

    function evaluateStringForTest(func, args) {
        return `WebInspectorAudit.Resources.${func}(${Array.isArray(args) ? args.map(JSON.stringify).join(", ") : ""})`;
    }

    const tests = [
        { name: "Audit.run.Resources.getResources", func: "getResources" },
        { name: "Audit.run.Resources.getResourceContent.InvalidId", func: "getResourceContent", args: [-1], shouldError: true, },
    ];

    for (let {name, func, args, shouldError} of tests) {
        suite.addTestCase({
            name,
            async test() {
                async function getContentForResource(resource) {
                    let {result, wasThrown} = await AuditAgent.run(`function() { return JSON.stringify(${evaluateStringForTest("getResourceContent", [resource.id])}); }`);
                    InspectorTest.assert(!wasThrown, "Should not throw an exception");
                    return JSON.parse(result.value);
                }

                let functionString = evaluateStringForTest(func, args);

                await InspectorTest.Audit.setupAudit();

                InspectorTest.log(`Audit run \`${functionString}\`...`);
                let {result, wasThrown} = await AuditAgent.run(`function() { return JSON.stringify(${functionString}); }`);

                if (shouldError)
                    InspectorTest.expectThat(wasThrown, "Should throw an exception.");
                else
                    InspectorTest.assert(!wasThrown, "Should not throw an exception.");

                if (!wasThrown) {
                    let resources = JSON.parse(result.value);

                    resources.sort((a, b) => a.url.extendedLocaleCompare(b.url));

                    for (let resource of resources) {
                        InspectorTest.assert(resource.id, `All resources should have "id".`);
                        InspectorTest.assert(resource.url, `All resources should have "url".`);
                        InspectorTest.assert(resource.mimeType, `All resources should have "mimeType".`);

                        if (resource.url.endsWith("sample-resource.js")) {
                            InspectorTest.log("Found sample-resource.js.");
                            InspectorTest.assert(resource.mimeType === "text/javascript", "sample-resource.js should have a text/javascript MIME type.");

                            let content = await getContentForResource(resource);
                            InspectorTest.expectEqual(content.data, "/* TEST JS */", "sample-resource.js should have the expected content.");
                            InspectorTest.expectFalse(content.base64Encoded, "sample-resource.js should not be base64 encoded.");
                        }

                        if (resource.url.endsWith("sample-resource.css")) {
                            InspectorTest.log("Found sample-resource.css.");
                            InspectorTest.assert(resource.mimeType === "text/css", "sample-resource.css should have a text/css MIME type.");

                            let content = await getContentForResource(resource);
                            InspectorTest.expectEqual(content.data, "/* TEST CSS */", "sample-resource.css should have the expected content.");
                            InspectorTest.expectFalse(content.base64Encoded, "sample-resource.css should not be base64 encoded.");
                        }

                        if (resource.url.startsWith("data:image/png;base64")) {
                            InspectorTest.log("Found dataURL image.");
                            InspectorTest.assert(resource.mimeType === "image/png", "dataURL image should have a image/png MIME type.");

                            let content = await getContentForResource(resource);
                            InspectorTest.expectEqual(content.data, "iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAAXNSR0IArs4c6QAAABNJREFUCB1j/M/AAEQMDEwgAgQAHxcCAmtAm/sAAAAASUVORK5CYII=", "dataURL image should have the expected content.");
                            InspectorTest.expectThat(content.base64Encoded, "dataURL image should be base64 encoded.");
                        }
                    }
                } else
                    InspectorTest.log(result.description);

                await InspectorTest.Audit.teardownAudit();
            },
        });
    }

    suite.addTestCase({
        name: "Audit.run.Resources.InvalidCopiedFunctionCall",
        description: "Check that WebInspectorAudit.Resources functions throw an error when called outside of an audit.",
        async test() {
            let functions = new Map;
            for (let test of tests)
                functions.set(test.func, test);

            await InspectorTest.Audit.setupAudit();
            InspectorTest.log(`Copying WebInspectorAudit to window...`);
            let {wasThrown} = await AuditAgent.run(`function() { window.CopiedWebInspectorAudit = WebInspectorAudit; }`);
            InspectorTest.assert(!wasThrown, "Should not throw an exception.");
            await InspectorTest.Audit.teardownAudit();

            for (let {func, args} of functions.values()) {
                InspectorTest.log(`Testing copied ${func}...`);
                await InspectorTest.expectException(async function() {
                    await InspectorTest.evaluateInPage("window.Copied" + evaluateStringForTest(func, args));
                });
            }
        },
    });

    suite.runTestCasesAndFinish();
}
</script>
</head>
<body onload="runTest()">
    <p>Tests for the injected WebInspectorAudit.Resources functions.</p>
</body>
</html>
