Versiones comparadas

Clave

  • Se ha a帽adido esta l铆nea.
  • Se ha eliminado esta l铆nea.
  • El formato se ha cambiado.

Subdirecci贸n de las Tecnolog铆as de la Informaci贸n y Comunicaciones

脕rea de Gobernanza y Calidad

Table Excerpt Include
nameLOGO_JUNTA
merge-tablestrue
pageRecursos
typepage

Versi贸n

Table Excerpt Include
isFirstTimeEntertrue
statictrue
copytabletrue
v2
nameVERSION_GUIA_TESTING
merge-tablestrue
pageNorm-front-toc
transposenever
typepage

Tabla de Contenido


Tabla de contenidos
maxLevel4
indent20px
exclude.*(Versi贸n Actual|Cumplimiento Normativo|Hist贸rico de cambios|Subdirecci贸n de las Tecnolog铆as de la Informaci贸n y Comunicaciones|脕rea de Gobernanza y Calidad|Tabla de Contenido)

Uso de las Gu铆as de Desarrollo


Advertencia

Las gu铆as de desarrollo son un documento que busca facilitar el onboarding y la homogeneidad de los proyectos en la STIC. La STIC podr谩 estudiar los casos excepcionales los cuales ser谩n gestionados a trav茅s de los responsables del proyecto correspondiente y autorizados por el 脕rea de Gobernanza de la STIC. Asimismo cualquier aspecto no recogido en estas gu铆as deber谩 regirse en primera instancia por las gu铆as t茅cnicas correspondientes al esquema nacional de seguridad y esquema nacional de interoperabilidad seg煤n correspondencia y en su defecto a los marcos normativos y de desarrollo software establecidos por la Junta de Andaluc铆a, debiendo ser puesto de manifiesto ante la STIC.

La STIC se reserva el derecho a la modificaci贸n de la gu铆a sin previo aviso, tras lo cual, notificar谩 del cambio a los actores implicados para su adopci贸n inmediata seg煤n la planificaci贸n de cada proyecto.

En el caso de que alg煤n actor considere conveniente y/o necesario el incumplimiento de alguna de las normas y/o recomendaciones, deber谩 aportar previamente la correspondiente justificaci贸n fehaciente documentada de la soluci贸n alternativa propuesta, as铆 como toda aquella documentaci贸n que le sea requerida por la STIC para proceder a su validaci贸n t茅cnica.

Contacto Arquitectura: l-arquitectura.stic@juntadeandalucia.es

Hist贸rico de cambios


Los cambios en la normativa vendr谩n acompa帽ados de un registro de las modificaciones. De este modo se podr谩 realizar un seguimiento y consultar su evoluci贸n. Orden谩ndose de mas recientes a menos recientes, prestando especial cuidado a las cabeceras de la tablas d贸nde se indican las fechas de entrada en vigor y versi贸n.

Expandir
titleHist贸rico de cambios
Versi贸nPre-release聽Adopci贸nActivaRetiroAlcance
v01r00





  • Versi贸n inicial del documento

Introducci贸n

En este documento se describir谩n las principales pautas a tener en cuenta a la hora de dise帽ar y ejecutar test en los desarrollos frontales. Importante eEl c贸digo de los ejemplos compartidos en esta gu铆a de dise帽o se puede encontrar en el espacio p煤blico B4b3l.2029

Configuraci贸n

Este apartado pretende compartir algunas configuraciones consideradas de utilidad para una correcta ejecuci贸n de los test.

Web test runner

  • Dependencias
    • @open-wc/testing

    • @types/mocha

    • @web/test-runner

    • @web/test-runner-puppeteer

    • sinon

    • puppeteer

  • Fichero de configuraci贸n del runner
    • Esta configuraci贸n permite la ejecuci贸n de los test desde typescript, realizando la transpilaci贸n de forma autom谩tica.
    • Tambi茅n est谩 configurado para funcionar en un monorepo
    • Tambi茅n permite la correcta ejecuci贸n en contenedores, requisito indispensable para la entrega en la plataforma de Jenkins
Bloque de c贸digo
languagejs
themeEmacs
titleweb-test-runner.config.mjs
collapsetrue
mport { esbuildPlugin } from '@web/dev-server-esbuild';

import { puppeteerLauncher } from '@web/test-runner-puppeteer';
import { defaultReporter } from '@web/test-runner';




export default {
  plugins: [
    esbuildPlugin({ ts: true, tsconfig: 'tsconfig.dev.json', // Aseg煤rate de que esbuild use tu tsconfig.json
      loaders: {
        '.ts': 'ts',
      } }),

  ],
  browsers: [puppeteerLauncher({ launchOptions: { args: ['--no-sandbox', '--disable-setuid-sandbox'] } })],
  reporters:[    defaultReporter({ reportTestResults: true, reportTestProgress: true })],
  nodeResolve: true,
  preserveSymlinks: true,
  rootDir: '.',
  files: ['packages/**/*.test.ts'],
  mimeTypes: {
    '**/*.ts': 'js',
  },
};


Ejemplos

Componente de ejemplo base para el test

Bloque de c贸digo
languagejava
themeEclipse
titleCodigo de un WC para los test
collapsetrue
import { html, LitElement } from "lit";
import { property } from "lit/decorators.js";
export class Example extends LitElement{

    @property({ type: String, attribute: 'some-attribute'})
    public someProperty: string = "default value";
    constructor() {
        super();
    }
    connectedCallback() {
        super.connectedCallback();
        console.debug(`Cargado componente  ${this.tagName} `);
    }
    render(): any {
        return html`<h2>componente creado</h2>
        <p id="property-value">${this.someProperty}</p>`;
    }
}
customElements.define('example-test-component', Example);

Renderizar un componente

Bloque de c贸digo
languagejava
themeEclipse
titleEjemplo de test de renderizado de un WC
collapsetrue
//Importante que los import vengas de @open-wc/testing para que tener la m谩xima compatibilidad con lit-element
import { defineCE, expect, fixture, fixtureCleanup, html, unsafeStatic} from "@open-wc/testing";
//Importamos el componente
import { Example } from "../index";

describe("Testing Lit WebComponent ", () => {
    //Se restaura el sandbox y se limpia el fixture despu茅s de cada test
    afterEach(() => {
      fixtureCleanup();
    });
  
    //test de renderizado del componente example-test-component
    it("should render a web component", async () => {
      //await fixture espera hasta que se renderice el componente
      const el = await fixture< Example >(html`<example-test-component></example-test-component>`);
      expect(el).to.exist;
      // si tiene shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
      expect(el.shadowRoot).to.exist;
    });
    it("should render a web component with random test tag", async () => {
      const tag = defineCE(class extends Example{});
      const unsafeTag = unsafeStatic(tag);
      //await fixture espera hasta que se renderice el componente
      const el = await fixture< Example >(html`<${unsafeTag}></${unsafeTag}>`);
      expect(el).to.exist;
      // si tiene shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
      expect(el.shadowRoot).to.exist;
    });
});

Propiedades Reactivas

Advertencia
titleAlerta Acoplamiento

聽 聽 聽 //Cuidado!!!!! este c贸digo genera acoplamiento al html generado por el render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
聽 聽 聽 expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('default value');

Bloque de c贸digo
languagejava
themeEclipse
titleEjemplo Testing de propiedades del componente
collapsetrue
//Importante que los import vengas de @open-wc/testing para que tener la m谩xima compatibilidad con lit-element
import { defineCE, elementUpdated, expect, fixture, fixtureCleanup, html, unsafeStatic} from "@open-wc/testing";
//Importamos el componente
import { Example } from "../index";

describe("Testing Lit WebComponent ", () => {

    //creaci贸n de un sandbox para el mock
    before(() => {
    });
    //Se restaura el sandbox y se limpia el fixture despu茅s de cada test
    afterEach(() => {
      fixtureCleanup();
    });
  
    //test de renderizado del componente example-test-component
    it("should render a default value of property", async () => {
      //await fixture espera hasta que se renderice el componente
      const el = await fixture< Example >(html`<example-test-component></example-test-component>`);
      expect(el).to.exist;
      // si tiene shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
      expect(el.shadowRoot).to.exist;

      expect(el.someProperty).to.equal('default value');
      //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('default value');
    });
    it("should render a default value of property in a web component with random test tag", async () => {
      const tag = defineCE(class extends Example{});
      const unsafeTag = unsafeStatic(tag);
      //await fixture espera hasta que se renderice el componente
      const el = await fixture< Example >(html`<${unsafeTag}></${unsafeTag}>`);
      expect(el).to.exist;
      // si tiene shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
      expect(el.shadowRoot).to.exist;
      expect(el.someProperty).to.equal('default value');
      //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('default value');
    });
    it("should render a initialize value property", async () => {
      //await fixture espera hasta que se renderice el componente
      const el = await fixture< Example >(html`<example-test-component .someProperty=${'init value'} ></example-test-component>`);
      expect(el).to.exist;
      // si tiene shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
      expect(el.shadowRoot).to.exist;
      expect(el.someProperty).to.equal('init value');
      //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('init value');
    });
     it("should render a initialize value property in a web component with random test tag", async () => {
      const tag = defineCE(class extends Example{});
      const unsafeTag = unsafeStatic(tag);
      //await fixture espera hasta que se renderice el componente
      const el = await fixture< Example >(html`<${unsafeTag} .someProperty=${'init value'}></${unsafeTag}>`);
      expect(el).to.exist;
      // si tiene shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
      expect(el.shadowRoot).to.exist;
      expect(el.someProperty).to.equal('init value');
      //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('init value');
    });
 it("should render a changed value property", async () => {
      //await fixture espera hasta que se renderice el componente
      const el = await fixture< Example >(html`<example-test-component .someProperty=${'init value'} ></example-test-component>`);
      expect(el).to.exist;
      // si tiene shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
      expect(el.shadowRoot).to.exist;
      expect(el.someProperty).to.equal('init value');
      //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('init value');
      el.someProperty = 'new value';
      await elementUpdated(el);
      expect(el.someProperty).to.equal('new value');
      //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('new value');

    });
      it("should render a changed value property in a web component with random test tag", async () => {
      const tag = defineCE(class extends Example{});
      const unsafeTag = unsafeStatic(tag);
      //await fixture espera hasta que se renderice el componente
      const el = await fixture< Example >(html`<${unsafeTag} .someProperty=${'init value'}></${unsafeTag}>`);
      expect(el).to.exist;
      // si tiene shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
      expect(el.shadowRoot).to.exist;
      expect(el.someProperty).to.equal('init value');
      //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('init value');
      el.someProperty = 'new value';
      await elementUpdated(el);
      expect(el.someProperty).to.equal('new value');
      //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('new value');
    });
    
   it("should render a reactive changed value property", async () => {
      let propertyReactiveBind = 'init value';
      //await fixture espera hasta que se renderice el componente
      const el = await fixture< Example >(html`<example-test-component .someProperty=${propertyReactiveBind} ></example-test-component>`);
      expect(el).to.exist;
      // si tiene shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
      expect(el.shadowRoot).to.exist;
      expect(el.someProperty).to.equal('init value');
      //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('init value');
      propertyReactiveBind = 'new value';
      //Tenemos que hacer esto ya que no existe un m茅todo para actualizar la propiedad de forma reactiva a trav茅s del html desde un entorno de test.
      el.someProperty = propertyReactiveBind;
      await elementUpdated(el);
      expect(el.someProperty).to.equal('new value');
      //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('new value');
    });
    it("should render a reactive changed value property in a web component with random test tag", async () => {
      let propertyReactiveBind = 'init value';
      const tag = defineCE(class extends Example{});
      const unsafeTag = unsafeStatic(tag);
      //await fixture espera hasta que se renderice el componente
      const el = await fixture< Example >(html`<${unsafeTag} .someProperty=${propertyReactiveBind}></${unsafeTag}>`);
      expect(el).to.exist;
      // si tiene shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
      expect(el.shadowRoot).to.exist;
      expect(el.someProperty).to.equal('init value');
      //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('init value');
      propertyReactiveBind = 'new value';
       //Tenemos que hacer esto ya que no existe un m茅todo para actualizar la propiedad de forma reactiva a trav茅s del html desde un entorno de test.
      el.someProperty = propertyReactiveBind;
      await elementUpdated(el);
      expect(el.someProperty).to.equal('new value');
      //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('new value');
    }); 
});

Atributos Reactivos

Advertencia
titleAlerta Acoplamiento

聽 聽 聽 //Cuidado!!!!! este c贸digo genera acoplamiento al html generado por el render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor del atributo se renderiza correctamente, no solo que se ha definido
聽 聽 聽 expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('default value');

Bloque de c贸digo
languagejava
themeEclipse
titleEjemplo Testing de atributos del componente
collapsetrue
//Importante que los import vengas de @open-wc/testing para que tener la m谩xima compatibilidad con lit-element
import { defineCE, elementUpdated, expect, fixture, fixtureCleanup, html, unsafeStatic} from "@open-wc/testing";
//Importamos el componente
import { Example } from "../index";

describe("Testing Lit WebComponent ", () => {

    //creaci贸n de un sandbox para el mock
    before(() => {
    });
    //Se restaura el sandbox y se limpia el fixture despu茅s de cada test
    afterEach(() => {
      fixtureCleanup();
    });
  
    //test de renderizado del componente example-test-component
    it("should render a default value of attribute", async () => {
      //await fixture espera hasta que se renderice el componente
      const el = await fixture< Example >(html`<example-test-component></example-test-component>`);
      expect(el).to.exist;
      // si tiene shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
      expect(el.shadowRoot).to.exist;
      expect(el.getAttribute('some-attribute')).to.not.exist;
      expect(el.someProperty).to.equal('default value');
      //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('default value');
    });
    it("should render a default value of attribute in a web component with random test tag", async () => {
      const tag = defineCE(class extends Example{});
      const unsafeTag = unsafeStatic(tag);
      //await fixture espera hasta que se renderice el componente
      const el = await fixture< Example >(html`<${unsafeTag}></${unsafeTag}>`);
      expect(el).to.exist;
      // si tiene shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
      expect(el.shadowRoot).to.exist;
      expect(el.getAttribute('some-attribute')).to.not.exist;
      expect(el.someProperty).to.equal('default value');
      //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('default value');
    });
    it("should render a initialize value attribute", async () => {
      //await fixture espera hasta que se renderice el componente
      const el = await fixture< Example >(html`<example-test-component some-attribute=${'init value'} ></example-test-component>`);
      expect(el).to.exist;
      // si tiene shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
      expect(el.shadowRoot).to.exist;
      expect(el.getAttribute('some-attribute')).to.equal('init value');
      expect(el.someProperty).to.equal('init value');
      //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('init value');
    });
     it("should render a initialize value attribute in a web component with random test tag", async () => {
      const tag = defineCE(class extends Example{});
      const unsafeTag = unsafeStatic(tag);
      //await fixture espera hasta que se renderice el componente
      const el = await fixture< Example >(html`<${unsafeTag} some-attribute=${'init value'}></${unsafeTag}>`);
      expect(el).to.exist;
      // si tiene shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
      expect(el.shadowRoot).to.exist;
      expect(el.getAttribute('some-attribute')).to.equal('init value');
      expect(el.someProperty).to.equal('init value');
      //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('init value');
    });
    it("should render a changed value attribute", async () => {
      //await fixture espera hasta que se renderice el componente
      const el = await fixture< Example >(html`<example-test-component some-attribute=${'init value'} ></example-test-component>`);
      expect(el).to.exist;
      // si tiene shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
      expect(el.shadowRoot).to.exist;
      expect(el.getAttribute('some-attribute')).to.equal('init value');
      expect(el.someProperty).to.equal('init value');
      //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('init value');
      el.setAttribute('some-attribute', 'new value');
      await elementUpdated(el);
      expect(el.getAttribute('some-attribute')).to.equal('new value');
      expect(el.someProperty).to.equal('new value');
      //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('new value');

    });
    it("should render a changed value attribute in a web component with random test tag", async () => {
      const tag = defineCE(class extends Example{});
      const unsafeTag = unsafeStatic(tag);
      //await fixture espera hasta que se renderice el componente
      const el = await fixture< Example >(html`<${unsafeTag} some-attribute=${'init value'}></${unsafeTag}>`);
      expect(el).to.exist;
      // si tiene shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
      expect(el.shadowRoot).to.exist;
      expect(el.getAttribute('some-attribute')).to.equal('init value');
      expect(el.someProperty).to.equal('init value');
      //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('init value');
      el.setAttribute('some-attribute', 'new value');
      await elementUpdated(el);
      expect(el.getAttribute('some-attribute')).to.equal('new value');
      expect(el.someProperty).to.equal('new value');
      //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('new value');
    });
    it("should render a reactive changed value attribute", async () => {
      let propertyReactiveBind = 'init value';
      //await fixture espera hasta que se renderice el componente
      const el = await fixture< Example >(html`<example-test-component some-attribute=${propertyReactiveBind} ></example-test-component>`);
      expect(el).to.exist;
      // si tiene shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
      expect(el.shadowRoot).to.exist;
      expect(el.getAttribute('some-attribute')).to.equal('init value');
      expect(el.someProperty).to.equal('init value');
      //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('init value');
      propertyReactiveBind = 'new value';
        //Tenemos que hacer esto ya que no existe un m茅todo para actualizar la propiedad de forma reactiva a trav茅s del html desde un entorno de test.
        el.setAttribute('some-attribute', propertyReactiveBind);
      await elementUpdated(el);
      expect(el.getAttribute('some-attribute')).to.equal('new value');
      expect(el.someProperty).to.equal('new value');
      //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('new value');
    });
    it("should render a reactive changed value attribute in a web component with random test tag", async () => {
      let propertyReactiveBind = 'init value';
      const tag = defineCE(class extends Example{});
      const unsafeTag = unsafeStatic(tag);
      //await fixture espera hasta que se renderice el componente
      const el = await fixture< Example >(html`<${unsafeTag} some-attribute=${propertyReactiveBind}></${unsafeTag}>`);
      expect(el).to.exist;
      // si tiene shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
      expect(el.shadowRoot).to.exist;
      expect(el.getAttribute('some-attribute')).to.equal('init value');
      expect(el.someProperty).to.equal('init value');
      //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('init value');
      propertyReactiveBind = 'new value';
      //Tenemos que hacer esto ya que no existe un m茅todo para actualizar la propiedad de forma reactiva a trav茅s del html desde un entorno de test.
      el.setAttribute('some-attribute', propertyReactiveBind);
      await elementUpdated(el);
      expect(el.getAttribute('some-attribute')).to.equal('new value');
      expect(el.someProperty).to.equal('new value');
      //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('new value');
    });
});
Renderizar un componente customizado

Captura de eventos

Bloque de c贸digo
languagejava
themeEclipse
titleEjemplo de test de captura de eventos emitidos por un componente customizado
collapsetrue
//Importante que los import vengas de @open-wc/testing para que tener la m谩xima compatibilidad con lit-element
import { defineCE, expect, fixture, fixtureCleanup, html, oneEvent, unsafeStatic } from "@open-wc/testing";
//Importamos el componente
import { LitElementExample } from "lit../src/index";
//Creaci贸n de un componente LitElement din谩mico
const customElementWithProperties = defineCE(
  class extends LitElement{
    static properties = {
      someProperty: { type: String },
    };
    constructor()
describe("Testing Lit WebComponent ", () => {
    //Se restaura el sandbox y se limpia el fixture despu茅s de cada test
    afterEach(() => {
      superfixtureCleanup();
    });
  
  connectedCallback() {
 //test de renderizado del  super.connectedCallback();componente example-test-component
      console.debug(`Cargado componente  ${this.tagName} `);
    }
    render(): anyit("should receive a web component custom event", async () => {
      //await returnfixture html`<h2>componenteespera creado STAND-ALONE</h2>`;
    }
  }
);

//Obtenci贸n del tag del componente para su renderizado din谩mico
const customElementWithPropertiesTag = unsafeStatic(customElementWithProperties);

//Definici贸n de la suit
describe("Testing Lit WebComponent ", () => {
  //Se restaura el sandbox y se limpia el fixture despu茅s de cada test
  afterEach(() => {
    fixtureCleanup();
  });

  //test de renderizado del componente customizado
  it("should render a web component", async () => {
     //await fixture espera hasta que se renderice el componente
    const el = await fixture< LitElement >(html`<${customElementWithPropertiesTag}></${customElementWithPropertiesTag}`);
    expect(el).to.exist;
    // si tiene shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
    expect(el.shadowRoot).to.exist;
  });
});

Ejecuci贸n

Depuraci贸n

Navegadores

hasta que se renderice el componente
      const el = await fixture< Example >(html`<example-test-component></example-test-component>`);
      expect(el).to.exist;
      // si tiene shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
      expect(el.shadowRoot).to.exist;
      setTimeout(() => el.fireEvent());

      const { detail } = await oneEvent(el, 'example-event');
      expect(detail).to.deep.equal ({ message: "Hello world" });
    });
    it("should receive a web component custom event with random test tag", async () => {
      const tag = defineCE(class extends Example{});
      const unsafeTag = unsafeStatic(tag);
      //await fixture espera hasta que se renderice el componente
      const el = await fixture< Example >(html`<${unsafeTag}></${unsafeTag}>`);
      expect(el).to.exist;
      // si tiene shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
      expect(el.shadowRoot).to.exist;
      setTimeout(() => el.fireEvent());

      const { detail } = await oneEvent(el, 'example-event');
      expect(detail).to.deep.equal({ message: "Hello world" });
    });
});

Renderizar un componente customizado

Bloque de c贸digo
languagejava
themeEclipse
titleEjemplo de test de componente customizado
collapsetrue
//Importante que los import vengas de @open-wc/testing para que tener la m谩xima compatibilidad con lit-element
import { defineCE, expect, fixture, fixtureCleanup, html, unsafeStatic } from "@open-wc/testing";
import { LitElement } from "lit";
//Creaci贸n de un componente LitElement din谩mico
const customElementWithProperties = defineCE(
  class extends LitElement{
    static properties = {
      someProperty: { type: String },
    };
    constructor() {
      super();
    }
    connectedCallback() {
      super.connectedCallback();
      console.debug(`Cargado componente  ${this.tagName} `);
    }
    render(): any {
      return html`<h2>componente creado STAND-ALONE</h2>`;
    }
  }
);

//Obtenci贸n del tag del componente para su renderizado din谩mico
const customElementWithPropertiesTag = unsafeStatic(customElementWithProperties);

//Definici贸n de la suit
describe("Testing Lit WebComponent ", () => {
  //Se restaura el sandbox y se limpia el fixture despu茅s de cada test
  afterEach(() => {
    fixtureCleanup();
  });

  //test de renderizado del componente customizado
  it("should render a web component", async () => {
     //await fixture espera hasta que se renderice el componente
    const el = await fixture< LitElement >(html`<${customElementWithPropertiesTag}></${customElementWithPropertiesTag}`);
    expect(el).to.exist;
    // si tiene shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
    expect(el.shadowRoot).to.exist;
  });
});


Ejecuci贸n

Depuraci贸n

Navegadores

Iframe

Advertencia
titleAdvertencia sobre la carga de m贸dulos

Un iframe genera un contexto independiente para la ejecuci贸n del c贸digo alojado dentro de 茅l. Esto implica que se debe incluir las dependencias necesarias para la ejecuci贸n de forma manual.


Advertencia
titleAdvertencia sobre el acceso a los m贸dulos

Web Test Runner (WTR) genera la transpilaci贸n de los elemento en memoria. Esto implica que los ficheros js resultantes no est谩n disponibles para importarlos dentro del iframe. Para poder acceder a ellos se debe:

  • Antes de ejecutar un test que vaya a renderizar un componente dentro de un iframe, se deber谩 ejecutar una transpilaci贸n previa del c贸digo a testear.聽
  • El import debe apuntar a la ruta donde se haya generado el c贸digo que se desea importar.
Advertencia
titleAdvertencia sobre el c贸digo
El c贸digo compartido para el ejemplo solo es v谩lido para el 谩mbito del testing por motivos de seguridad.聽 En ning煤n caso se crear谩 un componente que haga uso de un iframe y rellene el contenido del iframe de esta forma. Se deber谩 utilizar la manera tradicional (src) combinado con los CSP
Bloque de c贸digo
languagejava
themeEclipse
titleEjemplo de test de componente renderizado dentro de un iframe
collapsetrue
import { fixture, expect, html, elementUpdated} from "@open-wc/testing";
import { Example } from "../src/index";
import { LitElement } from "lit";

describe("Test Lit component inside iframe", () => {
  it("should render the Lit component inside an iframe and access shadow DOM", async () => {
    // Cargar un iframe con el componente
    const el = await fixture<HTMLIFrameElement>(html` <iframe srcdoc="${getIframeHtmlCodeForExistingComponent("example-test-component")}" width="600" height="400"></iframe> `);

    // Esperar a que el iframe se cargue completamente

    await new Promise((resolve) => {
      el.onload = () => resolve(true);
    });

    // Acceder al documento del iframe
    const iframeDocument = el.contentDocument!;
    const exampleComponent = iframeDocument.querySelector<Example>("example-test-component");

    // Verificar que el componente Lit se ha renderizado dentro del iframe
    expect(exampleComponent).to.exist;

    // Esperar a que se complete la actualizaci贸n del componente Lit dentro del iframe
    await elementUpdated(exampleComponent!);
    // si tiene shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
    expect(exampleComponent?.shadowRoot).to.exist;
    // Verificar el contenido renderizado del shadow DOM

    expect(exampleComponent?.someProperty).to.equal("default value");
    //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
    expect(exampleComponent?.shadowRoot?.getElementById("property-value")?.textContent).to.equal("default value");
  });

  it("should render the Lit component with random tag inside an iframe and access shadow DOM", async () => {
    const tag = 'example-test-component-' + Math.random().toString(36).substring(7);
    // Cargar un iframe con el componente
    const el = await fixture<HTMLIFrameElement>(html` <iframe srcdoc="${getIframeHtmlCodeForCustomComponent(tag)}" width="600" height="400"></iframe> `);

    // Esperar a que el iframe se cargue completamente

    await new Promise((resolve) => {
      el.onload = () => resolve(true);
    });

    // Acceder al documento del iframe
    const iframeDocument = el.contentDocument!;
    const exampleComponent = iframeDocument.querySelector<LitElement>(tag);

    // Verificar que el componente Lit se ha renderizado dentro del iframe
    expect(exampleComponent).to.exist;

    // Esperar a que se complete la actualizaci贸n del componente Lit dentro del iframe
    await elementUpdated(exampleComponent!);
    // si tiene shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
    expect(exampleComponent?.shadowRoot).to.exist;
    //Cuidado!!!!! este c贸digo genera acoplamiento al render del componente, no es recomendable ya que los test deben ser funcionales. Nos sirve para testear que el valor de la propiedad se renderiza correctamente, no solo que se ha definido
    expect(exampleComponent?.shadowRoot?.getElementById("html-iframe-rendered")?.textContent).to.equal("testing");
  });
});

const getIframeHtmlCodeForExistingComponent = (componentName: string) => {
  return `<html>
    <head>
        <!-- Incluir los m贸dulos de Lit desde el propio servidor de testing-->
        <script type='module' src='${window.location.origin}/node_modules/lit/index.js'></script>
        <!-- Importar el componente -->
        <script type='module'>
        import '/dist/src/index.js';
        </script>
    </head>
    <body><${componentName}></${componentName}></body></html>`;
};

const getIframeHtmlCodeForCustomComponent = (componentName: string) => {
  return `<html>
    <head>
        
        <script type='module'>
       //Incluir los m贸dulos de Lit desde el propio servidor de testing
        import { LitElement, html } from "${window.location.origin}/node_modules/lit/index.js";

    //Definir el componente
        customElements.define(
          '${componentName}',
          class extends LitElement {
               static get properties() {
                  return {
                    somePropertyInsideIframe: { type: String }
                  };
                }
                constructor() {
                  super(); 
                }
                connectedCallback() {
                  super.connectedCallback();
                  console.log("Cargado componente ${componentName} dentro del iframe");
                }
                //Importante los caracteres especiales se deben escapar con \ para que no se interpreten como caracteres especiales
                render() {
                  return html\`<p id='html-iframe-rendered'>testing</p>\`;
                }
              }
        );
        </script>
    </head>
    <body><${componentName}></${componentName}></body></html>`;
};

Normativa

Table Excerpt Include
isFirstTimeEntertrue
v2
nameNORMATIVA_FRONT_CONT
merge-tablestrue
pageGOBP:TOC FRONT: Normativa, gu铆as y recomendaciones
transposenever
typepage

Gu铆as de desarrollo

Table Excerpt Include
isFirstTimeEntertrue
v2
nameGUIA_IMPL_FRONT_CONT
merge-tablestrue
pageGOBP:TOC FRONT: Normativa, gu铆as y recomendaciones
transposenever
typepage

Gu铆as de dise帽o

Table Excerpt Include
isFirstTimeEntertrue
v2
nameGUIA_DIS_FRONT_CONT
merge-tablestrue
pageGOBP:TOC FRONT: Normativa, gu铆as y recomendaciones
transposenever
typepage