server.test.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import { LitElement, html } from 'lit';
  2. import { describe, it } from 'node:test';
  3. import * as assert from 'node:assert/strict';
  4. // Must come after lit import because @lit/reactive-element defines
  5. // globalThis.customElements which the server shim expects to be defined.
  6. import server from '../server.js';
  7. import * as cheerio from 'cheerio';
  8. const { check, renderToStaticMarkup } = server;
  9. describe('check', () => {
  10. it('should be false with no component', async () => {
  11. assert.equal(await check(), false);
  12. });
  13. it('should be false with a registered non-lit component', async () => {
  14. const tagName = 'non-lit-component';
  15. // Lit no longer shims HTMLElement globally, so we need to do it ourselves.
  16. if (!globalThis.HTMLElement) {
  17. globalThis.HTMLElement = class {};
  18. }
  19. customElements.define(tagName, class TestComponent extends HTMLElement {});
  20. assert.equal(await check(tagName), false);
  21. });
  22. it('should be true with a registered lit component', async () => {
  23. const tagName = 'lit-component';
  24. customElements.define(tagName, class extends LitElement {});
  25. assert.equal(await check(tagName), true);
  26. });
  27. });
  28. describe('renderToStaticMarkup', () => {
  29. it('should throw error if trying to render an unregistered component', async () => {
  30. const tagName = 'non-registrered-component';
  31. try {
  32. await renderToStaticMarkup(tagName);
  33. } catch (e) {
  34. assert.equal(e instanceof TypeError, true);
  35. }
  36. });
  37. it('should render empty component with default markup', async () => {
  38. const tagName = 'nothing-component';
  39. customElements.define(tagName, class extends LitElement {});
  40. const render = await renderToStaticMarkup(tagName);
  41. assert.deepEqual(render, {
  42. html: `<${tagName}><template shadowroot="open" shadowrootmode="open"><!--lit-part--><!--/lit-part--></template></${tagName}>`,
  43. });
  44. });
  45. it('should render component with default markup', async () => {
  46. const tagName = 'simple-component';
  47. customElements.define(
  48. tagName,
  49. class extends LitElement {
  50. render() {
  51. return html`<p>hola</p>`;
  52. }
  53. }
  54. );
  55. const render = await renderToStaticMarkup(tagName);
  56. const $ = cheerio.load(render.html);
  57. assert.equal($(`${tagName} template`).html().includes('<p>hola</p>'), true);
  58. });
  59. it('should render component with properties and attributes', async () => {
  60. const tagName = 'props-and-attrs-component';
  61. const attr1 = 'test';
  62. const prop1 = 'Daniel';
  63. customElements.define(
  64. tagName,
  65. class extends LitElement {
  66. static properties = {
  67. prop1: { type: String },
  68. };
  69. constructor() {
  70. super();
  71. this.prop1 = 'someone';
  72. }
  73. render() {
  74. return html`<p>Hello ${this.prop1}</p>`;
  75. }
  76. }
  77. );
  78. const render = await renderToStaticMarkup(tagName, { prop1, attr1 });
  79. const $ = cheerio.load(render.html);
  80. assert.equal($(tagName).attr('attr1'), attr1);
  81. assert.equal($(`${tagName} template`).text().includes(`Hello ${prop1}`), true);
  82. });
  83. it('should render nested components', async () => {
  84. const tagName = 'parent-component';
  85. const childTagName = 'child-component';
  86. customElements.define(
  87. childTagName,
  88. class extends LitElement {
  89. render() {
  90. return html`<p>child</p>`;
  91. }
  92. }
  93. );
  94. customElements.define(
  95. tagName,
  96. class extends LitElement {
  97. render() {
  98. return html`<child-component></child-component>`;
  99. }
  100. }
  101. );
  102. const render = await renderToStaticMarkup(tagName);
  103. const $ = cheerio.load(render.html);
  104. assert.equal($(`${tagName} template`).text().includes('child'), true);
  105. // Child component should have `defer-hydration` attribute so it'll only
  106. // hydrate after the parent hydrates
  107. assert.equal($(childTagName).attr('defer-hydration'), '');
  108. });
  109. it('should render DSD attributes based on shadowRootOptions', async () => {
  110. const tagName = 'shadow-root-options-component';
  111. customElements.define(
  112. tagName,
  113. class extends LitElement {
  114. static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true };
  115. }
  116. );
  117. const render = await renderToStaticMarkup(tagName);
  118. assert.deepEqual(render, {
  119. html: `<${tagName}><template shadowroot=\"open\" shadowrootmode=\"open\" shadowrootdelegatesfocus><!--lit-part--><!--/lit-part--></template></${tagName}>`,
  120. });
  121. });
  122. });