fix: make web-test-runner using documentOrShadowRoot.activeElement debuggable

This commit is contained in:
Thijs Louisse 2024-11-21 09:01:13 +01:00 committed by GitHub
parent 3d1c723d39
commit 3e13adedc2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 160 additions and 122 deletions

View file

@ -0,0 +1,6 @@
---
'@lion/ui': patch
---
make web-test-runner statements checking `documentOrShadowRoot.activeElement` debuggable by exposing
a test-helper method `isActiveElement`.

View file

@ -1,20 +1,22 @@
import {
getComboboxMembers,
getFilteredOptionValues,
mimicKeyPress,
mimicUserTyping,
mimicUserTypingAdvanced,
} from '@lion/ui/combobox-test-helpers.js';
import { defineCE, expect, fixture, html, unsafeStatic } from '@open-wc/testing';
import { Required, Unparseable } from '@lion/ui/form-core.js';
import { sendKeys } from '@web/test-runner-commands';
import { LionCombobox } from '@lion/ui/combobox.js';
import { browserDetection } from '@lion/ui/core.js';
import '@lion/ui/define/lion-combobox.js';
import '@lion/ui/define/lion-listbox.js';
import '@lion/ui/define/lion-option.js';
import { Required, Unparseable } from '@lion/ui/form-core.js';
import { defineCE, expect, fixture, html, unsafeStatic } from '@open-wc/testing';
import { sendKeys } from '@web/test-runner-commands';
import { LitElement } from 'lit';
import sinon from 'sinon';
import {
getFilteredOptionValues,
mimicUserTypingAdvanced,
getComboboxMembers,
mimicUserTyping,
mimicKeyPress,
} from '@lion/ui/combobox-test-helpers.js';
import { isActiveElement } from '../../core/test-helpers/isActiveElement.js';
/**
* @typedef {import('../types/SelectionDisplay.js').SelectionDisplay} SelectionDisplay
@ -986,7 +988,7 @@ describe('lion-combobox', () => {
options[0].click();
await el.updateComplete;
expect(el.opened).to.equal(false);
expect(document.activeElement).to.equal(_inputNode);
expect(isActiveElement(_inputNode)).to.be.true;
// step [4]
await el.updateComplete;

View file

@ -0,0 +1,14 @@
import { getDeepActiveElement } from '../src/getDeepActiveElement.js';
/**
* Readable alternative for `expect(el).to.equal(document.activeElement);`.
* While this is readable by itself, it makes Web Test Runner hang completely in many occasions.
* Therefore it's better to write:
* `expect(isActiveElement(el)).to.be.true;`
* @param {Element} el
* @param {{deep?: boolean}} opts
* @returns {boolean}
*/
export function isActiveElement(el, { deep = false } = {}) {
const activeEl = deep ? getDeepActiveElement() : document.activeElement;
return el === activeEl;
}

View file

@ -4,6 +4,7 @@ import { LitElement } from 'lit';
import sinon from 'sinon';
import { ScopedElementsMixin, supportsScopedRegistry } from '../src/ScopedElementsMixin.js';
import { isActiveElement } from '../test-helpers/isActiveElement.js';
/**
* @typedef {import('../types/SlotMixinTypes.js').SlotHost} SlotHost
@ -210,12 +211,12 @@ describe('SlotMixin', () => {
);
const el = /** @type {* & SlotHost} */ (await fixture(`<${tag}></${tag}>`));
el._focusableNode.focus();
expect(document.activeElement).to.equal(el._focusableNode);
expect(isActiveElement(el._focusableNode)).to.be.true;
el.currentValue = 1;
await el.updateComplete;
expect(document.activeElement).to.equal(el._focusableNode);
expect(isActiveElement(el._focusableNode)).to.be.true;
});
it('keeps focus after rerendering complex shadow root into slot', async () => {
@ -277,7 +278,7 @@ describe('SlotMixin', () => {
el.currentValue = 1;
await el.updateComplete;
expect(document.activeElement).to.equal(el._focusableNode);
expect(isActiveElement(el._focusableNode)).to.be.true;
expect(el._focusableNode.shadowRoot.activeElement).to.equal(el._focusableNode._buttonNode);
});
@ -335,12 +336,12 @@ describe('SlotMixin', () => {
el._focusableNode._buttonNode.focus();
expect(el._focusableNode.shadowRoot.activeElement).to.equal(el._focusableNode._buttonNode);
expect(isActiveElement(el._focusableNode._buttonNode, { deep: true })).to.be.true;
el.currentValue = 1;
await el.updateComplete;
expect(document.activeElement).to.equal(el._focusableNode);
expect(isActiveElement(el._focusableNode)).to.be.true;
expect(el._focusableNode.shadowRoot.activeElement).to.equal(el._focusableNode._buttonNode);
});

View file

@ -1,6 +1,7 @@
/* eslint-disable lit-a11y/no-autofocus */
import { expect, fixture as _fixture, html, unsafeStatic, aTimeout } from '@open-wc/testing';
import { runOverlayMixinSuite } from '../../overlays/test-suites/OverlayMixin.suite.js';
import { isActiveElement } from '../../core/test-helpers/isActiveElement.js';
import '@lion/ui/define/lion-dialog.js';
/**
@ -89,8 +90,8 @@ describe('lion-dialog', () => {
const invokerNode = el._overlayInvokerNode;
invokerNode.focus();
invokerNode.click();
const contentNode = el.querySelector('[slot="content"]');
expect(document.activeElement).to.equal(contentNode);
const contentNode = /** @type {Element} */ (el.querySelector('[slot="content"]'));
expect(isActiveElement(contentNode)).to.be.true;
});
it('sets focus on autofocused element', async () => {
@ -107,8 +108,8 @@ describe('lion-dialog', () => {
const invokerNode = el._overlayInvokerNode;
invokerNode.focus();
invokerNode.click();
const input = el.querySelector('input');
expect(document.activeElement).to.equal(input);
const input = /** @type {Element} */ (el.querySelector('input'));
expect(isActiveElement(input)).to.be.true;
});
it('with trapsKeyboardFocus set to false the focus stays on the invoker', async () => {
@ -125,7 +126,7 @@ describe('lion-dialog', () => {
const invokerNode = el._overlayInvokerNode;
invokerNode.focus();
invokerNode.click();
expect(document.activeElement).to.equal(invokerNode);
expect(isActiveElement(invokerNode)).to.be.true;
});
it('opened-changed event should send detail object with opened state', async () => {

View file

@ -1,14 +1,16 @@
import { LitElement } from 'lit';
import { getFormControlMembers } from '@lion/ui/form-core-test-helpers.js';
import { defineCE, expect, fixture, html, triggerFocusFor, unsafeStatic } from '@open-wc/testing';
import { sendKeys } from '@web/test-runner-commands';
import { spy } from 'sinon';
import { getFormControlMembers } from '@lion/ui/form-core-test-helpers.js';
import { NativeTextFieldMixin } from '@lion/ui/form-core.js';
import { sendKeys } from '@web/test-runner-commands';
import { browserDetection } from '@lion/ui/core.js';
import { LitElement } from 'lit';
import { spy } from 'sinon';
import { isActiveElement } from '../../core/test-helpers/isActiveElement.js';
/**
* @typedef {import('../types/FormControlMixinTypes.js').FormControlHost} FormControlHost
* @typedef {ArrayConstructor | ObjectConstructor | NumberConstructor | BooleanConstructor | StringConstructor | DateConstructor | 'iban' | 'email'} modelValueType
* @typedef {import('../types/FormControlMixinTypes.js').FormControlHost} FormControlHost
*/
/**
@ -56,7 +58,7 @@ export function runNativeTextFieldMixinSuite(customConfig) {
const { _inputNode } = getFormControlMembers(el);
await triggerFocusFor(el);
await el.updateComplete;
expect(document.activeElement).to.equal(_inputNode);
expect(isActiveElement(_inputNode)).to.be.true;
await sendKeys({
press: 'h',
});

View file

@ -1,27 +1,28 @@
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
import { Required, Validator } from '@lion/ui/form-core.js';
import '@lion/ui/define/lion-field.js';
import { getFormControlMembers } from '@lion/ui/form-core-test-helpers.js';
import { getLocalizeManager } from '@lion/ui/localize-no-side-effects.js';
import { localizeTearDown } from '@lion/ui/localize-test-helpers.js';
import {
expect,
fixture,
html,
triggerBlurFor,
triggerFocusFor,
unsafeStatic,
} from '@open-wc/testing';
import { Required, Validator } from '@lion/ui/form-core.js';
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
import '@lion/ui/define/lion-field.js';
import sinon from 'sinon';
import {
triggerFocusFor,
triggerBlurFor,
unsafeStatic,
fixture,
expect,
html,
} from '@open-wc/testing';
import { isActiveElement } from '../../core/test-helpers/isActiveElement.js';
/**
* @typedef {import('../src/LionField.js').LionField} LionField
* @typedef {import('../types/FormControlMixinTypes.js').FormControlHost} FormControlHost
* @typedef {FormControlHost & HTMLElement & {_parentFormGroup?:HTMLElement, checked?:boolean}} FormControl
* @typedef {HTMLElement & {shadowRoot: HTMLElement, assignedNodes: Function}} ShadowHTMLElement
* @typedef {import('../types/FormControlMixinTypes.js').FormControlHost} FormControlHost
* @typedef {import('../src/LionField.js').LionField} LionField
*/
/** @typedef {HTMLElement & {shadowRoot: HTMLElement, assignedNodes: Function}} ShadowHTMLElement */
const tagString = 'lion-field';
const tag = unsafeStatic(tagString);
const inputSlotString = '<input slot="input" />';
@ -106,7 +107,7 @@ describe('<lion-field>', () => {
await triggerFocusFor(el);
expect(document.activeElement).to.equal(_inputNode);
expect(isActiveElement(_inputNode)).to.be.true;
expect(cbFocusHost.callCount).to.equal(1);
expect(cbFocusNativeInput.callCount).to.equal(1);
expect(cbBlurHost.callCount).to.equal(0);
@ -117,7 +118,7 @@ describe('<lion-field>', () => {
expect(cbBlurNativeInput.callCount).to.equal(1);
await triggerFocusFor(el);
expect(document.activeElement).to.equal(_inputNode);
expect(isActiveElement(_inputNode)).to.be.true;
expect(cbFocusHost.callCount).to.equal(2);
expect(cbFocusNativeInput.callCount).to.equal(2);

View file

@ -1,13 +1,14 @@
/* eslint-disable lit-a11y/no-autofocus */
import { expect, fixture } from '@open-wc/testing';
import { html } from 'lit';
import { getAllTagNames } from './helpers/helpers.js';
import './helpers/umbrella-form.js';
import '@lion/ui/define/lion-dialog.js';
import '@lion/ui/define/lion-checkbox.js';
import '@lion/ui/define/lion-dialog.js';
import '@lion/ui/define/lion-option.js';
import '@lion/ui/define/lion-radio.js';
import { html } from 'lit';
import { isActiveElement } from '../../core/test-helpers/isActiveElement.js';
import { getAllTagNames } from './helpers/helpers.js';
import './helpers/umbrella-form.js';
/**
* @typedef {import('./helpers/umbrella-form.js').UmbrellaForm} UmbrellaForm
* @typedef {import('../../dialog/src/LionDialog.js').LionDialog} LionDialog
@ -89,6 +90,6 @@ describe('Form inside dialog Integrations', () => {
el._overlayInvokerNode.click();
const lionInput = el.querySelector('[name="input"]');
// @ts-expect-error [allow-protected-in-tests]
expect(document.activeElement).to.equal(lionInput._focusableNode);
expect(isActiveElement(lionInput._focusableNode)).to.be.true;
});
});

View file

@ -1,25 +1,27 @@
import { LionFieldset } from '@lion/ui/fieldset.js';
import '@lion/ui/define/lion-fieldset.js';
import { LionField, Required } from '@lion/ui/form-core.js';
import '@lion/ui/define/lion-field.js';
import '@lion/ui/define/lion-validation-feedback.js';
import { LionFieldset } from '@lion/ui/fieldset.js';
import '@lion/ui/define/lion-checkbox-group.js';
import '@lion/ui/define/lion-radio-group.js';
import '@lion/ui/define/lion-fieldset.js';
import '@lion/ui/define/lion-checkbox.js';
import '@lion/ui/define/lion-listbox.js';
import '@lion/ui/define/lion-option.js';
import '@lion/ui/define/lion-checkbox-group.js';
import '@lion/ui/define/lion-checkbox.js';
import '@lion/ui/define/lion-radio-group.js';
import '@lion/ui/define/lion-field.js';
import '@lion/ui/define/lion-radio.js';
import '@lion/ui/define/lion-form.js';
import { spy } from 'sinon';
import {
fixture as _fixture,
unsafeStatic,
aTimeout,
defineCE,
expect,
fixture as _fixture,
html,
oneEvent,
unsafeStatic,
expect,
html,
} from '@open-wc/testing';
import { spy } from 'sinon';
import { isActiveElement } from '../../core/test-helpers/isActiveElement.js';
/**
* @typedef {import('../src/LionForm.js').LionForm} LionForm
@ -225,7 +227,7 @@ describe('<lion-form>', () => {
button.click();
expect(dispatchSpy.args[0][0].type).to.equal('submit');
// @ts-ignore [allow-protected] in test
expect(document.activeElement).to.equal(el.formElements[1]._inputNode);
expect(isActiveElement(el.formElements[1]._inputNode)).to.be.true;
});
it('sets focus on submit to the first erroneous form element within a fieldset', async () => {
@ -248,7 +250,7 @@ describe('<lion-form>', () => {
expect(dispatchSpy.args[0][0].type).to.equal('submit');
const fieldset = el.formElements[0];
// @ts-ignore [allow-protected] in test
expect(document.activeElement).to.equal(fieldset.formElements[1]._inputNode);
expect(isActiveElement(fieldset.formElements[1]._inputNode)).to.be.true;
});
it('sets focus on submit to the first form element within a erroneous fieldset', async () => {
@ -268,7 +270,7 @@ describe('<lion-form>', () => {
button.click();
expect(dispatchSpy.args[0][0].type).to.equal('submit');
const fieldset = el.formElements[0];
expect(document.activeElement).to.equal(fieldset.formElements[0]._inputNode);
expect(isActiveElement(fieldset.formElements[0]._inputNode)).to.be.true;
});
it('sets focus on submit to the first form element within a erroneous fieldset within another fieldset', async () => {
@ -290,7 +292,7 @@ describe('<lion-form>', () => {
const childFieldsetEl = parentFieldSetEl.formElements[0];
const inputEl = childFieldsetEl.formElements[0];
button.click();
expect(document.activeElement).to.equal(inputEl._focusableNode);
expect(isActiveElement(inputEl._focusableNode)).to.be.true;
});
it('sets focus on submit to the first form element within a erroneous listbox', async () => {
@ -308,7 +310,7 @@ describe('<lion-form>', () => {
const button = /** @type {HTMLButtonElement} */ (el.querySelector('button'));
button.click();
const listboxEl = el.formElements[0];
expect(document.activeElement).to.equal(listboxEl._inputNode);
expect(isActiveElement(listboxEl._inputNode)).to.be.true;
});
it('sets focus on submit to the first form element within a erroneous listbox within a fieldset', async () => {
@ -329,7 +331,7 @@ describe('<lion-form>', () => {
button.click();
const fieldsetEl = el.formElements[0];
const listboxEl = fieldsetEl.formElements[0];
expect(document.activeElement).to.equal(listboxEl._inputNode);
expect(isActiveElement(listboxEl._inputNode)).to.be.true;
});
it('sets focus on submit to the first form element within a erroneous checkbox-group', async () => {
@ -348,7 +350,7 @@ describe('<lion-form>', () => {
const checkboxGroupEl = el.formElements[0];
const checkboxEl = checkboxGroupEl.formElements[0];
button.click();
expect(document.activeElement).to.equal(checkboxEl._focusableNode);
expect(isActiveElement(checkboxEl._focusableNode)).to.be.true;
});
it('sets focus on submit to the first form element within a erroneous radio-group', async () => {
@ -370,6 +372,6 @@ describe('<lion-form>', () => {
const radioGroupEl = el.formElements[0];
const radioEl = radioGroupEl.formElements[0];
button.click();
expect(document.activeElement).to.equal(radioEl._focusableNode);
expect(isActiveElement(radioEl._focusableNode)).to.be.true;
});
});

View file

@ -6,7 +6,7 @@
* and contains several bugs on IE11.
*/
import { getDeepActiveElement } from './get-deep-active-element.js';
import { getDeepActiveElement } from '../../../core/src/getDeepActiveElement.js';
import { getFocusableElements } from './get-focusable-elements.js';
import { deepContains } from './deep-contains.js';
import { keyCodes } from './key-codes.js';

View file

@ -12,6 +12,7 @@ import {
html,
} from '@open-wc/testing';
import { isActiveElement } from '../../core/test-helpers/isActiveElement.js';
import { createShadowHost } from '../test-helpers/createShadowHost.js';
import { _adoptStyleUtils } from '../src/utils/adopt-styles.js';
import { simulateTab } from '../src/utils/simulate-tab.js';
@ -574,7 +575,8 @@ describe('OverlayController', () => {
trapsKeyboardFocus: true,
});
await ctrl.show();
expect(ctrl.contentNode).to.equal(document.activeElement);
expect(isActiveElement(ctrl.contentNode)).to.be.true;
});
it('keeps focus within the overlay e.g. you can not tab out by accident', async () => {
@ -1139,10 +1141,10 @@ describe('OverlayController', () => {
await ctrl.show();
const input = /** @type {HTMLInputElement} */ (contentNode.querySelector('input'));
input.focus();
expect(document.activeElement).to.equal(input);
expect(isActiveElement(input)).to.be.true;
await ctrl.hide();
expect(document.activeElement).to.equal(document.body);
expect(isActiveElement(document.body)).to.be.true;
});
it('supports elementToFocusAfterHide option to focus it when hiding', async () => {
@ -1159,10 +1161,10 @@ describe('OverlayController', () => {
await ctrl.show();
const textarea = /** @type {HTMLTextAreaElement} */ (contentNode.querySelector('textarea'));
textarea.focus();
expect(document.activeElement).to.equal(textarea);
expect(isActiveElement(textarea)).to.be.true;
await ctrl.hide();
expect(document.activeElement).to.equal(input);
expect(isActiveElement(input)).to.be.true;
expect(isInViewport(input)).to.be.true;
});
@ -1187,10 +1189,10 @@ describe('OverlayController', () => {
await ctrl.show();
const textarea = /** @type {HTMLTextAreaElement} */ (contentNode.querySelector('textarea'));
textarea.focus();
expect(document.activeElement).to.equal(textarea);
expect(isActiveElement(textarea)).to.be.true;
await ctrl.hide();
expect(document.activeElement).to.equal(input);
expect(isActiveElement(input)).to.be.true;
document.body.removeChild(shadowHost);
});
@ -1208,10 +1210,10 @@ describe('OverlayController', () => {
await ctrl.show();
// an outside element has taken over focus
outsideButton.focus();
expect(document.activeElement).to.equal(outsideButton);
expect(isActiveElement(outsideButton)).to.be.true;
await ctrl.hide();
expect(document.activeElement).to.equal(outsideButton);
expect(isActiveElement(outsideButton)).to.be.true;
});
it('allows to set elementToFocusAfterHide on show', async () => {
@ -1230,10 +1232,10 @@ describe('OverlayController', () => {
await ctrl.show(input);
const textarea = /** @type {HTMLTextAreaElement} */ (contentNode.querySelector('textarea'));
textarea.focus();
expect(document.activeElement).to.equal(textarea);
expect(isActiveElement(textarea)).to.be.true;
await ctrl.hide();
expect(document.activeElement).to.equal(input);
expect(isActiveElement(input)).to.be.true;
});
});

View file

@ -1,11 +1,12 @@
/* eslint-disable lit-a11y/no-autofocus */
import { expect, fixture, nextFrame } from '@open-wc/testing';
import { html } from 'lit/static-html.js';
import { getFocusableElements } from '@lion/ui/overlays.js';
import { renderLitAsNode } from '@lion/ui/helpers.js';
import { getDeepActiveElement, getFocusableElements } from '@lion/ui/overlays.js';
import { html } from 'lit/static-html.js';
import { keyCodes } from '../../src/utils/key-codes.js';
import { isActiveElement } from '../../../core/test-helpers/isActiveElement.js';
import { containFocus } from '../../src/utils/contain-focus.js';
import { keyCodes } from '../../src/utils/key-codes.js';
function simulateTabWithinContainFocus() {
const event = new CustomEvent('keydown', { detail: 0, bubbles: true });
@ -87,7 +88,7 @@ describe('containFocus()', () => {
const root = /** @type {HTMLElement} */ (document.getElementById('rootElement'));
const { disconnect } = containFocus(root);
expect(getDeepActiveElement()).to.equal(root);
expect(isActiveElement(root, { deep: true })).to.be.true;
expect(root.getAttribute('tabindex')).to.equal('-1');
expect(root.style.getPropertyValue('outline-style')).to.equal('none');
@ -99,7 +100,7 @@ describe('containFocus()', () => {
const el = /** @type {HTMLElement} */ (document.querySelector('input[autofocus]'));
const { disconnect } = containFocus(el);
expect(getDeepActiveElement()).to.equal(el);
expect(isActiveElement(el, { deep: true })).to.be.true;
disconnect();
});
@ -113,7 +114,7 @@ describe('containFocus()', () => {
/** @type {HTMLElement} */ (document.getElementById('outside-1')).focus();
simulateTabWithinContainFocus();
expect(getDeepActiveElement()).to.equal(focusableElements[0]);
expect(isActiveElement(focusableElements[0], { deep: true })).to.be.true;
disconnect();
});
@ -127,7 +128,7 @@ describe('containFocus()', () => {
focusableElements[focusableElements.length - 1].focus();
simulateTabWithinContainFocus();
expect(getDeepActiveElement()).to.equal(focusableElements[0]);
expect(isActiveElement(focusableElements[0], { deep: true })).to.be.true;
disconnect();
});
@ -146,7 +147,7 @@ describe('containFocus()', () => {
* actual tab key press. So the best we can do is if we didn't redirect focus
* to the first element.
*/
expect(getDeepActiveElement()).to.equal(focusableElements[2]);
expect(isActiveElement(focusableElements[2], { deep: true })).to.be.true;
disconnect();
});
@ -158,9 +159,10 @@ describe('containFocus()', () => {
const { disconnect } = containFocus(root);
focusableElements[2].focus();
expect(getDeepActiveElement()).to.equal(focusableElements[2]);
expect(isActiveElement(focusableElements[2], { deep: true })).to.be.true;
document.body.click(); // this does not cause focusout event :( doesn't seem possible to mock
expect(getDeepActiveElement()).to.equal(root);
expect(isActiveElement(root, { deep: true })).to.be.true;
disconnect();
});
@ -185,11 +187,12 @@ describe('containFocus()', () => {
// Simulate tab in window
simulateTabInWindow(/** @type {HTMLElement} */ (document.getElementById('outside-1')));
expect(getDeepActiveElement()).to.equal(focusableElements[0]);
expect(isActiveElement(focusableElements[0], { deep: true })).to.be.true;
// Simulate shift+tab in window
simulateTabInWindow(/** @type {HTMLElement} */ (document.getElementById('outside-2')));
expect(getDeepActiveElement()).to.equal(focusableElements[focusableElements.length - 1]);
expect(isActiveElement(focusableElements[focusableElements.length - 1], { deep: true })).to.be
.true;
disconnect();
});
@ -202,11 +205,12 @@ describe('containFocus()', () => {
// Simulate tab in window
simulateTabInWindow(/** @type {HTMLElement} */ (document.getElementById('outside-1')));
expect(getDeepActiveElement()).to.equal(focusableElements[0]);
expect(isActiveElement(focusableElements[0], { deep: true })).to.be.true;
// Simulate shift+tab in window
simulateTabInWindow(/** @type {HTMLElement} */ (document.getElementById('outside-2')));
expect(getDeepActiveElement()).to.equal(focusableElements[focusableElements.length - 1]);
expect(isActiveElement(focusableElements[focusableElements.length - 1], { deep: true })).to.be
.true;
disconnect();
});
@ -219,11 +223,12 @@ describe('containFocus()', () => {
// Simulate tab in window
simulateTabInWindow(focusableElements[0]);
expect(getDeepActiveElement()).to.equal(focusableElements[0]);
expect(isActiveElement(focusableElements[0], { deep: true })).to.be.true;
// Simulate shift+tab in window
simulateTabInWindow(focusableElements[focusableElements.length - 1]);
expect(getDeepActiveElement()).to.equal(focusableElements[focusableElements.length - 1]);
expect(isActiveElement(focusableElements[focusableElements.length - 1], { deep: true })).to.be
.true;
disconnect();
});

View file

@ -1,30 +1,28 @@
import { LitElement } from 'lit';
import { LionOption } from '@lion/ui/listbox.js';
import { OverlayController } from '@lion/ui/overlays.js';
import { mimicClick } from '@lion/ui/overlays-test-helpers.js';
import { LionSelectInvoker, LionSelectRich } from '@lion/ui/select-rich.js';
import '@lion/ui/define/lion-option.js';
import '@lion/ui/define/lion-listbox.js';
import { getSelectRichMembers } from '@lion/ui/select-rich-test-helpers.js';
import { mimicClick } from '@lion/ui/overlays-test-helpers.js';
import { OverlayController } from '@lion/ui/overlays.js';
import { LionOption } from '@lion/ui/listbox.js';
import '@lion/ui/define/lion-select-rich.js';
import '@lion/ui/define/lion-listbox.js';
import '@lion/ui/define/lion-option.js';
import { LitElement } from 'lit';
import {
fixture as _fixture,
unsafeStatic,
nextFrame,
aTimeout,
defineCE,
expect,
fixture as _fixture,
html,
nextFrame,
unsafeStatic,
} from '@open-wc/testing';
import { getSelectRichMembers } from '@lion/ui/select-rich-test-helpers.js';
import { isActiveElement } from '../../core/test-helpers/isActiveElement.js';
/**
* @typedef {import('../../listbox/src/LionOptions.js').LionOptions} LionOptions
* @typedef {import('../../listbox/types/ListboxMixinTypes.js').ListboxHost} ListboxHost
* @typedef {import('../../form-core/types/FormControlMixinTypes.js').FormControlHost} FormControlHost
*/
/**
* @typedef {import('../../listbox/types/ListboxMixinTypes.js').ListboxHost} ListboxHost
* @typedef {import('../../listbox/src/LionOptions.js').LionOptions} LionOptions
* @typedef {import('lit').TemplateResult} TemplateResult
*/
@ -478,7 +476,7 @@ describe('lion-select-rich', () => {
el.opened = true;
await el.updateComplete;
expect(document.activeElement).to.equal(_listboxNode);
expect(isActiveElement(_listboxNode)).to.be.true;
el.opened = false;
await el.updateComplete;

View file

@ -1,16 +1,17 @@
import { getFormControlMembers } from '@lion/ui/form-core-test-helpers.js';
import { expect, fixture as _fixture } from '@open-wc/testing';
import { html } from 'lit/static-html.js';
import sinon from 'sinon';
import { Validator } from '@lion/ui/form-core.js';
import { LionSwitch } from '@lion/ui/switch.js';
import { getFormControlMembers } from '@lion/ui/form-core-test-helpers.js';
import { html } from 'lit/static-html.js';
import '@lion/ui/define/lion-switch.js';
import sinon from 'sinon';
import { isActiveElement } from '../../core/test-helpers/isActiveElement.js';
/**
* @typedef {import('../src/LionSwitchButton.js').LionSwitchButton} LionSwitchButton
* @typedef {import('lit').TemplateResult} TemplateResult
* @typedef {import('@lion/ui/types/form-core.js').FormControlHost} FormControlHost
* @typedef {import('lit').TemplateResult} TemplateResult
*/
const IsTrue = class extends Validator {
@ -60,7 +61,7 @@ describe('lion-switch', () => {
const { _inputNode, _labelNode } = getSwitchMembers(el);
_labelNode.click();
expect(document.activeElement).to.equal(_inputNode);
expect(isActiveElement(_inputNode)).to.be.true;
});
it('clicking the label should not focus the toggle button when disabled', async () => {

View file

@ -11,11 +11,12 @@ export { withTooltipConfig } from '../components/overlays/src/configurations/wit
export { containFocus, rotateFocus } from '../components/overlays/src/utils/contain-focus.js';
export { deepContains } from '../components/overlays/src/utils/deep-contains.js';
export { getDeepActiveElement } from '../components/overlays/src/utils/get-deep-active-element.js';
// re-export via this entrypoint for backwards compatibility
export { getDeepActiveElement } from '../components/core/src/getDeepActiveElement.js';
export { getFocusableElements } from '../components/overlays/src/utils/get-focusable-elements.js';
export {
setSiblingsInert,
unsetSiblingsInert,
setSiblingsInert,
} from '../components/overlays/src/utils/inert-siblings.js';
export { overlays } from '../components/overlays/src/singleton.js';

View file

@ -11,7 +11,8 @@ const groups = (
await optimisedGlob(['packages/*/test', 'packages/ui/components/**/test'], {
onlyDirectories: true,
})
).map(dir => ({ name: dir.split('/').at(-2), files: `${dir}/**/*.test.js` }));
) // @ts-expect-error [update-es-version-later]
.map(dir => ({ name: dir.split('/').at(-2), files: `${dir}/**/*.test.js` })); // .filter(({name}) => name === 'overlays');
/**
* @type {import('@web/test-runner').TestRunnerConfig['testRunnerHtml']}