Subdirecci贸n de las Tecnolog铆as de la Informaci贸n y Comunicaciones
脕rea de Gobernanza y Calidad
Versi贸n
Guia de Testing en el Frontend
Versión: 1.0.0
Estado: Vigente
Entrada en vigor desde:
Guia de Testing en el Frontend
Versión: 1.0.0
Estado: PRE-RELEASE
Entrada en vigor desde:
Tabla de Contenido
Uso de las Gu铆as de Desarrollo
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.
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.
Versión
Pre-release
Adopción
Activa
Retiro
Alcance
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 e
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
Ejemplo de test de renderizado de un WCAmpliar origen
//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} from "@open-wc/testing";
//Librería de MOCK
import sinon from "sinon";
//Importamos el componente
import { Example } from "../index";
describe("Testing Lit WebComponent ", () => {
let sandbox: sinon.SinonSandbox;
//creación de un sandbox para el mock
before(() => {
sandbox = sinon.createSandbox();
});
//Se restaura el sandbox y se limpia el fixture después de cada test
afterEach(() => {
sandbox.restore();
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(Example);
//await fixture espera hasta que se renderice el componente
const el = await fixture< Example >(html`<${tag}></${tag}>`);
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
Alerta 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")).to.equal('default value');
Ejemplo Testing de propiedades del componenteAmpliar origen
//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} from "@open-wc/testing";
//Librería de MOCK
import sinon from "sinon";
//Importamos el componente
import { Example } from "../index";
describe("Testing Lit WebComponent ", () => {
let sandbox: sinon.SinonSandbox;
//creación de un sandbox para el mock
before(() => {
sandbox = sinon.createSandbox();
});
//Se restaura el sandbox y se limpia el fixture después de cada test
afterEach(() => {
sandbox.restore();
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.getAttribute('someProperty')).to.equal('default value');
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")).to.equal('default value');
});
it("should render a default value of property in a web component with random test tag", async () => {
const tag = defineCE(Example);
//await fixture espera hasta que se renderice el componente
const el = await fixture< Example >(html`<${tag}></${tag}>`);
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('someProperty')).to.equal('default value');
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")).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.getAttribute('someProperty')).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")).to.equal('init value');
});
it("should render a initialize value property in a web component with random test tag", async () => {
const tag = defineCE(Example);
//await fixture espera hasta que se renderice el componente
const el = await fixture< Example >(html`<${tag} .someProperty=${'init value'}></${tag}>`);
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('someProperty')).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")).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.getAttribute('someProperty')).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")).to.equal('init value');
el.someProperty = 'new value';
await elementUpdated(el);
expect(el.getAttribute('someProperty')).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")).to.equal('new value');
});
it("should render a changed value property in a web component with random test tag", async () => {
const tag = defineCE(Example);
//await fixture espera hasta que se renderice el componente
const el = await fixture< Example >(html`<${tag} .someProperty=${'init value'}></${tag}>`);
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('someProperty')).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")).to.equal('init value');
el.someProperty = 'new value';
await elementUpdated(el);
expect(el.getAttribute('someProperty')).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")).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.getAttribute('someProperty')).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")).to.equal('init value');
propertyReactiveBind = 'new value';
await elementUpdated(el);
expect(el.getAttribute('someProperty')).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")).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(Example);
//await fixture espera hasta que se renderice el componente
const el = await fixture< Example >(html`<${tag} .someProperty=${propertyReactiveBind}></${tag}>`);
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('someProperty')).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")).to.equal('init value');
propertyReactiveBind = 'new value';
await elementUpdated(el);
expect(el.getAttribute('someProperty')).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")).to.equal('new value');
});
});
Renderizar un componentecustomizado
Ejemplo de test de componente customizadoAmpliar origen
//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";
//Librería de MOCK
import sinon from "sinon";
//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 ", () => {
let sandbox: sinon.SinonSandbox;
//creación de un sandbox para el mock
before(() => {
sandbox = sinon.createSandbox();
});
//Se restaura el sandbox y se limpia el fixture después de cada test
afterEach(() => {
sandbox.restore();
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;
});
});