Skip to content

Commit

Permalink
Merge pull request #436 from capricorn86/task/434-active-element-does…
Browse files Browse the repository at this point in the history
…-not-target-the-same-in-test-as-in-browser

#434@patch: Fixes issue with Document.activeElement not being the fir…
  • Loading branch information
capricorn86 committed Mar 30, 2022
2 parents f679f76 + fba67c7 commit 548c33a
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 1 deletion.
12 changes: 12 additions & 0 deletions packages/happy-dom/src/nodes/document/Document.ts
Expand Up @@ -37,6 +37,7 @@ import DocumentReadyStateEnum from './DocumentReadyStateEnum';
import DocumentReadyStateManager from './DocumentReadyStateManager';
import Location from '../../location/Location';
import Selection from '../../selection/Selection';
import IShadowRoot from '../shadow-root/IShadowRoot';

/**
* Document.
Expand Down Expand Up @@ -240,6 +241,17 @@ export default class Document extends Node implements IDocument {
* @returns Active element.
*/
public get activeElement(): IHTMLElement {
if (this._activeElement) {
let rootNode: IShadowRoot | IDocument = <IShadowRoot | IDocument>(
this._activeElement.getRootNode()
);
let activeElement: IHTMLElement = this._activeElement;
while (rootNode !== this) {
activeElement = <IHTMLElement>(<IShadowRoot>rootNode).host;
rootNode = <IShadowRoot | IDocument>activeElement.getRootNode();
}
return activeElement;
}
return this._activeElement || this.body || this.documentElement || null;
}

Expand Down
56 changes: 56 additions & 0 deletions packages/happy-dom/test/nodes/document/Document.test.ts
Expand Up @@ -30,6 +30,8 @@ import ISVGElement from '../../../src/nodes/svg-element/ISVGElement';
import CustomEvent from '../../../src/event/events/CustomEvent';
import Selection from '../../../src/selection/Selection';

/* eslint-disable jsdoc/require-jsdoc */

describe('Document', () => {
let window: IWindow;
let document: IDocument;
Expand Down Expand Up @@ -309,6 +311,60 @@ describe('Document', () => {

expect(document.activeElement === document.body).toBe(true);
});

it('Returns the first custom element that has document as root node when the focused element is nestled in multiple shadow roots.', () => {
class CustomElementA extends window.HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
}

public connectedCallback(): void {
this.shadowRoot.innerHTML = `
<div>
<custom-element-b></custom-element-b>
</div>
`;
}
}
class CustomElementB extends window.HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
}

public connectedCallback(): void {
this.shadowRoot.innerHTML = `
<div>
<button tabindex="0"></button>
</div>
`;
}
}

window.customElements.define('custom-element-a', CustomElementA);
window.customElements.define('custom-element-b', CustomElementB);

const customElementA = document.createElement('custom-element-a');
const div = document.createElement('div');
div.appendChild(customElementA);
document.body.appendChild(div);

const button = <IHTMLElement>(
(<IHTMLElement>(
customElementA.shadowRoot.querySelector('custom-element-b')
)).shadowRoot.querySelector('button')
);

let focusCalls = 0;
button.addEventListener('focus', () => focusCalls++);

button.focus();
button.focus();

expect(document.activeElement).toBe(customElementA);
expect(focusCalls).toBe(1);
});
});

describe('get scrollingElement()', () => {
Expand Down
2 changes: 1 addition & 1 deletion packages/happy-dom/test/window/Window.test.ts
Expand Up @@ -100,7 +100,7 @@ describe('Window', () => {

describe('get Array()', () => {
it('Is the same as [].constructor.', () => {
expect((() => {}).constructor).toBe(window.Function);
expect([].constructor).toBe(window.Array);

const context = VM.createContext(new Window());
expect(context.eval('[].constructor === window.Array')).toBe(true);
Expand Down

0 comments on commit 548c33a

Please sign in to comment.