Quiero probar el contenido de una ranura en uno de mis componentes personalizados. Si uso mi componente en un archivo html y lo abro en un navegador, todo funciona según lo previsto. Sin embargo, si quiero automatizar mi prueba con broma, falla. A continuación se muestra un ejemplo de trabajo mínimo con la broma del formulario de salida:
marcador de posición.js:
const template = document.createElement("template"); template.innerHTML = ` <p> <slot></slot> </p> `; class Placeholder extends HTMLElement { constructor() { super(); this.attachShadow({ mode: "open" }); this.shadowRoot.appendChild(template.content.cloneNode(true)); } get name() { return this.shadowRoot.querySelector("slot").innerText; } } window.customElements.define("place-holder", Placeholder); export default Placeholder;marcador de posición.prueba.js:
import Placeholder from "../src/placeholder.js"; describe("name is 'Lorem Ipsum'", () => { let ph; beforeAll(() => { ph = new Placeholder(); const textNode = document.createTextNode("Lorem Ipsum"); ph.appendChild(textNode); }); test("if the name is 'Lorem Ipsum'", () => { expect(ph.name).toBe("Lorem Ipsum"); }); });producción:
name is 'Lorem Ipsum' › if the name is 'Lorem Ipsum' expect(received).toBe(expected) // Object.is equality Expected: "Lorem Ipsum" Received: undefined 11 | 12 | test("if the name is 'Lorem Ipsum'", () => { > 13 | expect(ph.name).toBe("Lorem Ipsum"); | ^ 14 | }); 15 | }); at Object.<anonymous> (test/placeholder.test.js:13:25) at TestScheduler.scheduleTests (node_modules/@jest/core/build/TestScheduler.js:333:13) at runJest (node_modules/@jest/core/build/runJest.js:387:19) at _run10000 (node_modules/@jest/core/build/cli/index.js:408:7) at runCLI (node_modules/@jest/core/build/cli/index.js:261:3)undefined . ¿Como puedó resolver esté problema?El nodo de texto no formará parte de las partes internas del elemento <slot> . Es solo un envoltorio para el nodo de texto. Para obtener los nodos que se colocan dentro de la ranura, debe usar el método HTMLSlotElement.assignedNodes() .
El método addedNodes() de la interfaz HTMLSlotElement devuelve una secuencia de los nodos asignados a esta ranura.
Con esto obtienes una matriz de nodos que residen en la ranura. El nodo de texto agregado estará en esta matriz.
Modifiqué su captador de name para obtener el primer nodo de la matriz de nodos asignados y devolver el valor de textContent del nodo.
const template = document.createElement("template"); template.innerHTML = ` <p> <slot></slot> </p> `; class Placeholder extends HTMLElement { constructor() { super(); this.attachShadow({ mode: "open" }); this.shadowRoot.appendChild(template.content.cloneNode(true)); } get name() { const slot = this.shadowRoot.querySelector("slot"); const [name] = slot.assignedNodes(); if (!name) { return '' } return name.textContent } connectedCallback() { console.log(this.name) } } window.customElements.define("place-holder", Placeholder); <place-holder>Hello</place-holder> Nota al margen: el elemento <slot> tendrá un texto innerText cada vez que agregue texto dentro de la ranura en la plantilla como marcador de posición.
class ExampleElement extends HTMLElement { constructor() { super(); this.attachShadow({ mode: "open" }); this.shadowRoot.innerHTML = ` <slot>Placeholder text</slot> `; } get placeholder() { const slot = this.shadowRoot.querySelector('slot'); return slot.innerText; } connectedCallback() { console.log(this.placeholder) } } customElements.define('example-element', ExampleElement); <example-element></example-element>