"use strict";
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
Object.defineProperty(exports, "__esModule", { value: true });
const chai_1 = require("chai");
const console_helpers_js_1 = require("../helpers/console-helpers.js");
describe('The Console Tab', () => {
    it('shows BigInts formatted', async ({ devToolsPage, inspectedPage }) => {
        const messages = await (0, console_helpers_js_1.getConsoleMessages)('big-int', false, () => (0, console_helpers_js_1.waitForConsoleMessagesToBeNonEmpty)(5, devToolsPage), devToolsPage, inspectedPage);
        chai_1.assert.deepEqual(messages, [
            '1n',
            'BigInt\xA0{2n}',
            '[1n]',
            '[BigInt]',
            'null 1n BigInt\xA0{2n}',
        ]);
    });
    it('shows uncaught promises', async ({ devToolsPage, inspectedPage }) => {
        const messages = await (0, console_helpers_js_1.getConsoleMessages)('uncaught-promise', false, () => (0, console_helpers_js_1.waitForConsoleMessagesToBeNonEmpty)(2, devToolsPage), devToolsPage, inspectedPage);
        chai_1.assert.deepEqual(messages, [
            `Uncaught (in promise) Error: err1
    at uncaught-promise.html:7:18`,
            `Uncaught (in promise) Error: err2
    at uncaught-promise.html:25:10`,
            `Uncaught (in promise) NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
    at throwDOMException (uncaught-promise.html:40:7)
    at catcher (uncaught-promise.html:33:5)`,
        ]);
    });
    it('shows structured objects', async ({ devToolsPage, inspectedPage }) => {
        const messages = await (0, console_helpers_js_1.getConsoleMessages)('structured-objects', false, () => (0, console_helpers_js_1.waitForConsoleMessagesToBeNonEmpty)(9, devToolsPage), devToolsPage, inspectedPage);
        chai_1.assert.deepEqual(messages, [
            '{}',
            'ƒ Object() { [native code] }',
            '{__defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, __lookupSetter__: ƒ,\xA0…}',
            '{foo: \'foo\'}',
            '{bar: \'bar\'}',
            '[\'test\']',
            '(10)\xA0[\'test\', \'test2\', empty × 2, \'test4\', empty × 5, foo: {…}]',
            '(200)\xA0[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …]',
            '(2)\xA0[1, Array(2)]',
        ]);
    });
    it('escapes and substitutes correctly', async ({ devToolsPage, inspectedPage }) => {
        const messages = await (0, console_helpers_js_1.getConsoleMessages)('escaping', false, () => (0, console_helpers_js_1.waitForConsoleMessagesToBeNonEmpty)(9, devToolsPage), devToolsPage, inspectedPage);
        chai_1.assert.deepEqual(messages, [
            'Test for zero "0" in formatter',
            '% self-escape1 dummy',
            '%s self-escape2 dummy',
            '%ss self-escape3 dummy',
            '%sdummy%s self-escape4',
            '%%% self-escape5 dummy',
            '%dummy self-escape6',
            '(2)\xA0[\'test\', \'test2\']',
            'Array(2)',
        ]);
    });
    it('shows built-in objects', async ({ devToolsPage, inspectedPage }) => {
        const messages = await (0, console_helpers_js_1.getConsoleMessages)('built-ins', false, () => (0, console_helpers_js_1.waitForConsoleMessagesToBeNonEmpty)(29, devToolsPage), devToolsPage, inspectedPage);
        chai_1.assert.deepEqual(messages, [
            '/^url\\(\\s*(?:(?:\"(?:[^\\\\\\\"]|(?:\\\\[\\da-f]{1,6}\\s?|\\.))*\"|\'(?:[^\\\\\\\']|(?:\\\\[\\da-f]{1,6}\\s?|\\.))*\')|(?:[!#$%&*-~\\w]|(?:\\\\[\\da-f]{1,6}\\s?|\\.))*)\\s*\\)/i',
            '/foo\\\\bar\\sbaz/i',
            'Error\n    at built-ins.html:13:17',
            'Error: My error message\n    at built-ins.html:16:28',
            'Error: my multiline\nerror message\n    at built-ins.html:19:37',
            'ƒ () { return 1; }',
            'ƒ () {\n    return 2;\n  }',
            'ƒ ( /**/ foo/**/, /*/**/bar,\n  /**/baz) {}',
            'Arguments(2)\xA0[1, \'2\', callee: (...), Symbol(Symbol.iterator): ƒ]',
            'Uint8Array\xA0[3, buffer: ArrayBuffer(1), byteLength: 1, byteOffset: 0, length: 1, Symbol(Symbol.toStringTag): \'Uint8Array\']',
            'Uint8Array(400)\xA0[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …]',
            'Uint8Array(400000000)\xA0[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, …]',
            'Uint16Array(3)\xA0[1, 2, 3, buffer: ArrayBuffer(6), byteLength: 6, byteOffset: 0, length: 3, Symbol(Symbol.toStringTag): \'Uint16Array\']',
            'Promise\xA0{<rejected>: -0}',
            'Promise\xA0{<fulfilled>: 1}',
            'Promise\xA0{<pending>}',
            'Symbol()',
            'Symbol(a)',
            '{a: Symbol(), Symbol(a): 2}',
            'Map(1)\xA0{{…} => {…}}',
            'WeakMap\xA0{{…} => {…}}',
            'Set(1)\xA0{{…}}',
            'WeakSet\xA0{{…}}',
            'Map(1)\xA0{Map(1) => WeakMap}',
            'Map(1)\xA0{Map(0) => WeakMap}',
            'Set(1)\xA0{WeakSet}',
            'Set(1)\xA0{WeakSet}',
            'Map(6)\xA0{\' from str \' => \' to str \', undefined => undefined, null => null, 42 => 42, {…} => {…}, …}',
            'genFunction\xA0{<suspended>}',
        ]);
    });
    it('shows primitives', async ({ devToolsPage, inspectedPage }) => {
        const messages = await (0, console_helpers_js_1.getConsoleMessages)('primitives', false, () => (0, console_helpers_js_1.waitForConsoleMessagesToBeNonEmpty)(15, devToolsPage), devToolsPage, inspectedPage);
        chai_1.assert.deepEqual(messages, [
            'null',
            'undefined',
            'NaN',
            '{}',
            '[ƒ]',
            '[\'test\']',
            'Infinity',
            '-Infinity',
            'Number\xA0{42}',
            'String\xA0{\'abc\'}',
            '0.12',
            '-0',
            'test',
            'test named \"test\"',
            'https://chromium.org',
            'Number\xA0{42, 1: \'foo\', a: \'bar\'}',
            'String\xA0{\'abc\', 3: \'foo\', 01: \'foo\', a: \'bar\'}',
        ]);
    });
    it('can handle prototype fields', async ({ devToolsPage, inspectedPage }) => {
        const messages = await (0, console_helpers_js_1.getConsoleMessages)('prototypes', false, () => (0, console_helpers_js_1.waitForConsoleMessagesToBeNonEmpty)(13, devToolsPage), devToolsPage, inspectedPage);
        chai_1.assert.deepEqual(messages, [
            '{enumerableProp: 4, __underscoreEnumerableProp__: 5, __underscoreNonEnumerableProp: 2, abc: 3, getFoo: ƒ,\xA0…}',
            '{longSubNamespace: {…}}',
            'namespace.longSubNamespace.x.className\xA0{}',
            '{}',
            'ArrayLike\xA0{length: 5}',
            'ArrayLike\xA0{length: 4294967295}',
            'ArrayLike\xA0{length: -5}',
            'ArrayLike\xA0{length: 5.6}',
            'ArrayLike\xA0{length: NaN}',
            'ArrayLike\xA0{length: Infinity}',
            'ArrayLike\xA0{length: -0}',
            'ArrayLike\xA0{length: 4294967296}',
            'NonArrayWithLength\xA0{keys: Array(0)}',
        ]);
    });
    it('can show DOM interactions', async ({ devToolsPage, inspectedPage }) => {
        const messages = await (0, console_helpers_js_1.getConsoleMessages)('dom-interactions', undefined, undefined, devToolsPage, inspectedPage);
        try {
            // Note depending on whether we got a remote object or not we have
            // slightly different representations of DOM. Both are correct.
            chai_1.assert.deepEqual(messages, [
                '',
                '',
                '',
                '',
                '#text',
                'HTMLCollection\xA0[select, sel: select]',
                'HTMLCollection\xA0[]',
                'HTMLOptionsCollection(2)\xA0[option, option, selectedIndex: 0]',
                'HTMLAllCollection(12)\xA0[html, head, body, div#first-child.c1.c2.c3, div#p, form, select, option, option, input, input, script, first-child: div#first-child.c1.c2.c3, p: div#p, sel: select, input: HTMLCollection(2)]',
                'HTMLFormControlsCollection(3)\xA0[select, input, input, sel: select, input: RadioNodeList(2)]',
                'RadioNodeList(2)\xA0[input, input, value: \'\']',
                'DOMTokenList(3)\xA0[\'c1\', \'c2\', \'c3\', value: \'c1 c2 c3\']',
                'NotFoundError: Failed to execute \'removeChild\' on \'Node\': The node to be removed is not a child of this node.',
            ]);
        }
        catch {
            chai_1.assert.deepEqual(messages, [
                'div#p',
                'attr',
                'attr',
                'id',
                '#text',
                'HTMLCollection\xA0[select, sel: select]',
                'HTMLCollection\xA0[]',
                'HTMLOptionsCollection(2)\xA0[option, option, selectedIndex: 0]',
                'HTMLAllCollection(12)\xA0[html, head, body, div#first-child.c1.c2.c3, div#p, form, select, option, option, input, input, script, first-child: div#first-child.c1.c2.c3, p: div#p, sel: select, input: HTMLCollection(2)]',
                'HTMLFormControlsCollection(3)\xA0[select, input, input, sel: select, input: RadioNodeList(2)]',
                'RadioNodeList(2)\xA0[input, input, value: \'\']',
                'DOMTokenList(3)\xA0[\'c1\', \'c2\', \'c3\', value: \'c1 c2 c3\']',
                'NotFoundError: Failed to execute \'removeChild\' on \'Node\': The node to be removed is not a child of this node.',
            ]);
        }
    });
    it('can handle sourceURLs in exceptions', async ({ devToolsPage, inspectedPage }) => {
        const messages = await (0, console_helpers_js_1.getConsoleMessages)('source-url-exceptions', false, () => (0, console_helpers_js_1.waitForConsoleMessagesToBeNonEmpty)(1, devToolsPage), devToolsPage, inspectedPage);
        chai_1.assert.deepEqual(messages, [
            `Uncaught ReferenceError: FAIL is not defined
    at foo (foo2.js:1:18)
    at source-url-exceptions.html:9:3`,
        ]);
    });
    it('can handle repeated messages from data URLs in exceptions', async ({ devToolsPage, inspectedPage }) => {
        const messages = await (0, console_helpers_js_1.getConsoleMessages)('data-url-exceptions', false, () => (0, console_helpers_js_1.waitForConsoleMessagesToBeNonEmpty)(1, devToolsPage), devToolsPage, inspectedPage);
        chai_1.assert.deepEqual(messages, [
            'msg', // 5 times from eval script, collapsed
            'msg', // 5 times from data url script, collapsed
            `Uncaught Error: Failed
    at fail (data-url-exceptions.html:12:11)
    at foo1 (data:text/javascript…sgZm9vMSgpOyB9:1:19)
    at foo2 (data:text/javascript…sgZm9vMSgpOyB9:2:20)
    at bar1 (data:text/javascript…ogYmFyMigpOw==:1:19)
    at bar2 (data:text/javascript…ogYmFyMigpOw==:2:20)
    at data:text/javascript…AogYmFyMigpOw==:3:2`,
        ]);
    });
    it('can show stackoverflow exceptions', async ({ devToolsPage, inspectedPage }) => {
        const messages = await (0, console_helpers_js_1.getConsoleMessages)('stack-overflow', false, () => (0, console_helpers_js_1.waitForConsoleMessagesToBeNonEmpty)(1, devToolsPage), devToolsPage, inspectedPage);
        const expectedOld = `Uncaught RangeError: Maximum call stack size exceeded
    at boo (foo2.js:2:2)
    at boo (foo2.js:2:2)
    at boo (foo2.js:2:2)
    at boo (foo2.js:2:2)
    at boo (foo2.js:2:2)
    at boo (foo2.js:2:2)
    at boo (foo2.js:2:2)
    at boo (foo2.js:2:2)
    at boo (foo2.js:2:2)
    at boo (foo2.js:2:2)`;
        const expectedNew = `Uncaught RangeError: Maximum call stack size exceeded
    at boo (foo2.js:1:13)
    at boo (foo2.js:2:2)
    at boo (foo2.js:2:2)
    at boo (foo2.js:2:2)
    at boo (foo2.js:2:2)
    at boo (foo2.js:2:2)
    at boo (foo2.js:2:2)
    at boo (foo2.js:2:2)
    at boo (foo2.js:2:2)
    at boo (foo2.js:2:2)`;
        // V8 behavior changed: the top frame of a stack overflow exception may point to the function entry (line 1)
        // instead of the call site (line 2). We accept both to avoid flakiness across V8 versions.
        chai_1.assert.isTrue(messages[0] === expectedOld || messages[0] === expectedNew, `Expected stack trace to match either old or new format. Actual:\n${messages[0]}`);
    });
    it('can show document.write messages', async ({ devToolsPage, inspectedPage }) => {
        const messages = await (0, console_helpers_js_1.getConsoleMessages)('document-write', false, () => (0, console_helpers_js_1.waitForConsoleMessagesToBeNonEmpty)(2, devToolsPage), devToolsPage, inspectedPage);
        chai_1.assert.deepEqual(messages, [
            'script element',
            'document.write from onload',
        ]);
    });
    it('can show verbose promise unhandledrejections', async ({ devToolsPage, inspectedPage }) => {
        const messages = await (0, console_helpers_js_1.getConsoleMessages)('onunhandledrejection', false, async () => {
            await (0, console_helpers_js_1.waitForConsoleMessagesToBeNonEmpty)(4, devToolsPage);
            await (0, console_helpers_js_1.showVerboseMessages)(devToolsPage);
        }, devToolsPage, inspectedPage);
        chai_1.assert.deepEqual(messages, [
            'onunhandledrejection1',
            'onrejectionhandled1',
            'onunhandledrejection2',
            `Uncaught (in promise) Error: e
    at runSecondPromiseRejection (onunhandledrejection.html:23:44)`,
            'onrejectionhandled2',
        ]);
    });
    describe('shows messages from before', () => {
        it('iframe removal', async ({ devToolsPage, inspectedPage }) => {
            const messages = await (0, console_helpers_js_1.getConsoleMessages)('navigation/after-removal', false, () => (0, console_helpers_js_1.waitForConsoleMessagesToBeNonEmpty)(3, devToolsPage), devToolsPage, inspectedPage);
            chai_1.assert.deepEqual(messages, [
                'A message with first argument string Second argument which should not be discarded',
                '2011 \'A message with first argument integer\'',
                'Window\xA0{window: Window, self: Window, document: document, name: \'\', location: Location,\xA0…} \'A message with first argument window\'',
            ]);
        });
        it('and after iframe navigation', async ({ devToolsPage, inspectedPage }) => {
            const messages = await (0, console_helpers_js_1.getConsoleMessages)('navigation/after-navigation', false, () => (0, console_helpers_js_1.waitForConsoleMessagesToBeNonEmpty)(4, devToolsPage), devToolsPage, inspectedPage);
            chai_1.assert.deepEqual(messages, [
                'A message with first argument string Second argument which should not be discarded',
                '2011 \'A message with first argument integer\'',
                'Window\xA0{window: Window, self: Window, document: document, name: \'\', location: Location,\xA0…} \'A message with first argument window\'',
                'After iframe navigation.',
            ]);
        });
    });
});
//# sourceMappingURL=console-message-format.test.js.map