Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions src/wcc.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,14 @@ async function renderComponentRoots(tree, includeShadowRoots = true) {
const { tagName } = node;
const { moduleURL } = definitions[tagName];
const elementInstance = await initializeCustomElement(moduleURL, tagName, node.attrs);

const shadowRootHtml = elementInstance.getInnerHTML({ includeShadowRoots });
const shadowRootTree = parseFragment(shadowRootHtml);

node.childNodes = node.childNodes.length === 0 ? shadowRootTree.childNodes : [...shadowRootTree.childNodes, ...node.childNodes];
const elementHtml = elementInstance.shadowRoot
? elementInstance.getInnerHTML({ includeShadowRoots })
: elementInstance.innerHTML;
const elementTree = parseFragment(elementHtml);

node.childNodes = node.childNodes.length === 0
? elementTree.childNodes
: [...elementTree.childNodes, ...node.childNodes];
}

if (node.childNodes && node.childNodes.length > 0) {
Expand Down Expand Up @@ -130,7 +133,9 @@ async function renderToString(elementURL, options = {}) {
const elementTagName = await getTagName(elementURL);
const elementInstance = await initializeCustomElement(elementURL);

const elementHtml = elementInstance.getInnerHTML({ includeShadowRoots });
const elementHtml = elementInstance.shadowRoot
? elementInstance.getInnerHTML({ includeShadowRoots })
: elementInstance.innerHTML;
const elementTree = getParse(elementHtml)(elementHtml);
const finalTree = await renderComponentRoots(elementTree, includeShadowRoots);
const html = !lightMode && elementTagName ? `
Expand Down
79 changes: 79 additions & 0 deletions test/cases/light-dom/light-dom.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/*
* Use Case
* Run wcc against nested custom elements using just innerHTML to intentionally NOT render Shadow DOM.
*
* User Result
* Should return the expected HTML with no template tags or Shadow Roots.
*
* User Workspace
* src/
* components/
* navigation.js
* header.js
* pages/
* index.js
*/
import chai from 'chai';
import { JSDOM } from 'jsdom';
import { renderToString } from '../../../src/wcc.js';

const expect = chai.expect;

describe('Run WCC For ', function() {
const LABEL = 'Nested Custom Element using only innerHTML (no Shadow DOM)';
let dom;

before(async function() {
const { html } = await renderToString(new URL('./src/pages/index.js', import.meta.url));

dom = new JSDOM(html);
});

describe(LABEL, function() {
it('should not have any <template> tags within the document', function() {
expect(dom.window.document.querySelectorAll('template').length).to.equal(0);
});

describe('static page content', function() {
it('should have the expected static content for the page', function() {
expect(dom.window.document.querySelector('h1').textContent).to.equal('Home Page');
});
});

describe('custom header element with nested navigation element', function() {
let headerContentsDom;

before(function() {
headerContentsDom = new JSDOM(dom.window.document.querySelectorAll('header')[0].innerHTML);
});

it('should have a <header> tag within the document', function() {
expect(dom.window.document.querySelectorAll('header').length).to.equal(1);
});

it('should have expected content within the <header> tag', function() {
const content = headerContentsDom.window.document.querySelector('a h4').textContent;

expect(content).to.contain('My Personal Blog');
});

describe('nested navigation element', function() {
let navigationContentsDom;

before(function() {
navigationContentsDom = new JSDOM(dom.window.document.querySelectorAll('wcc-navigation')[0].innerHTML);
});

it('should have a <nav> tag within the <template> shadowroot', function() {
expect(navigationContentsDom.window.document.querySelectorAll('nav').length).to.equal(1);
});

it('should have three links within the <nav> element', function() {
const links = navigationContentsDom.window.document.querySelectorAll('nav ul li a');

expect(links.length).to.equal(3);
});
});
});
});
});
37 changes: 37 additions & 0 deletions test/cases/light-dom/src/components/header.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import './navigation.js';

class Header extends HTMLElement {
connectedCallback() {
this.innerHTML = this.render();
}

render() {
return `
<header>
<div>
<a href="/">
<img src="/www/assets/greenwood-logo.jpg" alt="Greenwood logo"/>
<h4>My Personal Blog</h4>
</a>
</div>

<wcc-navigation></wcc-navigation>

<div class="social">
<a href="https://github.com/ProjectEvergreen/greenwood">
<img
src="https://img.shields.io/github/stars/ProjectEvergreen/greenwood.svg?style=social&logo=github&label=github"
alt="Greenwood GitHub badge"
class="github-badge"/>
</a>
</div>
</header>
`;
}
}

export {
Header
};

customElements.define('wcc-header', Header);
23 changes: 23 additions & 0 deletions test/cases/light-dom/src/components/navigation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const template = document.createElement('template');

template.innerHTML = `
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
<li><a href="/artists">Artists</a></li>
<ul>
</nav>
`;

class Navigation extends HTMLElement {
connectedCallback() {
this.appendChild(template.content.cloneNode(true));
}
}

export {
Navigation
};

customElements.define('wcc-navigation', Navigation);
16 changes: 16 additions & 0 deletions test/cases/light-dom/src/pages/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import '../components/header.js';

export default class HomePage extends HTMLElement {

connectedCallback() {
this.innerHTML = this.getTemplate();
}

getTemplate() {
return `
<wcc-header></wcc-header>

<h1>Home Page</h1>
`;
}
}