UNPKG

chrome-devtools-frontend

Version:
259 lines (220 loc) • 7.85 kB
// Copyright 2021 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import {dispatchKeyDownEvent, renderElementIntoDOM} from '../../../testing/DOMHelpers.js'; import * as Buttons from './buttons.js'; describe('Button', () => { const iconName = 'file-image'; function renderButton( data: Buttons.Button.ButtonData = { variant: Buttons.Button.Variant.PRIMARY, }, text = 'Button'): Buttons.Button.Button { const button = new Buttons.Button.Button(); button.data = data; // Toolbar and round buttons do not take text, and error if you try to set any. if (data.variant !== Buttons.Button.Variant.TOOLBAR && data.variant !== Buttons.Button.Variant.ICON) { button.innerText = text; } renderElementIntoDOM(button); return button; } function testClick( data: Buttons.Button.ButtonData = { variant: Buttons.Button.Variant.PRIMARY, disabled: false, }, expectedClickCount = 1): void { const button = renderButton(data); let clicks = 0; button.onclick = () => clicks++; const innerButton = button.shadowRoot?.querySelector('button') as HTMLButtonElement; assert.instanceOf(innerButton, HTMLButtonElement); innerButton.click(); dispatchKeyDownEvent(innerButton, { key: 'Enter', }); assert.strictEqual(clicks, expectedClickCount); } it('changes to `disabled` state are reflect in the property', () => { const button = renderButton(); button.disabled = false; assert.isFalse(button.disabled); button.disabled = true; assert.isTrue(button.disabled); }); describe('focus', () => { it('correctly focuses the <button> element in the shadow DOM', () => { const button = renderButton(); button.focus(); assert.isTrue(button.shadowRoot!.querySelector('button')!.hasFocus()); }); }); describe('hasFocus', () => { it('correctly reflects the focus state of the button', () => { const button = renderButton(); button.focus(); assert.isTrue(button.hasFocus()); }); }); it('primary button can be clicked', () => { testClick({ variant: Buttons.Button.Variant.PRIMARY, }); }); it('disabled primary button cannot be clicked', () => { testClick( { variant: Buttons.Button.Variant.PRIMARY, disabled: true, }, 0); }); it('secondary button can be clicked', () => { testClick({ variant: Buttons.Button.Variant.OUTLINED, }); }); it('disabled secondary button cannot be clicked', () => { testClick( { variant: Buttons.Button.Variant.OUTLINED, disabled: true, }, 0); }); it('toolbar button can be clicked', () => { testClick({ variant: Buttons.Button.Variant.TOOLBAR, iconName, }); }); it('disabled toolbar button cannot be clicked', () => { testClick( { variant: Buttons.Button.Variant.TOOLBAR, iconName, disabled: true, }, 0); }); it('gets the no additional classes set for the inner button if only text is provided', () => { const button = renderButton(); const innerButton = button.shadowRoot?.querySelector('button') as HTMLButtonElement; assert.isTrue(!innerButton.classList.contains('text-with-icon')); assert.isTrue(!innerButton.classList.contains('only-icon')); }); it('gets title set', () => { const button = renderButton({ variant: Buttons.Button.Variant.PRIMARY, title: 'Custom', }); const innerButton = button.shadowRoot?.querySelector('button') as HTMLButtonElement; assert.strictEqual(innerButton.title, 'Custom'); button.title = 'Custom2'; assert.strictEqual(innerButton.title, 'Custom2'); }); it('gets the text-with-icon class set for the inner button if text and icon is provided', () => { const button = renderButton( { variant: Buttons.Button.Variant.PRIMARY, iconName, }, 'text'); const innerButton = button.shadowRoot?.querySelector('button') as HTMLButtonElement; assert.isTrue(innerButton.classList.contains('text-with-icon')); assert.isTrue(!innerButton.classList.contains('only-icon')); }); it('gets the only-icon class set for the inner button if only icon is provided', () => { const button = renderButton( { variant: Buttons.Button.Variant.PRIMARY, iconName, }, ''); const innerButton = button.shadowRoot?.querySelector('button') as HTMLButtonElement; assert.isTrue(!innerButton.classList.contains('text-with-icon')); assert.isTrue(innerButton.classList.contains('only-icon')); }); it('gets the `small` class set for the inner button if size === SMALL', () => { const button = renderButton( { variant: Buttons.Button.Variant.PRIMARY, size: Buttons.Button.Size.SMALL, }, ''); const innerButton = button.shadowRoot?.querySelector('button') as HTMLButtonElement; assert.isTrue(innerButton.classList.contains('small')); }); it('does not get the `small` class set for the inner button if size === MEDIUM', () => { const button = renderButton( { variant: Buttons.Button.Variant.PRIMARY, iconName, }, ''); const innerButton = button.shadowRoot?.querySelector('button') as HTMLButtonElement; assert.isFalse(innerButton.classList.contains('small')); }); it('prevents only "keydown" events for Enter and Space to bubble up', () => { const button = renderButton({variant: Buttons.Button.Variant.PRIMARY}); const onKeydown = sinon.spy(); button.addEventListener('keydown', onKeydown); const innerButton = button.shadowRoot!.querySelector('button') as HTMLButtonElement; dispatchKeyDownEvent(innerButton, {bubbles: true, composed: true, key: 'Enter'}); dispatchKeyDownEvent(innerButton, {bubbles: true, composed: true, key: ' '}); dispatchKeyDownEvent(innerButton, {bubbles: true, composed: true, key: 'x'}); assert.isTrue(onKeydown.calledOnce); assert.strictEqual(onKeydown.getCall(0).args[0].key, 'x'); }); describe('in forms', () => { function renderForm(data: Buttons.Button.ButtonData = { variant: Buttons.Button.Variant.PRIMARY, }) { const form = document.createElement('form'); const input = document.createElement('input'); const button = new Buttons.Button.Button(); const reference = { submitCount: 0, form, button, input, }; form.onsubmit = (event: Event) => { event.preventDefault(); reference.submitCount++; }; button.data = data; button.innerText = 'button'; form.append(input); form.append(button); renderElementIntoDOM(form); return reference; } it('submits a form with button[type=submit]', () => { const state = renderForm({ variant: Buttons.Button.Variant.PRIMARY, type: 'submit', }); state.button.click(); assert.strictEqual(state.submitCount, 1); }); it('does not submit a form with button[type=button]', () => { const state = renderForm({ variant: Buttons.Button.Variant.PRIMARY, type: 'button', }); state.button.click(); assert.strictEqual(state.submitCount, 0); }); it('resets a form with button[type=reset]', () => { const state = renderForm({ variant: Buttons.Button.Variant.PRIMARY, type: 'reset', }); state.input.value = 'test'; state.button.click(); assert.strictEqual(state.input.value, ''); }); }); });