// Copyright 2022 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 Host from '../../../core/host/host.js';
import * as Platform from '../../../core/platform/platform.js';
import { dispatchCopyEvent, dispatchInputEvent, dispatchKeyDownEvent, dispatchPasteEvent, getCleanTextContentFromElements, renderElementIntoDOM, } from '../../../testing/DOMHelpers.js';
import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js';
import * as RenderCoordinator from '../../../ui/components/render_coordinator/render_coordinator.js';
import * as NetworkComponents from './components.js';
async function renderHeaderSectionRow(header) {
    const component = new NetworkComponents.HeaderSectionRow.HeaderSectionRow();
    const scrollIntoViewSpy = sinon.spy(component, 'scrollIntoView');
    renderElementIntoDOM(component);
    sinon.assert.notCalled(scrollIntoViewSpy);
    component.data = { header };
    await RenderCoordinator.done();
    assert.isNotNull(component.shadowRoot);
    let nameEditable = null;
    const nameEditableComponent = component.shadowRoot.querySelector('.header-name devtools-editable-span');
    if (nameEditableComponent) {
        assert.instanceOf(nameEditableComponent, HTMLElement);
        assert.isNotNull(nameEditableComponent.shadowRoot);
        nameEditable = nameEditableComponent.shadowRoot.querySelector('.editable');
        assert.instanceOf(nameEditable, HTMLSpanElement);
    }
    let valueEditable = null;
    const valueEditableComponent = component.shadowRoot.querySelector('.header-value devtools-editable-span');
    if (valueEditableComponent) {
        assert.instanceOf(valueEditableComponent, HTMLElement);
        assert.isNotNull(valueEditableComponent.shadowRoot);
        valueEditable = valueEditableComponent.shadowRoot.querySelector('.editable');
        assert.instanceOf(valueEditable, HTMLSpanElement);
    }
    return { component, nameEditable, valueEditable, scrollIntoViewSpy };
}
const hasReloadPrompt = (shadowRoot) => {
    return Boolean(shadowRoot.querySelector('devtools-icon[title="Refresh the page/request for these changes to take effect"]'));
};
describeWithEnvironment('HeaderSectionRow', () => {
    it('emits UMA event when a header value is being copied', async () => {
        const headerData = {
            name: Platform.StringUtilities.toLowerCaseString('some-header-name'),
            value: 'someHeaderValue',
            valueEditable: 0 /* NetworkComponents.HeaderSectionRow.EditingAllowedStatus.DISABLED */,
        };
        const { component, scrollIntoViewSpy } = await renderHeaderSectionRow(headerData);
        assert.isNotNull(component.shadowRoot);
        sinon.assert.notCalled(scrollIntoViewSpy);
        const spy = sinon.spy(Host.userMetrics, 'actionTaken');
        const headerValue = component.shadowRoot.querySelector('.header-value');
        assert.instanceOf(headerValue, HTMLElement);
        sinon.assert.notCalled(spy);
        dispatchCopyEvent(headerValue);
        sinon.assert.calledWith(spy, Host.UserMetrics.Action.NetworkPanelCopyValue);
    });
    it('renders detailed reason for blocked requests', async () => {
        const headerData = {
            name: Platform.StringUtilities.toLowerCaseString('cross-origin-resource-policy'),
            value: null,
            valueEditable: 0 /* NetworkComponents.HeaderSectionRow.EditingAllowedStatus.DISABLED */,
            headerNotSet: true,
            blockedDetails: {
                explanation: () => 'To use this resource from a different origin, the server needs to specify a cross-origin resource policy in the response headers:',
                examples: [
                    {
                        codeSnippet: 'Cross-Origin-Resource-Policy: same-site',
                        comment: () => 'Choose this option if the resource and the document are served from the same site.',
                    },
                    {
                        codeSnippet: 'Cross-Origin-Resource-Policy: cross-origin',
                        comment: () => 'Only choose this option if an arbitrary website including this resource does not impose a security risk.',
                    },
                ],
                link: { url: 'https://web.dev/coop-coep/' },
            },
        };
        const { component } = await renderHeaderSectionRow(headerData);
        assert.isNotNull(component.shadowRoot);
        const headerName = component.shadowRoot.querySelector('.header-name');
        assert.instanceOf(headerName, HTMLDivElement);
        const regex = /^\s*not-set\s*cross-origin-resource-policy\s*$/;
        assert.isTrue(regex.test(headerName.textContent || ''));
        const headerValue = component.shadowRoot.querySelector('.header-value');
        assert.instanceOf(headerValue, HTMLDivElement);
        assert.strictEqual(headerValue.textContent?.trim(), '');
        assert.strictEqual(getCleanTextContentFromElements(component.shadowRoot, '.call-to-action')[0], `To use this resource from a different origin, the server needs to specify a cross-origin resource policy in the response headers:
Cross-Origin-Resource-Policy: same-site Choose this option if the resource and the document are served from the same site.
Cross-Origin-Resource-Policy: cross-origin Only choose this option if an arbitrary website including this resource does not impose a security risk.
Learn more`);
    });
    it('displays decoded "x-client-data"-header', async () => {
        const headerData = {
            name: Platform.StringUtilities.toLowerCaseString('x-client-data'),
            value: 'CJa2yQEIpLbJAQiTocsB',
            valueEditable: 0 /* NetworkComponents.HeaderSectionRow.EditingAllowedStatus.DISABLED */,
        };
        const { component } = await renderHeaderSectionRow(headerData);
        assert.isNotNull(component.shadowRoot);
        const headerName = component.shadowRoot.querySelector('.header-name');
        assert.instanceOf(headerName, HTMLDivElement);
        assert.strictEqual(headerName.textContent?.trim(), 'x-client-data');
        const headerValue = component.shadowRoot.querySelector('.header-value');
        assert.instanceOf(headerValue, HTMLDivElement);
        assert.isTrue(headerValue.classList.contains('flex-columns'));
        assert.isTrue((getCleanTextContentFromElements(component.shadowRoot, '.header-value')[0]).startsWith('CJa2yQEIpLbJAQiTocsB'));
        assert.strictEqual(getCleanTextContentFromElements(component.shadowRoot, '.header-value code')[0], 'message ClientVariations { // Active Google-visible variation IDs on this client. These are reported for analysis, but do not directly affect any server-side behavior. repeated int32 variation_id = [3300118, 3300132, 3330195];\n}');
    });
    it('displays info about blocked "Set-Cookie"-headers', async () => {
        const headerData = {
            name: Platform.StringUtilities.toLowerCaseString('set-cookie'),
            value: 'secure=only; Secure',
            valueEditable: 0 /* NetworkComponents.HeaderSectionRow.EditingAllowedStatus.DISABLED */,
            setCookieBlockedReasons: ["SecureOnly" /* Protocol.Network.SetCookieBlockedReason.SecureOnly */, "OverwriteSecure" /* Protocol.Network.SetCookieBlockedReason.OverwriteSecure */],
        };
        const { component } = await renderHeaderSectionRow(headerData);
        assert.isNotNull(component.shadowRoot);
        const headerName = component.shadowRoot.querySelector('.header-name');
        assert.instanceOf(headerName, HTMLDivElement);
        assert.strictEqual(headerName.textContent?.trim(), 'set-cookie');
        const headerValue = component.shadowRoot.querySelector('.header-value');
        assert.instanceOf(headerValue, HTMLDivElement);
        assert.strictEqual(headerValue.textContent?.trim(), 'secure=only; Secure');
        const icon = component.shadowRoot.querySelector('devtools-icon');
        assert.instanceOf(icon, HTMLElement);
        assert.strictEqual(icon.title, 'This attempt to set a cookie via a Set-Cookie header was blocked because it had the ' +
            '"Secure" attribute but was not received over a secure connection.\nThis attempt to ' +
            'set a cookie via a Set-Cookie header was blocked because it was not sent over a ' +
            'secure connection and would have overwritten a cookie with the Secure attribute.');
    });
    it('can be highlighted', async () => {
        const headerData = {
            name: Platform.StringUtilities.toLowerCaseString('some-header-name'),
            value: 'someHeaderValue',
            valueEditable: 0 /* NetworkComponents.HeaderSectionRow.EditingAllowedStatus.DISABLED */,
            highlight: true,
        };
        const { component, scrollIntoViewSpy } = await renderHeaderSectionRow(headerData);
        assert.isNotNull(component.shadowRoot);
        const headerRowElement = component.shadowRoot.querySelector('.row.header-highlight');
        assert.instanceOf(headerRowElement, HTMLDivElement);
        sinon.assert.calledOnce(scrollIntoViewSpy);
    });
    it('allows editing header name and header value', async () => {
        const originalHeaderName = Platform.StringUtilities.toLowerCaseString('some-header-name');
        const originalHeaderValue = 'someHeaderValue';
        const headerData = {
            name: originalHeaderName,
            value: originalHeaderValue,
            nameEditable: true,
            valueEditable: 1 /* NetworkComponents.HeaderSectionRow.EditingAllowedStatus.ENABLED */,
        };
        const editedHeaderName = 'new-header-name';
        const editedHeaderValue = 'new value for header';
        const { component, nameEditable, valueEditable } = await renderHeaderSectionRow(headerData);
        assert.isNotNull(component.shadowRoot);
        let headerValueFromEvent = '';
        let headerNameFromEvent = '';
        let headerEditedEventCount = 0;
        component.addEventListener('headeredited', event => {
            headerEditedEventCount++;
            headerValueFromEvent = event.headerValue;
            headerNameFromEvent = event.headerName;
        });
        assert.instanceOf(nameEditable, HTMLSpanElement);
        assert.isTrue(hasReloadPrompt(component.shadowRoot));
        nameEditable.focus();
        nameEditable.innerText = editedHeaderName;
        dispatchInputEvent(nameEditable, { inputType: 'insertText', data: editedHeaderName, bubbles: true, composed: true });
        nameEditable.blur();
        await RenderCoordinator.done();
        assert.strictEqual(headerEditedEventCount, 1);
        assert.strictEqual(headerNameFromEvent, editedHeaderName);
        assert.strictEqual(headerValueFromEvent, originalHeaderValue);
        assert.isTrue(hasReloadPrompt(component.shadowRoot));
        assert.instanceOf(valueEditable, HTMLSpanElement);
        valueEditable.focus();
        valueEditable.innerText = editedHeaderValue;
        dispatchInputEvent(valueEditable, { inputType: 'insertText', data: editedHeaderValue, bubbles: true, composed: true });
        valueEditable.blur();
        await RenderCoordinator.done();
        assert.strictEqual(headerEditedEventCount, 2);
        assert.strictEqual(headerNameFromEvent, editedHeaderName);
        assert.strictEqual(headerValueFromEvent, editedHeaderValue);
        assert.isTrue(hasReloadPrompt(component.shadowRoot));
        nameEditable.focus();
        nameEditable.innerText = originalHeaderName;
        dispatchInputEvent(nameEditable, { inputType: 'insertText', data: originalHeaderName, bubbles: true, composed: true });
        nameEditable.blur();
        await RenderCoordinator.done();
        assert.strictEqual(headerEditedEventCount, 3);
        assert.strictEqual(headerNameFromEvent, originalHeaderName);
        assert.strictEqual(headerValueFromEvent, editedHeaderValue);
        assert.isTrue(hasReloadPrompt(component.shadowRoot));
        valueEditable.focus();
        valueEditable.innerText = originalHeaderValue;
        dispatchInputEvent(valueEditable, { inputType: 'insertText', data: originalHeaderValue, bubbles: true, composed: true });
        valueEditable.blur();
        await RenderCoordinator.done();
        assert.strictEqual(headerEditedEventCount, 4);
        assert.strictEqual(headerNameFromEvent, originalHeaderName);
        assert.strictEqual(headerValueFromEvent, originalHeaderValue);
        assert.isTrue(hasReloadPrompt(component.shadowRoot));
    });
    it('does not allow setting an emtpy header name', async () => {
        const headerName = Platform.StringUtilities.toLowerCaseString('some-header-name');
        const headerData = {
            name: headerName,
            value: 'someHeaderValue',
            nameEditable: true,
            valueEditable: 1 /* NetworkComponents.HeaderSectionRow.EditingAllowedStatus.ENABLED */,
        };
        const { component, nameEditable } = await renderHeaderSectionRow(headerData);
        assert.isNotNull(component.shadowRoot);
        let headerEditedEventCount = 0;
        component.addEventListener('headeredited', () => {
            headerEditedEventCount++;
        });
        assert.instanceOf(nameEditable, HTMLElement);
        nameEditable.focus();
        nameEditable.innerText = '';
        nameEditable.blur();
        assert.strictEqual(headerEditedEventCount, 0);
        assert.strictEqual(nameEditable.innerText, 'Some-Header-Name');
    });
    it('resets edited value on escape key', async () => {
        const originalHeaderValue = 'special chars: \'\"\\.,;!?@_-+/=<>()[]{}|*&^%$#§±`~';
        const headerData = {
            name: Platform.StringUtilities.toLowerCaseString('some-header-name'),
            value: originalHeaderValue,
            originalValue: originalHeaderValue,
            valueEditable: 1 /* NetworkComponents.HeaderSectionRow.EditingAllowedStatus.ENABLED */,
        };
        const { component, valueEditable } = await renderHeaderSectionRow(headerData);
        assert.isNotNull(component.shadowRoot);
        let eventCount = 0;
        component.addEventListener('headeredited', () => {
            eventCount++;
        });
        assert.instanceOf(valueEditable, HTMLElement);
        assert.strictEqual(valueEditable.innerText, originalHeaderValue);
        valueEditable.focus();
        valueEditable.innerText = 'new value for header';
        dispatchKeyDownEvent(valueEditable, { key: 'Escape', bubbles: true, composed: true });
        assert.strictEqual(eventCount, 0);
        assert.strictEqual(valueEditable.innerText, originalHeaderValue);
        const row = component.shadowRoot.querySelector('.row');
        assert.isFalse(row?.classList.contains('header-overridden'));
    });
    it('confirms edited value and exits editing mode on "Enter"-key', async () => {
        const headerData = {
            name: Platform.StringUtilities.toLowerCaseString('some-header-name'),
            value: 'someHeaderValue',
            valueEditable: 1 /* NetworkComponents.HeaderSectionRow.EditingAllowedStatus.ENABLED */,
        };
        const editedHeaderValue = 'new value for header';
        const { component, valueEditable } = await renderHeaderSectionRow(headerData);
        assert.isNotNull(component.shadowRoot);
        let headerValueFromEvent = '';
        let eventCount = 0;
        component.addEventListener('headeredited', event => {
            headerValueFromEvent = event.headerValue;
            eventCount++;
        });
        assert.instanceOf(valueEditable, HTMLElement);
        valueEditable.focus();
        valueEditable.innerText = editedHeaderValue;
        dispatchKeyDownEvent(valueEditable, { key: 'Enter', bubbles: true });
        assert.strictEqual(headerValueFromEvent, editedHeaderValue);
        assert.strictEqual(eventCount, 1);
    });
    it('adds and removes `header-overridden` class correctly', async () => {
        const headerData = {
            name: Platform.StringUtilities.toLowerCaseString('some-header-name'),
            value: 'someHeaderValue',
            originalValue: 'someHeaderValue',
            valueEditable: 1 /* NetworkComponents.HeaderSectionRow.EditingAllowedStatus.ENABLED */,
            highlight: true,
        };
        const { component, valueEditable } = await renderHeaderSectionRow(headerData);
        assert.isNotNull(component.shadowRoot);
        assert.instanceOf(valueEditable, HTMLElement);
        const row = component.shadowRoot.querySelector('.row');
        assert.isFalse(row?.classList.contains('header-overridden'));
        assert.isTrue(row?.classList.contains('header-highlight'));
        assert.isFalse(hasReloadPrompt(component.shadowRoot));
        valueEditable.focus();
        valueEditable.innerText = 'a';
        dispatchInputEvent(valueEditable, { inputType: 'insertText', data: 'a', bubbles: true, composed: true });
        await RenderCoordinator.done();
        assert.isTrue(row?.classList.contains('header-overridden'));
        assert.isFalse(row?.classList.contains('header-highlight'));
        assert.isTrue(hasReloadPrompt(component.shadowRoot));
        dispatchKeyDownEvent(valueEditable, { key: 'Escape', bubbles: true, composed: true });
        await RenderCoordinator.done();
        assert.isFalse(component.shadowRoot.querySelector('.row')?.classList.contains('header-overridden'));
    });
    it('adds and removes `header-overridden` class correctly when editing unset headers', async () => {
        const headerData = {
            name: Platform.StringUtilities.toLowerCaseString('some-header-name'),
            value: null,
            originalValue: null,
            valueEditable: 1 /* NetworkComponents.HeaderSectionRow.EditingAllowedStatus.ENABLED */,
        };
        const { component, valueEditable } = await renderHeaderSectionRow(headerData);
        assert.isNotNull(component.shadowRoot);
        assert.instanceOf(valueEditable, HTMLElement);
        const row = component.shadowRoot.querySelector('.row');
        assert.isFalse(row?.classList.contains('header-overridden'));
        valueEditable.focus();
        valueEditable.innerText = 'a';
        dispatchInputEvent(valueEditable, { inputType: 'insertText', data: 'a', bubbles: true, composed: true });
        await RenderCoordinator.done();
        assert.isTrue(row?.classList.contains('header-overridden'));
        dispatchKeyDownEvent(valueEditable, { key: 'Escape', bubbles: true, composed: true });
        await RenderCoordinator.done();
        assert.isFalse(component.shadowRoot.querySelector('.row')?.classList.contains('header-overridden'));
    });
    it('shows error-icon when header name contains disallowed characters', async () => {
        const headerData = {
            name: Platform.StringUtilities.toLowerCaseString('some-header-name'),
            value: 'someHeaderValue',
            originalValue: 'someHeaderValue',
            nameEditable: true,
            valueEditable: 1 /* NetworkComponents.HeaderSectionRow.EditingAllowedStatus.ENABLED */,
        };
        const { component, nameEditable } = await renderHeaderSectionRow(headerData);
        assert.isNotNull(component.shadowRoot);
        assert.instanceOf(nameEditable, HTMLElement);
        const row = component.shadowRoot.querySelector('.row');
        assert.instanceOf(row, HTMLDivElement);
        assert.isNull(row.querySelector('devtools-icon.disallowed-characters'));
        assert.isTrue(hasReloadPrompt(component.shadowRoot));
        nameEditable.focus();
        nameEditable.innerText = '*';
        dispatchInputEvent(nameEditable, { inputType: 'insertText', data: '*', bubbles: true, composed: true });
        await RenderCoordinator.done();
        assert.instanceOf(row.querySelector('devtools-icon.disallowed-characters'), HTMLElement);
        assert.isTrue(hasReloadPrompt(component.shadowRoot));
        dispatchKeyDownEvent(nameEditable, { key: 'Escape', bubbles: true, composed: true });
        await RenderCoordinator.done();
        assert.isNull(row.querySelector('devtools-icon.disallowed-characters'));
        assert.isTrue(hasReloadPrompt(component.shadowRoot));
    });
    it('split header name and value on pasted content', async () => {
        const originalHeaderName = Platform.StringUtilities.toLowerCaseString('some-header-name');
        const originalHeaderValue = 'someHeaderValue';
        const headerData = {
            name: originalHeaderName,
            value: originalHeaderValue,
            nameEditable: true,
            valueEditable: 1 /* NetworkComponents.HeaderSectionRow.EditingAllowedStatus.ENABLED */,
        };
        const editedHeaderName = 'permissions-Policy: unload=(https://xyz.com)';
        const { component, nameEditable, valueEditable } = await renderHeaderSectionRow(headerData);
        assert.isNotNull(component.shadowRoot);
        assert.instanceOf(nameEditable, HTMLElement);
        assert.instanceOf(valueEditable, HTMLElement);
        let headerValueFromEvent = '';
        let headerNameFromEvent = '';
        let headerEditedEventCount = 0;
        component.addEventListener('headeredited', event => {
            headerValueFromEvent = event.headerValue;
            headerNameFromEvent = event.headerName;
            headerEditedEventCount++;
        });
        const dt = new DataTransfer();
        dt.setData('text/plain', editedHeaderName);
        // update name on blur
        nameEditable.focus();
        dispatchPasteEvent(nameEditable, { clipboardData: dt, bubbles: true, composed: true });
        nameEditable.blur();
        await RenderCoordinator.done();
        assert.strictEqual(headerEditedEventCount, 1);
        assert.strictEqual(headerNameFromEvent, 'permissions-policy');
        assert.strictEqual(headerValueFromEvent, 'someHeaderValue');
        // update value on blur
        valueEditable.blur();
        await RenderCoordinator.done();
        assert.strictEqual(headerEditedEventCount, 2);
        assert.strictEqual(headerNameFromEvent, 'permissions-policy');
        assert.strictEqual(headerValueFromEvent, 'unload=(https://xyz.com)');
        // final value on UI
        const nameEl = component.shadowRoot.querySelector('.header-name devtools-editable-span');
        const valueEl = component.shadowRoot.querySelector('.header-value devtools-editable-span');
        assert.strictEqual(nameEl.value, 'Permissions-Policy');
        assert.strictEqual(valueEl.value, 'unload=(https://xyz.com)');
    });
    it('set and revert pasted header name on escape', async () => {
        const originalHeaderName = Platform.StringUtilities.toLowerCaseString('some-header-name');
        const originalHeaderValue = 'someHeaderValue';
        const headerData = {
            name: originalHeaderName,
            value: originalHeaderValue,
            nameEditable: true,
            valueEditable: 1 /* NetworkComponents.HeaderSectionRow.EditingAllowedStatus.ENABLED */,
        };
        const editedHeaderName = ':abc';
        const { component, nameEditable, valueEditable } = await renderHeaderSectionRow(headerData);
        assert.isNotNull(component.shadowRoot);
        assert.instanceOf(nameEditable, HTMLElement);
        assert.instanceOf(valueEditable, HTMLElement);
        let headerEditedEventCount = 0;
        component.addEventListener('headeredited', () => {
            headerEditedEventCount++;
        });
        const dt = new DataTransfer();
        dt.setData('text/plain', editedHeaderName);
        nameEditable.focus();
        dispatchPasteEvent(nameEditable, { clipboardData: dt, bubbles: true, composed: true });
        const nameEl = component.shadowRoot.querySelector('.header-name devtools-editable-span');
        const valueEl = component.shadowRoot.querySelector('.header-value devtools-editable-span');
        await RenderCoordinator.done();
        assert.strictEqual(nameEl.value, ':Abc');
        assert.strictEqual(valueEl.value, originalHeaderValue);
        dispatchKeyDownEvent(nameEditable, { key: 'Escape', bubbles: true, composed: true });
        await RenderCoordinator.done();
        assert.strictEqual(headerEditedEventCount, 0);
        assert.strictEqual(nameEl.value, 'Some-Header-Name');
    });
    it('revert pasted header name and value on escape', async () => {
        const originalHeaderName = Platform.StringUtilities.toLowerCaseString('some-header-name');
        const originalHeaderValue = 'someHeaderValue';
        const headerData = {
            name: originalHeaderName,
            value: originalHeaderValue,
            nameEditable: true,
            valueEditable: 1 /* NetworkComponents.HeaderSectionRow.EditingAllowedStatus.ENABLED */,
        };
        const editedHeaderName = 'permissions-Policy: unload=(https://xyz.com)';
        const { component, nameEditable, valueEditable } = await renderHeaderSectionRow(headerData);
        assert.isNotNull(component.shadowRoot);
        assert.instanceOf(nameEditable, HTMLElement);
        assert.instanceOf(valueEditable, HTMLElement);
        let headerEditedEventCount = 0;
        component.addEventListener('headeredited', () => {
            headerEditedEventCount++;
        });
        const dt = new DataTransfer();
        dt.setData('text/plain', editedHeaderName);
        nameEditable.focus();
        dispatchPasteEvent(nameEditable, { clipboardData: dt, bubbles: true, composed: true });
        const nameEl = component.shadowRoot.querySelector('.header-name devtools-editable-span');
        const valueEl = component.shadowRoot.querySelector('.header-value devtools-editable-span');
        await RenderCoordinator.done();
        assert.strictEqual(nameEl.value, 'Permissions-Policy');
        assert.strictEqual(valueEl.value, 'unload=(https://xyz.com)');
        dispatchKeyDownEvent(valueEditable, { key: 'Escape', bubbles: true, composed: true });
        await RenderCoordinator.done();
        assert.strictEqual(headerEditedEventCount, 0);
        assert.strictEqual(nameEl.value, 'Some-Header-Name');
        assert.strictEqual(valueEl.value, 'someHeaderValue');
    });
    it('recoginzes only alphanumeric characters, dashes, and underscores as valid in header names', () => {
        assert.isTrue(NetworkComponents.HeaderSectionRow.isValidHeaderName('AlphaNumeric123'));
        assert.isFalse(NetworkComponents.HeaderSectionRow.isValidHeaderName('Alpha Numeric'));
        assert.isFalse(NetworkComponents.HeaderSectionRow.isValidHeaderName('AlphaNumeric123!'));
        assert.isTrue(NetworkComponents.HeaderSectionRow.isValidHeaderName('With-dashes_and_underscores'));
        assert.isFalse(NetworkComponents.HeaderSectionRow.isValidHeaderName('no*'));
    });
    it('allows removing a header override', async () => {
        const headerName = Platform.StringUtilities.toLowerCaseString('some-header-name');
        const headerValue = 'someHeaderValue';
        const headerData = {
            name: headerName,
            value: headerValue,
            valueEditable: 1 /* NetworkComponents.HeaderSectionRow.EditingAllowedStatus.ENABLED */,
        };
        const { component } = await renderHeaderSectionRow(headerData);
        assert.isNotNull(component.shadowRoot);
        let headerValueFromEvent = '';
        let headerNameFromEvent = '';
        let headerRemovedEventCount = 0;
        component.addEventListener('headerremoved', event => {
            headerRemovedEventCount++;
            headerValueFromEvent = event.headerValue;
            headerNameFromEvent = event.headerName;
        });
        const removeHeaderButton = component.shadowRoot.querySelector('.remove-header');
        removeHeaderButton.click();
        assert.strictEqual(headerRemovedEventCount, 1);
        assert.strictEqual(headerNameFromEvent, headerName);
        assert.strictEqual(headerValueFromEvent, headerValue);
    });
    it('removes leading/trailing whitespace when editing header names/values', async () => {
        const originalHeaderName = Platform.StringUtilities.toLowerCaseString('some-header-name');
        const originalHeaderValue = 'someHeaderValue';
        const headerData = {
            name: originalHeaderName,
            value: originalHeaderValue,
            nameEditable: true,
            valueEditable: 1 /* NetworkComponents.HeaderSectionRow.EditingAllowedStatus.ENABLED */,
        };
        const editedHeaderName = ' new-header-name ';
        const editedHeaderValue = ' new value for header ';
        const { component, nameEditable, valueEditable } = await renderHeaderSectionRow(headerData);
        assert.isNotNull(component.shadowRoot);
        let headerValueFromEvent = '';
        let headerNameFromEvent = '';
        let headerEditedEventCount = 0;
        component.addEventListener('headeredited', event => {
            headerEditedEventCount++;
            headerValueFromEvent = event.headerValue;
            headerNameFromEvent = event.headerName;
        });
        assert.instanceOf(nameEditable, HTMLElement);
        nameEditable.focus();
        nameEditable.innerText = editedHeaderName;
        nameEditable.blur();
        assert.strictEqual(headerEditedEventCount, 1);
        assert.strictEqual(headerNameFromEvent, editedHeaderName.trim());
        assert.strictEqual(headerValueFromEvent, originalHeaderValue);
        assert.instanceOf(valueEditable, HTMLElement);
        valueEditable.focus();
        valueEditable.innerText = editedHeaderValue;
        valueEditable.blur();
        assert.strictEqual(headerEditedEventCount, 2);
        assert.strictEqual(headerNameFromEvent, editedHeaderName.trim());
        assert.strictEqual(headerValueFromEvent, editedHeaderValue.trim());
    });
});
//# sourceMappingURL=HeaderSectionRow.test.js.map