<!doctype html>
<html>
<head>
<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
<script src="../debugger/resources/breakpoint-options-utilities.js"></script>
<script src="../debugger/resources/log-active-stack-trace.js"></script>
<script src="resources/event-breakpoint-utilities.js"></script>
<script>

let intervalID = NaN;

function handleWindow_setInterval() {
    repeatClearInterval();

    TestPage.dispatchEventToFrontend("TestPage-setInterval");
}

function handleRepeat() {
}

function trigger_setInterval() {
    intervalID = setInterval(handleWindow_setInterval, 10);
}

function repeatSetInterval() {
    intervalID = setInterval(handleRepeat, 10);
}

function repeatClearInterval() {
    clearInterval(intervalID);
    intervalID = NaN;
}

function test() {
    const eventName = "setInterval";

    let suite = InspectorTest.createAsyncSuite("DOMDebugger.Event.Interval");

    suite.addTestCase({
        name: `DOMDebugger.Event.Interval.AddBreakpoint`,
        description: "Check that the debugger pauses for enabled breakpoints.",
        test(resolve, reject) {
            let paused = false;

            let listener = WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Paused, (event) => {
                paused = true;

                InspectorTest.pass("Should pause before event handler is run.");
                logActiveStackTrace();

                WI.debuggerManager.resume()
                .catch(reject);
            });

            InspectorTest.singleFireEventListener(`TestPage-${eventName}`, (event) => {
                if (!paused) {
                    WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, listener);

                    InspectorTest.fail("Should pause before event handler is run.");
                }

                resolve();
            });

            InspectorTest.EventBreakpoint.createBreakpoint(WI.EventBreakpoint.Type.Interval)
            .then(InspectorTest.EventBreakpoint.awaitEvent("window", eventName))
            .catch(reject);
        },
        teardown: InspectorTest.EventBreakpoint.teardown,
    });

    suite.addTestCase({
        name: `DOMDebugger.Event.Interval.AddDisabledBreakpoint`,
        description: "Check that debugger does not pause for disabled breakpoints.",
        test(resolve, reject) {
            InspectorTest.EventBreakpoint.failOnPause(resolve, reject, WI.DebuggerManager.PauseReason.Interval, eventName, "Should not pause for disabled breakpoint.");

            InspectorTest.EventBreakpoint.createBreakpoint(WI.EventBreakpoint.Type.Interval)
            .then(InspectorTest.EventBreakpoint.disableBreakpoint)
            .then(InspectorTest.EventBreakpoint.awaitEvent("window", eventName))
            .catch(reject);
        },
        teardown: InspectorTest.EventBreakpoint.teardown,
    });

    suite.addTestCase({
        name: `DOMDebugger.Event.Interval.RemoveBreakpoint`,
        description: "Check that debugger does not pause for removed breakpoint.",
        test(resolve, reject) {
            InspectorTest.EventBreakpoint.failOnPause(resolve, reject, WI.DebuggerManager.PauseReason.Interval, eventName, "Should not pause for removed breakpoint.");

            InspectorTest.EventBreakpoint.createBreakpoint(WI.EventBreakpoint.Type.Interval)
            .then(InspectorTest.EventBreakpoint.removeBreakpoint)
            .then(InspectorTest.EventBreakpoint.awaitEvent("window", eventName))
            .catch(reject);
        },
        teardown: InspectorTest.EventBreakpoint.teardown,
    });

    suite.addTestCase({
        name: `DOMDebugger.Event.Interval.RemoveDisabledBreakpoint`,
        description: "Check that a disabled breakpoint can be removed.",
        test(resolve, reject) {
            InspectorTest.EventBreakpoint.failOnPause(resolve, reject, WI.DebuggerManager.PauseReason.Interval, eventName, "Should not pause for removed disabled breakpoint.");

            InspectorTest.EventBreakpoint.createBreakpoint(WI.EventBreakpoint.Type.Interval)
            .then(InspectorTest.EventBreakpoint.disableBreakpoint)
            .then(InspectorTest.EventBreakpoint.removeBreakpoint)
            .then(InspectorTest.EventBreakpoint.awaitEvent("window", eventName))
            .catch(reject);
        },
        teardown: InspectorTest.EventBreakpoint.teardown,
    });

    suite.addTestCase({
        name: `DOMDebugger.Event.Interval.RepeatFireBreakpoint`,
        description: "Check that a single breakpoint pauses multiple times for the same interval.",
        test(resolve, reject) {
            let pauseCount = 0;

            let listener = WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.Paused, (event) => {
                ++pauseCount;

                InspectorTest.pass("Should pause before event handler is run.");
                logActiveStackTrace();

                WI.debuggerManager.resume()
                .catch(reject);

                if (pauseCount >= 2) {
                    WI.debuggerManager.removeEventListener(WI.DebuggerManager.Event.Paused, listener);

                    InspectorTest.evaluateInPage(`repeatClearInterval()`)
                    .then(resolve, reject)
                }
            });

            InspectorTest.EventBreakpoint.createBreakpoint(WI.EventBreakpoint.Type.Interval)
            .then(() => {
                InspectorTest.log("Firing \"setInterval\" on window...");
                return InspectorTest.evaluateInPage(`repeatSetInterval()`);
            })
            .catch(reject);
        },
        teardown: InspectorTest.EventBreakpoint.teardown,
    });

    InspectorTest.BreakpointOptions.addTestCases(suite, {
        createBreakpoint() {
            return InspectorTest.EventBreakpoint.createBreakpoint(WI.EventBreakpoint.Type.Interval, {eventName});
        },
        triggerBreakpoint() {
            return Promise.all([
                InspectorTest.awaitEvent("TestPage-" + eventName),
                InspectorTest.evaluateInPage(`trigger_${eventName}()`),
            ]);
        },
    });

    suite.runTestCasesAndFinish();
}
</script>
</head>
<body onload="runTest()">
    <p>Tests for Event Interval breakpoints.</p>
</body>
</html>
