Skip to content

Commit e253ceb

Browse files
johnjenkinsJohn Jenkins
andauthored
fix(ssr): mixed ssr methods styles (#6289)
Co-authored-by: John Jenkins <john.jenkins@nanoporetech.com>
1 parent f2dd25d commit e253ceb

3 files changed

Lines changed: 80 additions & 4 deletions

File tree

src/runtime/styles.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,7 @@ export const addStyle = (styleContainerNode: any, cmpMeta: d.ComponentRuntimeMet
7575
// This is only happening on native shadow-dom, do not needs CSS var shim
7676
styleElm.innerHTML = style;
7777
} else {
78-
styleElm =
79-
document.querySelector(`[${HYDRATED_STYLE_ID}="${scopeId}"]`) || win.document.createElement('style');
78+
styleElm = win.document.createElement('style');
8079
styleElm.innerHTML = style;
8180

8281
// Apply CSP nonce to the style tag if it exists

test/wdio/ssr-hydration/cmp.test.tsx

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ describe('Sanity check SSR > Client hydration', () => {
7777
await expect(getNodeNames(ele.shadowRoot.childNodes)).toBe(eles);
7878

7979
// Checking styling
80-
await expect(getComputedStyle(ele).color).toBe('rgb(255, 0, 0)');
81-
await expect(getComputedStyle(ele).backgroundColor).toBe('rgb(255, 255, 0)');
80+
await expect(getComputedStyle(ele).color).toBe('rgb(255, 0, 0)'); // red
81+
await expect(getComputedStyle(ele).backgroundColor).toBe('rgb(255, 255, 0)'); // yellow
8282
},
8383

8484
slots: async () => {
@@ -247,4 +247,48 @@ describe('Sanity check SSR > Client hydration', () => {
247247
renderTime = performance.measure('render', 'start-scoped', 'end-scoped').duration;
248248
await expect(renderTime).toBeLessThan(50);
249249
});
250+
251+
it("renders the styles of scoped components when they're embedded in a shadow root", async () => {
252+
if (document.querySelector('#stage')) {
253+
document.querySelector('#stage')?.remove();
254+
await browser.waitUntil(async () => !document.querySelector('#stage'));
255+
}
256+
const { html } = await renderToString(
257+
`
258+
<div>
259+
<wrap-ssr-shadow-cmp>Inside shadowroot</wrap-ssr-shadow-cmp>
260+
<ssr-shadow-cmp>Outside shadowroot</ssr-shadow-cmp>
261+
</div>`,
262+
{
263+
fullDocument: true,
264+
serializeShadowRoot: {
265+
default: 'declarative-shadow-dom',
266+
scoped: ['ssr-shadow-cmp'],
267+
},
268+
},
269+
);
270+
const stage = document.createElement('div');
271+
stage.setAttribute('id', 'stage');
272+
stage.setHTMLUnsafe(html);
273+
document.body.appendChild(stage);
274+
275+
// @ts-expect-error resolved through WDIO
276+
const { defineCustomElements } = await import('/dist/loader/index.js');
277+
defineCustomElements().catch(console.error);
278+
279+
// wait for Stencil to take over and reconcile
280+
await browser.waitUntil(async () => customElements.get('ssr-shadow-cmp'));
281+
expect(typeof customElements.get('ssr-shadow-cmp')).toBe('function');
282+
283+
const wrapCmp = document.querySelector('wrap-ssr-shadow-cmp');
284+
const scopedCmp = document.querySelector('ssr-shadow-cmp');
285+
const scopedNestCmp = wrapCmp.shadowRoot.querySelector('ssr-shadow-cmp');
286+
287+
await expect(getComputedStyle(wrapCmp).color).toBe('rgb(255, 255, 255)'); // white
288+
await expect(getComputedStyle(wrapCmp).backgroundColor).toBe('rgb(0, 0, 255)'); // blue
289+
await expect(getComputedStyle(scopedCmp).color).toBe('rgb(255, 0, 0)'); // red
290+
await expect(getComputedStyle(scopedCmp).backgroundColor).toBe('rgb(255, 255, 0)'); // yellow
291+
await expect(getComputedStyle(scopedNestCmp).color).toBe('rgb(255, 0, 0)'); // red
292+
await expect(getComputedStyle(scopedNestCmp).backgroundColor).toBe('rgb(255, 255, 0)'); // yellow
293+
});
250294
});
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { Component, h, Prop } from '@stencil/core';
2+
3+
@Component({
4+
tag: 'wrap-ssr-shadow-cmp',
5+
shadow: true,
6+
styles: `
7+
:host {
8+
display: block;
9+
padding: 10px;
10+
border: 2px solid #000;
11+
background: blue;
12+
color: white;
13+
}
14+
`,
15+
})
16+
export class SsrWrapShadowCmp {
17+
@Prop() selected: boolean;
18+
19+
render() {
20+
return (
21+
<div
22+
class={{
23+
selected: this.selected,
24+
}}
25+
>
26+
Nested component:
27+
<ssr-shadow-cmp>
28+
<slot />
29+
</ssr-shadow-cmp>
30+
</div>
31+
);
32+
}
33+
}

0 commit comments

Comments
 (0)