Outlook_Addin_LLM/node_modules/@fluentui/utilities/lib/focus.test.js

303 lines
15 KiB
JavaScript

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { createTestContainer } from '@fluentui/test-utilities';
import { isElementVisible, isElementTabbable, focusAsync, getElementIndexPath, getFirstTabbable, getFocusableByIndexPath, getLastTabbable, } from './focus';
function renderIntoDocument(element, container) {
var component = ReactDOM.render(element, container);
var renderedDOM = ReactDOM.findDOMNode(component);
return renderedDOM;
}
// JSDOM does not currently set `delegatesFocus`
// https://github.com/jsdom/jsdom/blob/b7683ed68ebe259cd2c68e5faf12d484a785f45f/lib/jsdom/living/nodes/Element-impl.js#L420-L424
function createDivWithShadowRoot(initOptions) {
var div = {
getAttribute: function (qualifiedName) { return null; },
shadowRoot: {
mode: initOptions.mode,
delegatesFocus: initOptions.delegatesFocus,
},
};
return div;
}
function makeShadowDiv(innerHTML) {
var ShadowDiv = function () {
var setRef = function (node) {
if (node) {
node.attachShadow({ mode: 'open' });
node.shadowRoot.innerHTML = innerHTML;
}
};
return React.createElement("div", { className: "parent", ref: setRef });
};
return ShadowDiv;
}
describe('isElementVisible', function () {
var testContainer;
afterEach(function () {
if (testContainer) {
ReactDOM.unmountComponentAtNode(testContainer);
testContainer.remove();
testContainer = undefined;
}
});
it('returns false if data-is-visible is false', function () {
testContainer = createTestContainer();
var _hiddenElement = renderIntoDocument(React.createElement("div", { "data-is-visible": false },
React.createElement("button", null)), testContainer);
expect(isElementVisible(_hiddenElement)).toEqual(false);
});
it('returns true if data-is-visible is true', function () {
testContainer = createTestContainer();
var _visibleElement = renderIntoDocument(React.createElement("div", { "data-is-visible": true },
React.createElement("button", null)), testContainer);
expect(isElementVisible(_visibleElement)).toEqual(true);
});
it('returns true if data-is-visible is undefined but element is visible', function () {
testContainer = createTestContainer();
var _element = renderIntoDocument(React.createElement("div", null,
React.createElement("button", null)), testContainer);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
_element.isVisible = true;
expect(isElementVisible(_element)).toEqual(true);
});
});
describe('isElementTabbable', function () {
it('returns false on null', function () {
expect(isElementVisible(null)).toEqual(false);
});
it('returns false on normal divs', function () {
var div = document.createElement('div');
expect(isElementTabbable(div)).toEqual(false);
});
it('returns false on disabled buttons', function () {
var button = document.createElement('button');
button.setAttribute('disabled', 'true');
expect(isElementTabbable(button)).toEqual(false);
});
it('returns true on buttons', function () {
var button = document.createElement('button');
expect(isElementTabbable(button)).toEqual(true);
});
it('returns true on anchors', function () {
var anchor = document.createElement('a');
expect(isElementTabbable(anchor)).toEqual(true);
});
it('returns true on input elements', function () {
var input = document.createElement('input');
expect(isElementTabbable(input)).toEqual(true);
});
it('returns true on select elements', function () {
var select = document.createElement('select');
expect(isElementTabbable(select)).toEqual(true);
});
it('returns true on textarea elements', function () {
var textarea = document.createElement('textarea');
expect(isElementTabbable(textarea)).toEqual(true);
});
it('works with tabbable divs', function () {
var div = document.createElement('div');
div.tabIndex = 0;
expect(isElementTabbable(div)).toEqual(true);
});
it('returns false with role=button divs', function () {
var div = document.createElement('div');
div.setAttribute('role', 'button');
expect(isElementTabbable(div)).toEqual(false);
});
it('returns false with role=button disabled buttons', function () {
var button = document.createElement('button');
button.setAttribute('role', 'button');
button.setAttribute('disabled', 'true');
expect(isElementTabbable(button)).toEqual(false);
});
it('returns false with -1 tabIndex', function () {
var button = document.createElement('button');
button.tabIndex = -1;
expect(isElementTabbable(button, true)).toEqual(false);
});
it('returns true for elements with shadowRoot.delegatesFocus=true', function () {
var _a;
var div = createDivWithShadowRoot({ mode: 'open', delegatesFocus: true });
expect((_a = div.shadowRoot) === null || _a === void 0 ? void 0 : _a.delegatesFocus).toEqual(true);
expect(isElementTabbable(div)).toEqual(true);
});
it('returns true for elements with shadowRoot.delegatesFocus=false', function () {
var div = createDivWithShadowRoot({ mode: 'open' });
expect(isElementTabbable(div)).toEqual(false);
});
it('returns true for elements with shadowRoot.delegatesFocus=true when set to ignore shadow roots', function () {
var div = createDivWithShadowRoot({ mode: 'open', delegatesFocus: true });
expect(isElementTabbable(div, undefined, false)).toEqual(false);
});
});
describe('focusAsync', function () {
var testContainer;
afterEach(function () {
if (testContainer) {
ReactDOM.unmountComponentAtNode(testContainer);
testContainer.remove();
testContainer = undefined;
}
});
beforeAll(function () {
jest.useFakeTimers();
});
afterAll(function () {
jest.useRealTimers();
});
it('focuses on an item on the next frame', function () {
testContainer = createTestContainer();
var container = renderIntoDocument(React.createElement("div", null,
React.createElement("button", { className: "a" }, "a"),
React.createElement("button", { className: "b" }, "b"),
React.createElement("button", { className: "c" }, "c")), testContainer);
var buttonA = container.querySelector('.a');
var buttonB = container.querySelector('.b');
var buttonC = container.querySelector('.c');
// Focus the first button.
focusAsync(buttonA);
window.requestAnimationFrame(function () {
expect(container.ownerDocument.activeElement).toBe(buttonA);
// Focus the second button, then the third before the next frame
focusAsync(buttonB);
focusAsync(buttonC);
window.requestAnimationFrame(function () {
expect(container.ownerDocument.activeElement).toBe(buttonC);
});
});
jest.runAllTimers();
});
it('can focus a component which implements focus()', function () {
var calledFocus = false;
var fakeComponent = {
ownerDocument: {},
focus: function () { return (calledFocus = true); },
};
focusAsync(fakeComponent);
jest.runAllTimers();
expect(calledFocus).toEqual(true);
});
});
describe('getFocusableByIndexPath', function () {
it('can recover a path', function () {
var parent = document.createElement('div');
parent.innerHTML = "\n <div>\n <div></div>\n <div></div>\n <div>\n <div></div>\n <button id='child' data-is-visible='true' />\n </div>\n </div>\n ";
var child = parent.querySelector('#child');
expect(getFocusableByIndexPath(parent, [0, 2, 1])).toEqual(child);
});
it('ignores hidden elements', function () {
var parent = document.createElement('div');
parent.innerHTML = "\n <div>\n <div></div>\n <div></div>\n <div>\n <div></div>\n <button id='child' data-is-visible='false' />\n </div>\n </div>\n ";
parent.querySelector('#child');
expect(getFocusableByIndexPath(parent, [0, 2, 1])).toEqual(null);
});
it('can fallback to a previous element', function () {
var parent = document.createElement('div');
parent.innerHTML = "\n <div>\n <button id='child' data-is-visible='true'>\n <div>\n <div/>\n </div>\n </button>\n </div>\n ";
var child = parent.querySelector('#child');
expect(getFocusableByIndexPath(parent, [0, 0, 0, 0, 0, 0])).toEqual(child);
});
});
describe('getElementIndexPath', function () {
it('can get a path', function () {
var parent = document.createElement('div');
parent.innerHTML = "\n <div>\n <div></div>\n <div></div>\n <div>\n <div></div>\n <div id='child'></div>\n </div>\n </div>\n ";
var child = parent.querySelector('#child');
expect(getElementIndexPath(parent, child)).toEqual([0, 2, 1]);
});
it('can handle the same element', function () {
var parent = document.createElement('div');
expect(getElementIndexPath(parent, parent)).toEqual([]);
});
});
describe('getFirstTabbable', function () {
var testContainer;
afterEach(function () {
if (testContainer) {
ReactDOM.unmountComponentAtNode(testContainer);
testContainer.remove();
testContainer = undefined;
}
});
it('focuses on the next tabbable item', function () {
testContainer = createTestContainer();
var container = renderIntoDocument(React.createElement("div", null,
React.createElement("div", { className: "parent" },
React.createElement("button", { className: "a", "data-is-visible": true }, "a"),
React.createElement("button", { className: "b", "data-is-visible": true }, "b"),
React.createElement("button", { className: "c", "data-is-visible": true }, "c"))), testContainer);
var parent = container.querySelector('.parent');
var buttonA = container.querySelector('.a');
var buttonB = container.querySelector('.b');
expect(getFirstTabbable(parent, buttonA, true, false)).toEqual(buttonB);
});
it('focuses on the next tabbable item in shadow DOM', function () {
var _a, _b;
testContainer = createTestContainer();
var innerHTML = "\n <button class=\"a\" data-is-visible=\"true\">\n a\n </button>\n <button class=\"b\" data-is-visible=\"true\">\n b\n </button>\n <button class=\"c\" data-is-visible=\"true\">\n c\n </button>\n ";
var ShadowDiv = makeShadowDiv(innerHTML);
var container = renderIntoDocument(React.createElement("div", null,
React.createElement(ShadowDiv, null)), testContainer);
var parent = container.querySelector('.parent');
var buttonA = (_a = parent === null || parent === void 0 ? void 0 : parent.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('.a');
var buttonB = (_b = parent === null || parent === void 0 ? void 0 : parent.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('.b');
expect(getFirstTabbable(parent, buttonA, true, false, true)).toEqual(buttonB);
});
it('does not focus on an item with tabIndex of -1', function () {
testContainer = createTestContainer();
var container = renderIntoDocument(React.createElement("div", null,
React.createElement("div", { className: "parent" },
React.createElement("button", { className: "a", "data-is-visible": true, tabIndex: -1 }, "a"),
React.createElement("button", { className: "b", "data-is-visible": true, tabIndex: -1 }, "b"),
React.createElement("button", { className: "c", "data-is-visible": true, tabIndex: -1 }, "c"))), testContainer);
var parent = container.querySelector('.parent');
var buttonA = container.querySelector('.a');
expect(getFirstTabbable(parent, buttonA, true, false)).toEqual(null);
});
});
describe('getLastTabbable', function () {
var testContainer;
afterEach(function () {
if (testContainer) {
ReactDOM.unmountComponentAtNode(testContainer);
testContainer.remove();
testContainer = undefined;
}
});
it('focuses on the last tabbable item', function () {
testContainer = createTestContainer();
var container = renderIntoDocument(React.createElement("div", null,
React.createElement("div", { className: "parent" },
React.createElement("button", { className: "a", "data-is-visible": true }, "a"),
React.createElement("button", { className: "b", "data-is-visible": true }, "b"),
React.createElement("button", { className: "c", "data-is-visible": true }, "c"))), testContainer);
var parent = container.querySelector('.parent');
var buttonB = container.querySelector('.b');
var buttonC = container.querySelector('.c');
expect(getLastTabbable(parent, buttonC, true, false)).toEqual(buttonB);
});
it('focuses on the last tabbable item in shadow DOM', function () {
var _a, _b;
testContainer = createTestContainer();
var innerHTML = "\n <button class=\"a\" data-is-visible=\"true\">\n a\n </button>\n <button class=\"b\" data-is-visible=\"true\">\n b\n </button>\n <button class=\"c\" data-is-visible=\"true\">\n c\n </button>\n ";
var ShadowDiv = makeShadowDiv(innerHTML);
var container = renderIntoDocument(React.createElement("div", null,
React.createElement(ShadowDiv, null)), testContainer);
var parent = container.querySelector('.parent');
var buttonB = (_a = parent === null || parent === void 0 ? void 0 : parent.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('.b');
var buttonC = (_b = parent === null || parent === void 0 ? void 0 : parent.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('.c');
expect(getLastTabbable(parent, buttonC, true, false, true)).toEqual(buttonB);
});
it('does not focus on an item with tabIndex of -1', function () {
testContainer = createTestContainer();
var container = renderIntoDocument(React.createElement("div", null,
React.createElement("div", { className: "parent" },
React.createElement("button", { className: "a", "data-is-visible": true, tabIndex: -1 }, "a"),
React.createElement("button", { className: "b", "data-is-visible": true, tabIndex: -1 }, "b"),
React.createElement("button", { className: "c", "data-is-visible": true, tabIndex: -1 }, "c"))), testContainer);
var parent = container.querySelector('.parent');
var buttonC = container.querySelector('.c');
expect(getLastTabbable(parent, buttonC, true, false)).toEqual(null);
});
});
//# sourceMappingURL=focus.test.js.map