Versiones comparadas

Clave

  • Se ha añadido esta línea.
  • Se ha eliminado esta línea.
  • El formato se ha cambiado.
Comentarios: Publicación

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 documentados, 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
v01r00
VersiónPre-release AdopciónActivaRetiroAlcance
1.0.0

1.0.0

 

--
  • Versión inicial del documento

Version history
dateFormatdd-MM-yyyyy
first1


Introducción

En este documento se describirán las los principales pautas aspectos a tener en cuenta a la hora de diseñar y ejecutar test en los desarrollos frontales, que serán ejecutables dentro de los procesos de IC de la STIC.

El 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-puppeteerplaywright

    • sinon

    • puppeteerplaywright

  • 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
languagejsjava
themeEmacsEclipse
titleweb-test-runner.config.mjs
collapsetrue
mport// Este archivo es la configuración de Web Test Runner. Aquí puedes configurar los plugins, los navegadores, los reporters, etc.
import { esbuildPlugin } from '@web/dev-server-esbuild';

import { puppeteerLauncherplaywrightLauncher } from '@web/test-runner-puppeteerplaywright';
import { defaultReporter } from '@web/test-runner';

function playwrightLauncherExtended(options, browserName) {
  const launcher = playwrightLauncher(options);
  launcher.name = browserName??launcher.name;
  return launcher;
}

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

  ],
  browsers: [puppeteerLauncher
    playwrightLauncherExtended({
    launchOptions: { argsproduct: ['--no-sandboxchromium', '--disable-setuid-sandbox'] } })],
  reporters:[
      launchOptions: {
     defaultReporter({ reportTestResults: true, reportTestProgresschannel: true })]'chrome',
  nodeResolve: true,
  preserveSymlinks: true},
    rootDir:}, '.Chrome'), // Lanza Chromium
    playwrightLauncherExtended({
      filesproduct: ['packages/**/*.test.ts'],
  mimeTypes'chromium',
      launchOptions: {
        '**/*.ts'channel: 'jsmsedge',
      },
};

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'})'Microsoft Edge'),
    playwrightLauncherExtended({
      product: 'firefox',
    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);}, 'Mozilla Firefox') // Lanza Firefox
  ],
  reporters: [defaultReporter({ reportTestResults: true, reportTestProgress: true })],
  nodeResolve: true,
  preserveSymlinks: true,
  rootDir: '.',
  files: ['test/**/*.test.ts'],
  mimeTypes: {
    '**/*.ts': 'js',
  }
};

package.json

Bloque de código
languagejs
themeEclipse
titlepackage.json
collapsetrue
{
  ....
  "scripts": {
	"test": "wtr --coverage",
    "test:debug": "wtr --debug --watch",
    "build:dev":"tsc --project tsconfig.dev.json",
    "build":"npm i -ddd && tsc",
    "postinstall": "npx playwright install --with-deps"
  },
  "devDependencies": {
....
    "@open-wc/testing": "4.0.0",
    "@types/mocha": "10.0.9",
    "@web/dev-server-esbuild": "1.0.2",
    "@web/test-runner": "0.19.0",
    "@web/test-runner-playwright": "0.11.0",
    "lit": "2.7.4",
    "playwright": "1.48.1",
    "sinon": "19.0.2",
    "typescript": "5.6.3"
....
  },
 ...
}


tsconfig.json

Bloque de código
languagejs
themeEclipse
titletsconfig.json
collapsetrue
{
  "compilerOptions": {
    "target": "es2018",
    "module": "esnext",
    "moduleResolution": "node",
    "noEmitOnError": true,
    "lib": ["es2017", "dom"],
    "strict": true,
    "esModuleInterop": false,
    "allowSyntheticDefaultImports": true,
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
    "importHelpers": true,
    "outDir": "dist",
    "sourceMap": true,
    "inlineSources": true,
    "rootDir": ".",
    "declaration": true,
    "declarationMap": true
  },
  "include": ["./src/**/*.ts"],
  "exclude": [
    "./dist","./node_modules"
  ]
}

tsconfig.dev.json

Bloque de código
languagejs
themeEclipse
titletsconfig.dev.json
collapsetrue
 {
  "extends": "./tsconfig.json",
  "compilerOptions": {  
    "declarationDir": "./types/"
  }
}

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

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ónSe derestaura unel sandbox paray se limpia 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 propertyweb 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;

      expect(el.someProperty).to.equal('default value'});
    it("should  //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 definidorender 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
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('default value');
    }const el = await fixture< Example >(html`<${unsafeTag}></${unsafeTag}>`);
    it("should render a default value of property in a web component with random test tag", async () => {
      const tag = defineCE(class extends Example{}); expect(el).to.exist;
      // si tiene shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
      const unsafeTag = unsafeStatic(tag)expect(el.shadowRoot).to.exist;
      //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});
});

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 ",
      //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 () => {

      //awaitcreación fixturede esperaun hasta que se rendericesandbox para el componentemock
    before(()  const el = await fixture< Example >(html`<example-test-component .someProperty=${'init value'} ></example-test-component>`=> {
    });
    //Se restaura expect(el).to.exist;
 sandbox y se limpia el //fixture sidespués tienede shadowRootcada estest
 que es un webcomponent y que se ha renderizado de forma correctaafterEach(() => {
      expectfixtureCleanup(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 definidotest 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.shadowRoot?.getElementById("property-value")?.textContent).to.equal('init value')exist;
    });
  // si tiene it("should render a initialize value property in a web component with random test tag", async () => {shadowRoot es que es un webcomponent y que se ha renderizado de forma correcta
      const tag = defineCE(class extends Example{});expect(el.shadowRoot).to.exist;

      const unsafeTag = unsafeStatic(tagexpect(el.someProperty).to.equal('default value');
      //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 correctaCuidado!!!!! 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).to.exist;
      expect(el.someProperty?.getElementById("property-value")?.textContent).to.equal('initdefault value');
    });
    it("should render  //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 definidoa 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
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('init value');
    }const el = await fixture< Example >(html`<${unsafeTag}></${unsafeTag}>`);
 it("should render a changed value property", async () => { expect(el).to.exist;
      //await fixture espera hasta si tiene shadowRoot es que es un webcomponent y que se ha renderizado rendericede elforma componentecorrecta
      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.expect(el.shadowRoot).to.exist;
      expect(el.someProperty).to.equal('initdefault 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('initdefault value');
    });
  el.someProperty = 'new value';
      await elementUpdated(el);
      expect(el.someProperty).to.equal('new value'); it("should render a initialize value property", async () => {
      //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 soloawait 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 definido renderizado de forma correcta
      expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.exist;
      expect(el.someProperty).to.equal('newinit value');

     });
      it("should //Cuidado!!!!! este código genera acoplamiento al render adel changedcomponente, valueno propertyes inrecomendable aya webque component withlos random test tag",deben asyncser () => {
      const tag = defineCE(class extends Example{});
      const unsafeTag = unsafeStatic(tagfuncionales. 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');
    });
  //await fixture espera hasta que se renderice el componente
      const el = await fixture< Example 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');
    });
  el.someProperty = 'new value';it("should render a changed value property", async () => {
      //await elementUpdated(el);
fixture espera hasta que se renderice el componente
      const el  expect(el.someProperty).to.equal('new value'= await fixture< Example >(html`<example-test-component .someProperty=${'init value'} ></example-test-component>`);
      //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 definidoexpect(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.shadowRoot?.getElementById("property-value")?.textContentsomeProperty).to.equal('newinit value');
    });
  //Cuidado!!!!! este 
código genera acoplamiento it("shouldal render adel reactivecomponente, changedno valuees property",recomendable asyncya ()que =>los {
test deben ser funcionales. Nos sirve letpara propertyReactiveBindtestear =que 'init value';
      //await fixture espera hasta que se renderice el componente
 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');
     const el.someProperty = await fixture< Example >(html`<example-test-component .someProperty=${propertyReactiveBind} ></example-test-component>`'new value';
      await elementUpdated(el);
      expect(el.someProperty).to.existequal('new value');
      // 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 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('initnew 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 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 elementUpdated(el);
 fixture espera hasta que se renderice el componente
      const el  expect(el.someProperty).to.equal('new value'= 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('newinit value');
       })el.someProperty = '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 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`<${unsafeTag}html`<example-test-component .someProperty=${propertyReactiveBind} ></${unsafeTag}>`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';
});

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      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('defaultnew 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('defaultnew 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
    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('initdefault 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('initdefault value');
    });
     it("should render a initializedefault 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} 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').not.exist;
      expect(el.someProperty).to.equal('initdefault 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('initdefault value');
    });
    it("should render a changedinitialize 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'it("should render a initialize value attribute in a web component with random test tag", async () => {
      const tag = defineCE(class extends Example{});
      expect(el.someProperty).to.equal('new value')const unsafeTag = unsafeStatic(tag);
      //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 definidoawait 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?.getElementById("property-value")?.textContent).to.exist;
      expect(el.getAttribute('some-attribute')).to.equal('newinit value');

       }expect(el.someProperty).to.equal('init value');
    it("should render a changed value attribute in a web component with random test tag", async () => { //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
      const tag = defineCE(class extends Example{expect(el.shadowRoot?.getElementById("property-value")?.textContent).to.equal('init value');
    });
    it("should render a changed constvalue unsafeTagattribute", =async unsafeStatic(tag); => {
      //await fixture espera hasta que se renderice el componente
      const el = await fixture< Example >(html`<${unsafeTag}html`<example-test-component some-attribute=${'init value'} ></${unsafeTag}>`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 reactive changed value attribute in a web component with random test tag", async () => {
      letconst propertyReactiveBindtag = 'init value' defineCE(class extends Example{});
      const unsafeTag = unsafeStatic(tag);
      //await fixture espera hasta que se renderice el componente
      const el = await fixture< Example >(html`<example-test-componenthtml`<${unsafeTag} some-attribute=${propertyReactiveBind'init value'} ></example-test-component>`${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 =el.setAttribute('some-attribute', 'new value');
      await  //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(elelementUpdated(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//await tagfixture =espera defineCE(classhasta extends Example{});
      const unsafeTag = unsafeStatic(tag);
      //await fixture espera hasta que se que se renderice el componente
      const el = await fixture< Example >(html`<${unsafeTag}html`<example-test-component some-attribute=${propertyReactiveBind} ></${unsafeTag}>`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');
    });
});

Captura de eventos

Bloque de código
languagejava
themeEclipse
titleEjemplo de test de captura de eventos emitidos por un componente
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 { Example } from "../src/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 receive a web component custom event", async () => {
      //await fixture espera hasta que se renderice el componente
      const el = await fixture< Example >(html`<example-test-component></example-test-component>`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.existequal('init value');
      // si tiene shadowRoot es queCuidado!!!!! este código genera acoplamiento al render del componente, no es unrecomendable webcomponent yya que selos hatest renderizadodeben deser formafuncionales. correcta
Nos sirve para testear que  expect(el.shadowRoot).to.exist;
      setTimeout(() => el.fireEvent());

      const { detail } = await oneEvent(el, 'example-event');
      expect(detail).to.deep.equal ({ message: "Hello world" }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  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}>`= '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).to.exist.getAttribute('some-attribute')).to.equal('new value');
      // 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(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(detailel.shadowRoot?.getElementById("property-value")?.textContent).to.deep.equal({ message: "Hello world" }'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
describe("Testing Lit WebComponent ", () => {
    static//Se propertiesrestaura =el {
sandbox y se limpia el fixture someProperty:después {de type: String },cada test
    };
    constructorafterEach(() => {
      superfixtureCleanup();
    });
  
  connectedCallback() {
 //test de renderizado del  super.connectedCallback();componente example-test-component
    it("should receive console.debug(`Cargado componente  ${this.tagName} `);
    }a web component custom event", async () => {
    render(): any {
//await fixture espera hasta que se returnrenderice html`<h2>componenteel creado STAND-ALONE</h2>`;
componente
     }
  }
);

//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
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 renderreceive a web component custom event with random test tag", async () => {
     //await fixtureconst esperatag hasta que= defineCE(class extends Example{});
      const unsafeTag = unsafeStatic(tag);
      //await fixture espera hasta que se renderice el componente
      const el = await fixture< LitElementExample >(html`<${customElementWithPropertiesTagunsafeTag}></${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

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

La herramienta de ejecución de los test es el Web Test Runner (wtr).

La configuración ofrecida, permite la transpilación de forma directa por el wtr. Dicha transpilación se genera en memoria que, salvo algunos casos concretos (por ejemplo dentro de un iframe),  no tiene implicación.

Nota
titleScript

EL script utilizado es test → npm run test


Depuración

Para la depurar WTR ofrece la posiblidad de probarlo en el navegador de forma manual (opción D) y ahí poder hacer la depuración que se considere necesaria. Combinado con la opción --watch, se realizará una reejecución con cada cambio detectado.

Otra facilidad que ofrece WTR es que, de todos los test lanzados, puedes centrarte en uno solo (opción F). La lista de ficheros con test fallidos en su ejecución aparecerán en rojo.

Nota
titleScript

EL script utilizado es test → npm run test:debug

Navegadores

Se puede configurar para lanzar los test en diferentes navegadores. Por normativa, los desarrollos deben ser compatibles con los navegadores evergreen ( Chrome/Chromium, Microsoft Edge, Firefox). Safari no es obligatorio actualmente

Bloque de código
languagebash
themeDJango
titleInstalación de un navegador
npx playwright install --with-deps

Para ver diferentes opciones que ofrece el instalador podéis usar la opción de help

Bloque de código
languagebash
themeDJango
titleVisualización de opciones para instalar un navegador
npx playwright install --help

Con la configuración establecida se ejecutarán los test para todos los navegadores configurados.

Advertencia
titleAdvertencia

No está permitido el uso de playwright como parte del desarrollo y definición de los test. Solo está permitido su uso como launcher.

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
Advertencia
titleAdvertencia sobre el timeout
A veces la carga de iframe se ralentiza y supera los 2s de timeout, se recomiendo aumentar el timeout, como se muestra en el ejemplo
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 function() {
    this.timeout(10000);   => {
    // 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 function() => {{
    this.timeout(10000);  
    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