Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(mock-doc): overwrite parentElement in MockHTMLElement to return null #5336

Merged
merged 12 commits into from
Feb 8, 2024
17 changes: 16 additions & 1 deletion src/mock-doc/event.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ export class MockEvent {
this.cancelBubble = true;
}

/**
* @ref https://developer.mozilla.org/en-US/docs/Web/API/Event/composedPath
* @returns a composed path of the event
*/
composedPath(): MockElement[] {
const composedPath: MockElement[] = [];

Expand All @@ -54,7 +58,16 @@ export class MockEvent {
break;
}

currentElement = currentElement.parentElement;
/**
* bubble up the parent chain until we arrive to the HTML element. Here we continue
* with the document object instead of the parent element since the parent element
* is `null` for HTML elements.
*/
if (currentElement.parentElement == null && currentElement.tagName === 'HTML') {
currentElement = currentElement.ownerDocument;
} else {
currentElement = currentElement.parentElement;
}
}

return composedPath;
Expand Down Expand Up @@ -202,6 +215,8 @@ function triggerEventListener(elm: any, ev: MockEvent) {

if (elm.nodeName === NODE_NAMES.DOCUMENT_NODE) {
triggerEventListener((elm as MockDocument).defaultView, ev);
} else if (elm.parentElement == null && elm.tagName === 'HTML') {
triggerEventListener(elm.ownerDocument, ev);
} else {
triggerEventListener(elm.parentElement, ev);
}
Expand Down
13 changes: 13 additions & 0 deletions src/mock-doc/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1101,6 +1101,19 @@ export class MockHTMLElement extends MockElement {
this.nodeName = value;
}

/**
* A node’s parent of type Element is known as its parent element.
* If the node has a parent of a different type, its parent element
* is null.
* @returns MockElement
*/
override get parentElement() {
if (this.nodeName === 'HTML') {
return null;
}
return super.parentElement;
}

override get attributes(): MockAttributeMap {
if (this.__attributeMap == null) {
const attrMap = createAttributeProxy(true);
Expand Down
7 changes: 7 additions & 0 deletions src/mock-doc/test/element.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,13 @@ describe('element', () => {
});
});

describe('parentElement', () => {
it('returns `null` for when accessing the parent element of an html node', () => {
const element = new MockHTMLElement(doc, 'myElement');
expect(element.parentElement).toEqual(null);
});
});

describe('input', () => {
it('list is readonly prop', () => {
const input = doc.createElement('input');
Expand Down
14 changes: 11 additions & 3 deletions src/runtime/test/style.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ describe('style', () => {
it('get style string', async () => {
@Component({
tag: 'cmp-a',
styles: `div { color: red; }`,
styles: `
div {
color: red;
}
`,
})
class CmpA {
render() {
Expand All @@ -20,13 +24,17 @@ describe('style', () => {
});

expect(root).toHaveClass('hydrated');
expect(styles.get('sc-cmp-a')).toBe(`div { color: red; }`);
expect(styles.get('sc-cmp-a')).toContain(`color: red;`);
});

it('applies the nonce value to the head style tags', async () => {
@Component({
tag: 'cmp-a',
styles: `div { color: red; }`,
styles: `
div {
color: red;
}
`,
})
class CmpA {
render() {
Expand Down
9 changes: 7 additions & 2 deletions test/end-to-end/src/state-cmp/state-cmp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@ import { Component, State, h } from '@stencil/core';
@Component({
tag: 'state-cmp',
styles: `
button { color: black; }
.selected { font-weight: bold; color: blue; }
button {
color: black;
}
.selected {
font-weight: bold;
color: blue;
}
`,
shadow: true,
})
Expand Down
6 changes: 3 additions & 3 deletions test/karma/test-app/attribute-host/cmp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@ import { Component, State, h } from '@stencil/core';
@Component({
tag: 'attribute-host',
styles: `
[color=lime] {
[color='lime'] {
background: lime;
}
section::before {
content: attr(content);
}
[padding=true] {
[padding='true'] {
padding: 50px;
}
[margin] {
margin: 50px;
}
[bold=true] {
[bold='true'] {
font-weight: bold;
}
`,
Expand Down
15 changes: 8 additions & 7 deletions test/karma/test-app/listen-jsx/cmp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ import { Component, Listen, State, h } from '@stencil/core';
tag: 'listen-jsx',
scoped: true,
styles: `
:host{
background: black;
display: block;
color: white;
width: 100px;
height: 100px;
}`,
:host {
background: black;
display: block;
color: white;
width: 100px;
height: 100px;
}
`,
})
export class AttributeBasic {
@State() wasClicked = '';
Expand Down