Skip to content

Commit

Permalink
fix(hyrdate): support vdom annotation in nested dsd structures
Browse files Browse the repository at this point in the history
  • Loading branch information
christian-bromann committed Jun 25, 2024
1 parent 6ac07ec commit f1090ac
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 4 deletions.
4 changes: 2 additions & 2 deletions src/hydrate/platform/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export const win = window;
export const doc = win.document;

export const readTask = (cb: Function) => {
process.nextTick(() => {
nextTick(() => {
try {
cb();
} catch (e) {
Expand All @@ -66,7 +66,7 @@ export const readTask = (cb: Function) => {
};

export const writeTask = (cb: Function) => {
process.nextTick(() => {
nextTick(() => {
try {
cb();
} catch (e) {
Expand Down
10 changes: 9 additions & 1 deletion src/runtime/vdom/vdom-annotations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,15 @@ const parseVNodeAnnotations = (
}

if (node.nodeType === NODE_TYPE.ElementNode) {
node.childNodes.forEach((childNode) => {
/**
* we need to insert the vnode annotations on the host element childrens as well
* as on the children from its shadowRoot if there is one
*/
const childNodes = [
...Array.from(node.childNodes),
...Array.from(node.shadowRoot?.childNodes || [])
];
childNodes.forEach((childNode) => {
const hostRef = getHostRef(childNode);
if (hostRef != null && !docData.staticComponents.has(childNode.nodeName.toLowerCase())) {
const cmpData: CmpData = {
Expand Down
3 changes: 3 additions & 0 deletions test/wdio/declarative-shadow-dom/page-list-item.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:host {
display: block;
}
31 changes: 31 additions & 0 deletions test/wdio/declarative-shadow-dom/page-list-item.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Component, h, Prop } from '@stencil/core';

@Component({
tag: 'page-list-item',
styleUrl: 'page-list-item.css',
shadow: true,
})
export class MyOtherComponent {
/**
* Set the number to be displayed.
*/
@Prop() label!: number;

/**
* Set the number to be displayed.
*/
@Prop() active = false;

render() {
const paginationItemClass: any = {
'pagination-item': true,
'active': this.active,
};

return (
<div>
<div class={paginationItemClass}>{this.label}</div>
</div>
);
}
}
3 changes: 3 additions & 0 deletions test/wdio/declarative-shadow-dom/page-list.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:host {
display: block;
}
39 changes: 39 additions & 0 deletions test/wdio/declarative-shadow-dom/page-list.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// @ts-ignore may not be existing when project hasn't been built
type HydrateModule = typeof import('../../hydrate');
let renderToString: HydrateModule['renderToString'];

describe('renderToString', () => {
before(async () => {
// @ts-ignore may not be existing when project hasn't been built
const mod = await import('/hydrate/index.mjs');
renderToString = mod.renderToString;
});

beforeEach(async () => {
const { html } = await renderToString(
`<page-list last-page="5" current-page="1"></page-list>`,
{ serializeShadowRoot: true, prettyHtml: true, fullDocument: false },
);
const stage = document.createElement('div');
stage.setAttribute('id', 'stage')
stage.setHTMLUnsafe(html);
document.body.appendChild(stage);
});

afterEach(() => {
document.querySelector('#stage')?.remove();
});

it('can hydrate a nested shadow component', async () => {
expect(typeof customElements.get('page-list-item')).toBe('undefined')

// @ts-expect-error resolved through WDIO
const { defineCustomElements } = await import('/dist/loader/index.js');
defineCustomElements().catch(console.error);

// wait for Stencil to take over and reconcile
await browser.waitUntil(async () => customElements.get('page-list-item'));
expect(typeof customElements.get('page-list-item')).toBe('function')
await expect($('page-list')).toHaveText('0\n1\n2\n3\n4');
});
});
40 changes: 40 additions & 0 deletions test/wdio/declarative-shadow-dom/page-list.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Component, h, Prop, State } from '@stencil/core';

@Component({
tag: 'page-list',
styleUrl: 'page-list.css',
shadow: true,
})
export class PatternlibPagination {

@Prop({ mutable: true }) lastPage: number | null = null;
@State() pages: Array<number> = [];

private fillPageArray(start: number, num: number): Array<number> {
const pages = [];
for (let i = 0; i < num; i++) {
pages.push(start + i);
}
return pages;
}

componentWillLoad(): void {
// range guard
this.lastPage = this.lastPage && this.lastPage >= 1 ? this.lastPage : 1;
this.pages = this.fillPageArray(0, this.lastPage);
}

render() {
return (
<div>
<div class="pagination">
<div class="pagination-pages pagination-notation">
{this.pages.map(i => (
<page-list-item label={i}></page-list-item>
))}
</div>
</div>
</div>
);
}
}
3 changes: 2 additions & 1 deletion test/wdio/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ const testRequiresManualSetup =
window.__wdioSpec__.includes('custom-elements-delegates-focus') ||
window.__wdioSpec__.includes('custom-elements-output') ||
window.__wdioSpec__.includes('global-script') ||
window.__wdioSpec__.endsWith('custom-tag-name.test.tsx');
window.__wdioSpec__.endsWith('custom-tag-name.test.tsx') ||
window.__wdioSpec__.endsWith('page-list.test.ts');

/**
* setup all components defined in tests except for those where we want ot manually setup
Expand Down

0 comments on commit f1090ac

Please sign in to comment.