<!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()
{
    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" || resource.mimeType === "application/javascript", "sample-resource.js should have a valid 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>
