// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import { assert } from 'chai';
import sinon from 'sinon';
import * as Platform from '../../core/platform/platform.js';
import * as SDK from '../../core/sdk/sdk.js';
import * as IssuesManager from '../../models/issues_manager/issues_manager.js';
import * as Logs from '../../models/logs/logs.js';
import { renderElementIntoDOM } from '../../testing/DOMHelpers.js';
import { describeWithMockConnection } from '../../testing/MockConnection.js';
import { createViewFunctionStub } from '../../testing/ViewFunctionHelpers.js';
import * as Components from '../../ui/legacy/components/utils/utils.js';
import * as UI from '../../ui/legacy/legacy.js';
import * as Console from './console.js';
const { urlString } = Platform.DevToolsPath;
function createMessage(level, text, url) {
    const message = new SDK.ConsoleModel.ConsoleMessage(null, "javascript" /* Protocol.Log.LogEntrySource.Javascript */, level, text, { url });
    return new Console.ConsoleViewMessage.ConsoleViewMessage(message, sinon.createStubInstance(Components.Linkifier.Linkifier), sinon.createStubInstance(Logs.RequestResolver.RequestResolver), sinon.createStubInstance(IssuesManager.IssueResolver.IssueResolver), () => { });
}
function addMessage(sidebar, level, text, url) {
    const consoleViewMessage = createMessage(level, text, url);
    sidebar.onMessageAdded(consoleViewMessage);
    return consoleViewMessage;
}
async function getGroups(view) {
    const input = await view.nextInput;
    return Object.fromEntries(input.groups.map(group => [group.name, {
            count: group.messageCount,
            urls: Object.fromEntries(group.urlGroups.entries().map(([title, { count }]) => ([title, count])))
        }]));
}
describeWithMockConnection('ConsoleSidebar', () => {
    it('groups logs by URL', async () => {
        const view = createViewFunctionStub(Console.ConsoleSidebar.ConsoleSidebar);
        const sidebar = new Console.ConsoleSidebar.ConsoleSidebar(undefined, view);
        addMessage(sidebar, "info" /* Protocol.Log.LogEntryLevel.Info */, 'message 1', urlString `https://www.example.com/a.html`);
        addMessage(sidebar, "info" /* Protocol.Log.LogEntryLevel.Info */, 'message 2', urlString `https://www.example.com/b.html`);
        addMessage(sidebar, "info" /* Protocol.Log.LogEntryLevel.Info */, 'message 3', urlString `https://www.example.com/a.html`);
        assert.deepEqual(await getGroups(view), {
            error: { count: 0, urls: {} },
            info: {
                count: 3,
                urls: {
                    'https://www.example.com/a.html': 2,
                    'https://www.example.com/b.html': 1,
                }
            },
            message: {
                count: 3,
                urls: {
                    'https://www.example.com/a.html': 2,
                    'https://www.example.com/b.html': 1,
                }
            },
            'user message': { count: 0, urls: {} },
            verbose: { count: 0, urls: {} },
            warning: { count: 0, urls: {} },
        });
    });
    it('groups logs by level', async () => {
        const view = createViewFunctionStub(Console.ConsoleSidebar.ConsoleSidebar);
        const sidebar = new Console.ConsoleSidebar.ConsoleSidebar(undefined, view);
        addMessage(sidebar, "verbose" /* Protocol.Log.LogEntryLevel.Verbose */, 'message 1', urlString `https://www.example.com/a.html`);
        addMessage(sidebar, "error" /* Protocol.Log.LogEntryLevel.Error */, 'message 2', urlString `https://www.example.com/b.html`);
        addMessage(sidebar, "error" /* Protocol.Log.LogEntryLevel.Error */, 'message 3', urlString `https://www.example.com/a.html`);
        assert.deepEqual(await getGroups(view), {
            error: { count: 2, urls: { 'https://www.example.com/a.html': 1, 'https://www.example.com/b.html': 1 } },
            info: { count: 0, urls: {} },
            message: { count: 3, urls: { 'https://www.example.com/a.html': 2, 'https://www.example.com/b.html': 1 } },
            'user message': { count: 0, urls: {} },
            verbose: { count: 1, urls: { 'https://www.example.com/a.html': 1 } },
            warning: { count: 0, urls: {} }
        });
    });
    it('filters by groups', async () => {
        const view = createViewFunctionStub(Console.ConsoleSidebar.ConsoleSidebar);
        const sidebar = new Console.ConsoleSidebar.ConsoleSidebar(undefined, view);
        const messages = [
            addMessage(sidebar, "verbose" /* Protocol.Log.LogEntryLevel.Verbose */, 'message 1', urlString `https://www.example.com/a.html`),
            addMessage(sidebar, "error" /* Protocol.Log.LogEntryLevel.Error */, 'message 2', urlString `https://www.example.com/b.html`),
            addMessage(sidebar, "error" /* Protocol.Log.LogEntryLevel.Error */, 'message 3', urlString `https://www.example.com/a.html`),
        ];
        const input = await view.nextInput;
        const filter = input.groups.find(group => group.name === 'error')?.filter;
        assert.exists(filter);
        const filterSelected = sinon.stub();
        sidebar.addEventListener("FilterSelected" /* Console.ConsoleSidebar.Events.FILTER_SELECTED */, filterSelected);
        input.onSelectionChanged(filter);
        sinon.assert.calledOnce(filterSelected);
        assert.deepEqual(messages.map(message => sidebar.shouldBeVisible(message)), [false, true, true]);
    });
    it('applies filters on selection', async () => {
        const onSelectionChanged = sinon.stub();
        const groups = [
            new Console.ConsoleSidebar.ConsoleFilterGroup("message" /* Console.ConsoleSidebar.GroupName.ALL */, [], Console.ConsoleFilter.ConsoleFilter.allLevelsFilterValue()),
            new Console.ConsoleSidebar.ConsoleFilterGroup("error" /* Console.ConsoleSidebar.GroupName.ERROR */, [], Console.ConsoleFilter.ConsoleFilter.singleLevelMask("error" /* Protocol.Log.LogEntryLevel.Error */)),
        ];
        groups[1].onMessage(createMessage("error" /* Protocol.Log.LogEntryLevel.Error */, 'message 1', urlString `https://www.example.com/a.html`));
        groups[1].onMessage(createMessage("error" /* Protocol.Log.LogEntryLevel.Error */, 'message 2', urlString `https://www.example.com/b.html`));
        groups[1].onMessage(createMessage("error" /* Protocol.Log.LogEntryLevel.Error */, 'message 3', urlString `https://www.example.com/a.html`));
        const input = {
            groups,
            selectedFilter: groups[0].filter,
            onSelectionChanged,
        };
        const container = renderElementIntoDOM(document.createElement('div'));
        Console.ConsoleSidebar.DEFAULT_VIEW(input, {}, container);
        // Wait for mutation observer to fire
        await new Promise(r => setTimeout(r));
        onSelectionChanged.resetHistory();
        const treeShadow = container.querySelector('devtools-tree')?.shadowRoot;
        assert.exists(treeShadow);
        const treeNode = treeShadow.querySelectorAll('li').values().find(e => e.innerText.includes('a.html'));
        assert.exists(treeNode);
        const treeElement = UI.TreeOutline.TreeElement.getTreeElementBylistItemNode(treeNode);
        assert.exists(treeElement);
        treeElement.select();
        const expectedFilter = groups[1].urlGroups.get('https://www.example.com/a.html')?.filter;
        assert.exists(expectedFilter);
        sinon.assert.calledOnceWithExactly(onSelectionChanged, expectedFilter);
    });
    it('allows clearing messages', async () => {
        const view = createViewFunctionStub(Console.ConsoleSidebar.ConsoleSidebar);
        const sidebar = new Console.ConsoleSidebar.ConsoleSidebar(undefined, view);
        addMessage(sidebar, "verbose" /* Protocol.Log.LogEntryLevel.Verbose */, 'message 1', urlString `https://www.example.com/a.html`);
        assert.deepEqual(await getGroups(view), {
            error: { count: 0, urls: {} },
            info: { count: 0, urls: {} },
            message: { count: 1, urls: { 'https://www.example.com/a.html': 1 } },
            'user message': { count: 0, urls: {} },
            verbose: { count: 1, urls: { 'https://www.example.com/a.html': 1 } },
            warning: { count: 0, urls: {} }
        });
        sidebar.clear();
        assert.deepEqual(await getGroups(view), {
            error: { count: 0, urls: {} },
            info: { count: 0, urls: {} },
            message: { count: 0, urls: {} },
            'user message': { count: 0, urls: {} },
            verbose: { count: 0, urls: {} },
            warning: { count: 0, urls: {} }
        });
    });
});
//# sourceMappingURL=ConsoleSidebar.test.js.map