Prova de components a React: què i com es prova amb Jest i Enzyme?

Aquest article sobre les proves de components de reacció va ser escrit per Alona Pysarenko, Frontend Engineer de Django Stars.
Llegiu l'article original al bloc Django Stars.

Provar els components React pot ser un repte tant per a principiants com per a desenvolupadors experimentats que ja han treballat amb proves. Pot ser interessant comparar els vostres propis enfocaments amb els que fem servir en el nostre projecte. Per cobrir la base de codi, heu de saber quins components cal provar i quin codi es vol cobrir exactament en el component.

En aquest article, tractaré els temes següents:

  • Definiu l'ordre correcte de les proves unitàries en funció de l'estructura del projecte
  • Esbrineu què heu de deixar fora de la cobertura de la prova (què no proveu)
  • Determineu la necessitat de fer proves instantànies
  • Definiu què es vol provar en el component i en quin ordre
  • Proporcioneu exemples detallats de codis personalitzats

L’article suposa que teniu coneixement de com configurar Jest i Enzyme. Visiteu els llocs web oficials per obtenir informació sobre la instal·lació i la configuració.

Suposem el cas següent: heu de cobrir la base del codi del projecte amb proves. Amb què heu de començar i què heu d’obtenir al final de la prova? Cobertura del 100% de les proves? Aquest és el punt de referència que hauríeu d’apuntar, però en la majoria de situacions no ho assolireu.

Per què? Perquè no hauríeu de provar tot el codi. Esbrinarem per què i què no s’ha de provar. A més, la cobertura del 100% de la prova no sempre garanteix que el component s’hagi provat completament. Tampoc no es garanteix que se us notifiqui si alguna cosa ha canviat. No us molesteu amb els percentatges, eviteu escriure proves equivocades, només intenteu no perdre els detalls dels components principals.

Definiu l'ordre correcte de les proves unitàries en funció de l'estructura del projecte

Analitzem aquesta qüestió a la següent part de l'estructura del projecte:

Vaig agafar el directori compartit perquè és el més important. Consisteix en els components que s’utilitzaran a les diferents pàgines del projecte. Són reutilitzables i solen ser petites i no són complexes. Si falla un o altre component, això provoca un error en altres llocs. Per tant, hem d’estar segurs que s’han escrit correctament. L'estructura d'aquest directori es divideix en diverses carpetes, cadascuna de les quals conté components.

Per definir l'ordre correcte de les proves unitàries al directori compartit:

  • Seguiu sempre la regla de passar de simple a complex. Analitzeu cada directori i definiu quins components són independents. La representació no depèn dels altres components. Les completeu vosaltres mateixos i es poden utilitzar per separat com a unitat. A l’estructura anterior, aquest és el directori d’entrada de la carpeta de formularis. Conté components d’entrada per a formularis de Redux com TextInput, SelectInput, CheckboxInput, DateInput, etc.
  • A continuació, hem de definir els components auxiliars que s'utilitzen sovint als components d'entrada, però que s'han de provar per separat. Aquest és el directori utils. Els components d’aquesta carpeta no són complicats, però són molt importants. Sovint són reutilitzables i ajuden amb accions repetides.
  • Al pas següent, definiu quins components també es poden utilitzar independentment els uns dels altres. Si està disponible, porteu-lo amb vosaltres per provar-ho. Des de la nostra estructura són els ginys, els petits components amb funcionalitat senzilla. Sou el tercer element de la cua per cobrir les proves.
  • A més, analitzeu la resta de directoris i definiu components més complexos que es poden utilitzar independentment o conjuntament amb altres components. En el nostre cas és el directori modal. Aquests components es detallen a continuació.
  • Els components més complexos es mantenen fins al final. Són el directori hoc i els camps de la carpeta de formularis. Com definiu quins s’han de provar primer? Prendré el directori del qual ja s’han utilitzat components als components provats. Per tant, el component del directori Hoc estava disponible al component widgets. Per tant, ja sé on i amb quina finalitat s’utilitza aquest directori i el seu component.
  • L'últim és la carpeta de camp. Conté components associats als formularis Redux.

L'ordre final dels components (basat en el nostre exemple) té aquest aspecte:

Després de fer aquesta comanda, augmentareu gradualment la complexitat dels components provats. Així, quan treballeu amb components més complexos, ja sabeu com es comporten els més petits.

Per exemple, no proveu el camp Array si no esteu segur de com provar el camp Text. No utilitzeu components decorats amb el formulari Redux tret que hàgiu provat el camp "Formulari" vosaltres mateixos.

Sigueu coherents en les vostres decisions, no preneu el primer component que us vingui al cap i canvieu de lògica. Per descomptat, l’estructura del vostre projecte pot ser diferent. Pot tenir diferents noms de directori o components addicionals, accions i reduccions, però la lògica per definir l’ordre en què es proven els components és la mateixa.

Definim què deixar fora de la cobertura de la prova:

  • Biblioteques de tercers. No proveu funcions des d'una altra biblioteca. No sou responsable d’aquest codi. Omet-la o imita la implementació si la necessites per provar el teu codi.
  • Constants. El nom parla per si sol. No es poden canviar. Es tracta de conjunts de codis estàtics que no pretenen variar.
  • Estils en línia (si els utilitzeu al vostre component). Per provar estils en línia, heu de duplicar l'objecte amb els estils de la prova. Si canvien els estils d'objecte, també els heu de canviar a la prova. No copieu el codi d'un component a proves. Mai no pensareu a canviar-lo per proves. A més, el vostre company mai no notarà que hi ha hagut duplicats. En la majoria dels casos, els estils en línia no canvien el comportament del component. Per tant, no s’han de provar. Hi pot haver una excepció si els vostres estils canvien dinàmicament.
  • Coses que no tenen res a veure amb el component provat. Omet la cobertura amb els components de prova importats al component provat. Vés amb compte si està embolicat en un altre. No proveu l’embolcall, però analitzeu-lo i proveu-lo per separat.

Com s’escriuen proves realment? Combino dos enfocaments de prova:

  • Prova instantània
  • Prova de la lògica del component

Ara en parlaré tots dos.

Com provar amb instantànies

La prova instantània és una eina de prova útil quan voleu assegurar-vos que la interfície d'usuari no hagi canviat. La primera vegada que utilitzeu aquesta eina de proves, és possible que tingueu preguntes sobre com organitzar i gestionar instantànies. El principi és molt senzill, però malauradament no s’ha descrit completament enlloc.

Pas 1. Escriviu la prova del component i utilitzeu el mètode .toMatchSnapshot () al bloc expect, que s’utilitza per crear la instantània mateixa:

it ('Representa correctament el component de text', () => {const TextInputComponent = renderer.create ( ). toJSON (); expect (TextInputComponent) .toMatchSnapshot (); });

Pas 2. La primera vegada que executeu la prova a un nivell, es crea un directori anomenat __snapshots__ amb la prova que conté el fitxer generat automàticament amb l'extensió .snap.

La instantània té aquest aspecte:

// Instantània de broma v1, https://goo.gl/fbAQLP
exported [`TextInput render correctament component 1`] =` `;

Pas 3. Moveu la instantània al dipòsit i deseu-la amb la prova.

Si el component ha canviat, tot el que heu de fer és actualitzar la instantània amb el senyalador -updateSnapshot o utilitzar el senyal de forma breu u.

Així es crea la instantània: com funciona?

Considerem dos casos:

1. El component ha canviat

  • Feu proves
  • Es crea una instantània nova i es compara amb la instantània generada automàticament emmagatzemada al directori __snapshots__.
  • Les proves han fallat perquè la instantània és diferent

2. El component no ha canviat

  • Feu proves
  • Es crea una instantània nova i es compara amb la instantània generada automàticament que s’emmagatzema al directori __snapshots__.
  • Les proves es van passar ja que la instantània és idèntica

Tot està bé si provem un component petit sense lògica (només la representació de la IU). Però, com demostra la pràctica, no hi ha components d’aquest tipus en projectes reals. Si existeixen, n’hi ha poques.

Hi ha prou instantànies per provar components complets?

Instruccions principals per a la prova de components

1. Un component només ha de tenir una instantània.

Si falla una instantània, és probable que fallin les altres. No prengueu i no deseu instantànies innecessàries que obstrueixin l’espai del disc i confonguin els desenvolupadors que llegeixen les proves després de vosaltres.

Per descomptat, hi ha excepcions si cal provar el comportament d’un component en dos estats: per exemple, en l’estat del component abans d’obrir la finestra emergent i després d’obrir-lo.

Aquesta variant sempre es pot substituir per aquesta: la primera prova desa l'estat estàndard del component sense la finestra emergent de la instantània i la segona prova simula l'esdeveniment i comprova l'existència d'una determinada classe. D'aquesta manera, podeu evitar fàcilment la presa de diverses instantànies.

2. Accessoris de prova

Normalment divideixo les proves d’atrezzo en dues proves:

  • Primer, comproveu la representació dels valors predeterminats. Quan es representa el component, espero que un valor sigui igual a defaultProps si aquest punt té defaultProps.
  • En segon lloc, comproveu el valor personalitzat de l’atrezzo. Estableixo el meu propi valor i espero que es rebi després de representar el component.

3. Proves de tipus de dades

Per provar quin tipus de dades hi ha a l’atrezzo o quin tipus de dades s’obtindran després de determinades accions, podem utilitzar la biblioteca especial jest-Extended (Addicional Jest Matchers), que conté un conjunt ampli de coincidències que es troben a la falta de broma. Amb aquesta biblioteca, provar tipus de dades és molt més fàcil i agradable.

Les proves dels accessoris, en canvi, són una qüestió contradictòria. Alguns desenvolupadors poden argumentar contra la prova dels accessoris perquè es tracta d’un paquet de tercers que no s’hauria de provar. Tot i això, insisteixo a provar els accessoris del component, ja que no estic provant jo mateixa la funcionalitat del paquet. En lloc d’això, només m’asseguro que l’atrezzo sigui correcte. El tipus de dades és una part molt important de la programació i no s’ha d’ometre.

4. Prova d'esdeveniments

Després de fer una instantània i cobrir els accessoris amb proves, podeu estar segur que el component es renderitzarà correctament. Tot i això, això no és suficient per a una cobertura completa en cas que tingueu esdeveniments al component.

Hi ha diverses maneres de revisar l'esdeveniment. Els més utilitzats són:

  • simulacre d'esdeveniment => simula-ho => espera que es cridés l'esdeveniment
  • simulacre d'esdeveniment => simular esdeveniment amb params => esperar que es cridés l'esdeveniment amb params passat
  • lliura els accessoris necessaris => render component => simula esdeveniment => espera un comportament determinat quan es crida l'esdeveniment

5. Condicions de la prova

Molt sovint, podeu tenir condicions sobre la sortida d’una classe particular, representar una secció de codi concreta, transferir els accessoris necessaris, etc. No ho oblideu, ja que amb valors per defecte només una branca passarà la prova i la segona no es provarà.

En components complexos amb càlculs i moltes condicions, poden faltar algunes branques. Per assegurar-vos que totes les peces de codi estan cobertes per proves, utilitzeu una eina de cobertura de proves i comproveu visualment quines branques estan cobertes i quines no.

6. Condició de la prova

En la majoria dels casos, s’han d’escriure dues proves per comprovar l’estat:

  • El primer comprova l'estat actual.
  • El segon comprova l'estat després de trucar a un esdeveniment. Representa el component => funció de trucada directament a la prova => comprova com ha canviat l'estat. Per trucar a la funció del component, heu d'obtenir una instància del component i només després cridar-ne els mètodes (l'exemple es mostra a la prova següent).

Després d’haver revisat aquesta llista d’instruccions, el vostre component estarà cobert del 90 al 100%. Deixo un 10% per a casos especials que no s’han descrit a l’article però que poden aparèixer al codi.

Exemples de proves

Passem ara a exemples i tractem els components amb proves, tal com es descriu pas a pas més amunt.

1. Provar un component a partir de formularis / entrades.

Agafeu un component del directori formulari / entrada. Deixeu DateInput.js, el component del selector de dates.

Llista de codis per al component provat: DateInput.js Sembla que:

El component DateInput utilitza la biblioteca react-datepicker amb dues utilitats:

  • valueToDate (converteix el valor en data)
  • dateToValue (converteix la data en valor)

El paquet s'utilitza per editar amb data i PropTypes per comprovar els accessoris React.

Segons el codi del component, veiem la llista d’atrezzo estàndard amb el qual es pot representar el component:

const defaultProps = {inputClassName: 'input-custom', mesos Mostrat: 1, dateFormat: 'DD.MM.YYYY', showMonthYearsDropdowns: false, minDate: moment ()};

Tots els accessoris a excepció d’un: minDate: moment () són adequats per fer la instantània. Cada cop que s'executa la prova, moment () mostra la data actual i la instantània falla perquè es desa la data obsoleta. La solució és burlar-se d’aquest valor:

const defaultProps = {minDate: moment (0)}

Necessitem accessoris minDate en tots els components representats. Per evitar duplicar accessoris, crearé un HOC que rebrà defaultProps i tornaré un bonic component:

Importa TestDateInput des de '../DateInput'; const DataInput = (atrezzo) => ;

No oblideu la zona horària, sobretot si les proves les realitzen desenvolupadors d’un altre país en una zona horària diferent. Obtindreu el valor ridícul, però amb un canvi de zona horària. La solució és establir una zona horària per defecte:

const moment = require.requireActual ('moment-zona horària'). tz.setDefault ('America / Los_Angeles')

Ara es pot provar el component d'entrada de data:

1. Primer feu una instantània:

it ('Representar el component de la data correctament', () => {const DateInputComponent = renderer.create ( ). toJSON (); expect (DateInputComponent) .toMatchSnapshot (); });

2. Accessoris de prova:

Mireu a través dels accessoris i trobeu-ne els importants. El primer puntal a provar és showMonthYearsDropdowns. Quan s'estableix en true, es mostra la llista desplegable de mes i any:

it ('comprova les desplegables mostrades per a mes i any', () => {const props = {showMonthYearsDropdowns: true}, DateInputComponent = mount ( ) .find ('. datepicker'); expect (DateInputComponent.hasClass ('react-datepicker-hide-month'). toEqual (true);});

Proveu el valor de punt zero. Aquesta comprovació és necessària per assegurar-se que el component s'està representant sense un valor definit:

it ('Renderitza l'entrada de data correctament amb valor nul', () => {const props = {value: null}, DateInputComponent = mount ( ); expect ((DateInputComponent) .prop ('valor'). toEqual (nul);});

3. Proveu les propietats del valor i la data en què s'espera una cadena:

it ('comprova el tipus de valor', () => {const props = {value: '10 .03.2018 '}, DateInputComponent = mount ( ); expect (DateInputComponent.prop ('valor')). toBeString (); });

4. Prova d'esdeveniments:

Primer, comproveu l’esdeveniment onChange.

  • mock on Canvia la devolució de trucada
  • Representa el component d'entrada de cita
  • Simuleu un esdeveniment de canvi amb un valor objectiu nou
  • Finalment, comproveu si l'esdeveniment onChange s'ha cridat amb un valor nou.
it ('comprova la devolució de trucada onChange', () => {const onChange = jest.fn (), atrezzo = {valor: '20 .01.2018 ', si es modifica), DateInputComponent = mount ( ) .find ('entrada'); DateInputComponent.simulate ('canvi', {objectiu: {valor: moment ('22-01-2018')}}); expect (onChange) .toHaveBeenCalledWith ('22 .01.2018 '); });

A continuació, assegureu-vos que la finestra emergent del selector de dates s'obri després de fer clic a l'entrada de data. Per fer-ho, cerqueu l'entrada de data => simuleu clic esdeveniment => i espereu una finestra emergent quan estigui disponible la classe .react-datepicker.

it ('Open DatePicker-Popup', () => {const DateComponent = mount ( ), dateInput = DateComponent.find ("input [type = 'text']"); dateInput.simulate ('clic'); expect (DateComponent.find ('. react-datepicker'). toHaveLength (1);});

Llista de proves completa: DateInput.test.js

2. Proves d'ús:

Llistat de codis per a la utilitat provada: valueToDate.js

Aquesta utilitat converteix un valor en una data mitjançant un format personalitzat.

En primer lloc, analitzem la utilitat donada i definim els casos principals per provar:

  1. Converteix el valor segons el propòsit d'aquesta utilitat. Per tant, hem de comprovar aquest valor:
  • En cas que el valor no estigui definit: hem d'assegurar-nos que la utilitat no retorni cap excepció (error).
  • Amb un valor definit, hem de comprovar que la utilitat retorni la data actual.

2. El valor retornat hauria de pertànyer a la classe moment. Per tant, hauria de ser un moment.

3. El segon argument és dateFormat. Establiu-lo com a constant abans de provar-lo. Per això, superarà totes les proves i retornarà el valor segons el format de data. Hem de provar dateFormat per separat? Suposo que no. Aquest argument és opcional. Si no definiu el format de data, la utilitat no s'interromprà i només retornarà la data en el format predeterminat. És una feina momentània, no hauríem de provar biblioteques de tercers. Com he esmentat anteriorment, no oblidem la zona horària. Aquest és un punt molt important, especialment per a desenvolupadors de diferents zones horàries.

Codi:

  1. Escriviu la prova del primer cas. Si no tenim cap valor, està buit.
const format = 'DDMM.AAAA';
it ('utilitat render renderToDate amb un valor buit', () => {valor const = valorToDate ('', format); expect (valor) .toEqual (nul);});

2. Verifiqueu que es defineixi un valor.

const date = '21 .11.2015 ', format = "DD.MM.YYYY";
it ('utility' render valueToDate 'with value defined', () => {const value = valueToDate (date, format); expect (value) .toEqual (moment (data, format));});

3. Verifiqueu que el valor pertany a la classe moment.

const date = '21 .11.2015 ', format =' DD.MM.YYYY ';
it ('el valor de comprovació és instanceof moment', () => {const value = valueToDate (data, format); expect (valor instance of the moment) .toBeTruthy ();});

Llista de proves completa: valueToDate.test.js

3. Proveu ginys

Per provar ginys, he utilitzat un component giratori.

Llistat de codis per al giny provat: Spinner.js

Es veu així:

No es necessita el girador a l'explicació, ja que gairebé tots els recursos web tenen aquest component.

Per tant, quan anem a escriure proves:

  1. Primer pas: feu una instantània:
it ('Renderitza correctament el component giratori', () => {const SpinnerComponent = mount ( ); expect (SpinnerComponent) .toMatchSnapshot (); });

2. Accessoris de prova:

En primer lloc, fem una ullada al títol predeterminat de l’atrezzo i comprovem si es renderitza correctament.

it ('Comprova el títol de prop per defecte', () => {const SpinnerComponent = mount ( ); expect (SpinnerComponent.find ('p'). text ()). toEqual ("Si us plau, espereu"); });

A continuació, comprovem el títol personalitzat de l’atrezzo. Hem de comprovar que es retorna l’atrezzo correctament definit. Feu una ullada al codi, el títol s'inclou a rawMarkup util i es publica mitjançant la propietat dangerouslySetInnerHTML.

Llistat de codis per a RawMarkup util:

Exporta la funció estàndard rawMarkup (plantilla) {return {__html: template}; }

Hem d'incloure proves de rawMarkup al component de filador? No, és una utilitat independent que s’hauria de provar al costat de la filadora. No ens importa el seu funcionament, només hem de saber que el defensor del títol ofereix el resultat correcte.

Explicació: el motiu per utilitzar la propietat dangerouslySetInnerHTML és el següent. El nostre lloc web és multilingüe i l’equip de màrqueting de la traducció n’és el responsable. Podeu traduir-lo fàcilment amb una combinació de paraules o fins i tot amb etiquetes HTML com, o fins i tot text amb les llistes , llesca. No sabem exactament com tradueixen i decoren el text. Només hem de representar correctament totes les coses.

He resumit dos casos de prova principals en una prova:

  • Retorna el títol de prop personalitzat correcte
  • Representeu correctament el títol de l’atrezzo mitjançant etiquetes HTML
Bitte warten it ('Comprova el títol del prop amb etiquetes HTML', () => {const props = {title: ' Espera '         },         SpinnerComponent = mount ( '}, SpinnerComponent = mount ( ); ); expect (SpinnerComponent.find ('p'). text ()). expect (SpinnerComponent.find ('p'). text ()). toEqual ('Bitte warten'); toEqual ("Si us plau, espereu"); }); });

Agafeu el següent subtítol. És opcional i, per això, no hi ha un puntal estàndard. Saltar el pas amb els accessoris estàndard i provar accessoris personalitzats:

  • Comproveu que el text de la propietat Subtítols es mostri correctament:
const props = {subtitle: 'left 1 minute'}, SpinnerComponent = mount ( );
it ('render text correcte', () => {expect (SpinnerComponent.find ('p'). at (1) .text ()). toEqual (props.subTitle);});

Sabem que els subtítols són opcionals. Per això, hem de comprovar que no es va representar mitjançant accessoris estàndard, d'acord amb el marcatge de tall. Només cal que comproveu el nombre d’etiquetes :

it ('No es mostraran els subtítols', () => {const SpinnerComponent = mount ( ); expect (SpinnerComponent.find ('p'). longitud) .toEqual (1); });

3. Tipus d’atrezzo de prova:

  • Per al prop de títol, que s'espera com una cadena:
it ('Comprova que el tipus de suport del títol sigui una cadena', () => {const props = {title: 'wait'}, SpinnerComponent = mount ( ); expect (SpinnerComponent.find ('p'). text ()). toBeString (); });
  • També s’espera una cadena per al prop de subtítols:
const props = {subtitle: 'left 1 minute'}, SpinnerComponent = mount ( );
it ('type for subTitle is string', () => {expect (SpinnerComponent.find ('p'). at (1) .text ()). toBeString ();});

Llista completa de proves: Spinner.test.js

4. Proves modals (ModalWrapper.js i ModalTrigger.js)

Sembla:

Com provar els modals

Primer m’agradaria explicar com s’organitzen les modalitats en el nostre projecte. Tenim dos components: ModalWrapper.js i ModalTrigger.js.

ModalWrapper és el responsable del disseny emergent. Conté el contenidor modal, el botó "Tanca", el títol modal i el text.

ModalTrigger és responsable de la manipulació modal. Conté el disseny ModalWrapper i conté esdeveniments per al control de disseny del modal (accions per obrir i tancar).

Passo per cada component individualment:

1. Llista de codis per al component provat: ModalWrapper.js

Codi:

En primer lloc, el ModalWrapper rep el component i el fa representar-hi. Primer, assegureu-vos que ModalWrapper no falla sense el component. Feu una instantània amb accessoris estàndard:

it ('sense component', () => {const ModalWrapperComponent = superficial ( ); expect (ModalWrapperComponent) .toMatchSnapshot (); });

El següent pas és simular l'estat real, amb la representació dels components mitjançant accessoris:

it ('with component', () => {const props = {component: () => {}}, ModalWrapperComponent = superficial ( ); expect (ModalWrapperComponent) .toMatchSnapshot (); });

Accessoris de prova

Rebre un prop de nom de classe personalitzat:

it ('render the correct class name', () => {const props = {modalClassName: 'name of custom class'}, ModalWrapperComponent = shallow ( ) .find ('Modal'); expect (ModalWrapperComponent.hasClass ('Nom de la classe personalitzada'). toEqual (true);});

Rebre un títol personalitzat:

it ('render title correct', () => {const props = {title: 'Modal Title'}, ModalWrapperComponent = superficial ( ) .find ('ModalTitle'); expect (ModalWrapperComponent.props (). fills) .toEqual ('Títol modal'); });

Recepció del propi programa correcte:

it ('Comprova el valor del prop', () => {const props = {Show: true}, ModalWrapperComponent = superficial ( ) .find ('Modal'); expect (ModalWrapperComponent.props (). show) .toEqual (true); });

Accessoris de prova

  • Per obtenir suport
it ('Check prop type', () => {const props = {Show: true}, ModalWrapperComponent = shallow ( ) .find ('Modal'); expect (ModalWrapperComponent.props (). show) .toBeBoolean (); });
  • Per a Amagar Prop
it ('renderitzat correctament a Amagar el tipus de suport', () => {const props = {a Amagar: () => {}}, ModalWrapperComponent = superficial ( ) .find ('Modal'); expect (ModalWrapperComponent.props (). onHide) .toBeFunction (); });
  • Per al suport de components
it ('render correcte component prop type', () => {const props = {component: () => {}}, ModalWrapperComponent = mount ( ); expect (ModalWrapperComponent.props (). component) .toBeFunction (); });

Llista completa de proves: ModalWrapper.test.js

2. Llista de codis per al component provat: ModalTrigger.js

La closca modal es va cobrir amb una prova. La segona part tracta del component d'activació modal.

Visió general dels components: es basa en l’estat que mostra la visibilitat de ModalWrapper. Si està activat: false, la finestra emergent s'ocultarà, en cas contrari es mostrarà. La funció open () obre la finestra emergent de l'element fill. L'esdeveniment de clic i la funció close () amaguen la finestra emergent del botó representat al ModalWrapper.

Creació d’instantànies:

it ('Rendeix el component ModalTrigger correctament', () => {const ModalTriggerComponent = superficial ( ); expect (ModalTriggerComponent) .toMatchSnapshot (); });

Hem de provar ModalTrigger amb suports de components de representació? No, perquè el component s'està representant al component ModalWrapper. No depèn del component provat. Ja s’ha provat a les proves de ModalWrapper.

Accessoris de prova:

Tenim un nen d’atrezzo i volem estar segurs que només tenim un fill.

it ('assegureu-vos que només hi ha un element fill (control)', () => {expect (ModalTriggerComponent.findWhere (node ​​=> node.key () === 'modal-control'). length)) .toEqual (1);});

Accessoris de prova:

El manutenció infantil hauria de ser un objecte, comproveu-ho a la prova següent:

const ModalTriggerComponent = mount ( );
it ('Comprova el tipus de suport infantil', () => {expect (ModalTriggerComponent.props (). fills) .toBeObject ();});

Una part important del component ModalTrigger és comprovar l’estat.

Tenim dos estats:

  • S'obrirà la finestra emergent. Per saber que el modal està obert, hem de comprovar-ne l’estat. Per fer-ho, truqueu a la funció oberta des de la instància del component i espereu que l'estat d'activació sigui cert.
it ('comprova si el modal està obert', () => {const event = {preventDefault: () => {}, stopPropagation: () => {}}; ModalTriggerComponent.instance (). Obert (esdeveniment) ; expect (ModalTriggerComponent.state (). alternat) .toBeTruthy ();});
  • La finestra emergent està tancada. Es prova a l’inrevés, quan està engegat hauria de ser incorrecte.
es ('comprova si el modal està tancat', () => {ModalTriggerComponent.instance (). Close (); expect (ModalTriggerComponent.state (). toggled) .toBeFalsy ();});

Llista completa de proves: ModalTrigger.test.js

Ara les modalitats estan completament provades. Un consell per provar els components interdependents: primer mireu els components i escriviu el pla de prova, definiu el que heu de provar en cada component, reviseu els casos de prova de cada component i assegureu-vos que no Repetiu el mateix cas de prova en tots dos components. Analitzeu acuradament les variants òptimes i possibles per cobrir les proves.

5. Examen HOC (component de nivell superior)

Les dues darreres parts (HOC i verificació del camp del formulari) estan enllaçades. Vull compartir amb vosaltres com provar el disseny del camp amb el HOC.

A continuació s’explica què és BaseFieldLayout, per què necessitem aquest component i on l’utilitzem:

  • BaseFieldLayout.js és l’embolcall dels components d’entrada del formulari com TextInput, CheckboxInput, DateInput, SelectInput, etc. Els seus noms acaben amb -Input perquè estem utilitzant el paquet Redux Form i aquests components són els components d’entrada de la lògica Redux Form.
  • Necessitem BaseFieldLayout per establir els components del camp del formulari, és a dir, per representar etiquetes, consells d’informació, prefixos (moneda, abreviatures de metres quadrats, etc.), símbols, errors, etc.
  • L'utilitzem a BaseFieldHOC.js per integrar inputComponent en un disseny de camp i amb l'ajut del -Conecteu el component amb el formulari Redux.

Llista de codis per al component provat: BaseFieldHOC.js

És un HOC que rep el component d’entrada de formulari i retorna el component associat amb redux-form.

Anàlisi del HOC:

  • Aquest component només rep un puntal, el component. Primer he de crear aquest component i incloure'l a BaseFieldHOC.
  • A continuació, he de decorar el HOC empaquetat amb Redux-Form per connectar el camp amb Redux-Form.
  • Representeu aquest camp al component React Redux per fer disponible la memòria del component provat. Per burlar-se de la botiga, només cal fer el següent:
const store = createStore (() => ({}));

Ara he de fer el següent abans de cada prova:

deixeu BaseFieldHOCComponent;
beforeEach (() => {const TextInput = () => {return 'text input';}, BaseFieldHOCWrapper = BaseFieldHOC (TextInput), TextField = reduxForm ({form: 'testForm'}) (BaseFieldHOCWrapper); BaseFieldHOCComponent = renderer.create ( ) .toJSON (); });

A continuació, el component està a punt per provar-se:

  1. Feu una instantània:
it ('Representa el component correctament', () => {expect (BaseFieldHOCComponent) .toMatchSnapshot ();});

2. Assegureu-vos que el component d'entrada estigui inclòs a BaseFieldLayout després de renderitzar:

it ('Comproveu si el component d'entrada està inclòs a BaseFieldLayout', () => {expect (BaseFieldHOCComponent.props.className) .toEqual ('form-group');});

Això és tot, el HOC està protegit. La part més complicada de provar components relacionats amb Redux-Form és preparar el camp (decorar amb Redux-Form i configurar la memòria). La resta és fàcil, només cal que seguiu les instruccions i res més.

Llista completa de proves: BaseFieldHOC.test.js

6. Proveu formularis / camps

El camp HOC es cobreix amb proves perquè puguem canviar al component BaseFieldLayout.

Llista de codis per al component provat: BaseFieldLayout.js

Codifiquem BaseFieldLayout.js i escrivim les proves segons les instruccions anteriors:

  1. Primer, feu una instantània.

Aquest component no es representa sense defaultProps:

  • inputComponent
  • Accessoris de Redux-Form: objectes d’entrada i meta. Entrada amb nom de propietat i meta amb error de propietat i tocat:
const defaultProps = {meta: {tocat: nul, error: nul}, entrada: {nom: 'nom del camp'}, componentComponent: () => {retorn 'cas de prova'; }}

Per utilitzar defaultProps a cada embolcall provat, feu el següent:

Importeu TestBaseFieldLayout des de '../BaseFieldLayout';
const BaseFieldLayout = (atrezzo) => ;

Ara podem fer una instantània:

it ('Representa correctament el component BaseFieldLayout', () => {const BaseFieldLayoutComponent = renderer.create ( ). toJSON (); expect (BaseFieldLayoutComponent) .toMatchSnapshot (); });

2. Accessoris de prova:

Aquest component té molts accessoris. Mostraré exemples de diversos i la resta es posarà a prova de manera anàloga.

  • Assegureu-vos que la representació del símbol es reprodueix correctament
es ('render render correctament prop', () => {const props = {icon: }, BaseFieldLayoutComponent = mount ( ); expect (BaseFieldLayoutComponent.find ('span'). hasClass ('icon-exclamation')). ToBeTruthy (); });
  • Assegureu-vos que el contingut de les descripcions aparegui al costat de l’etiqueta
const props = {labelTooltipContent: 'Tooltip for label'}, BaseFieldLayoutComponent = mount ( );
it ('Es requereix un requisit', () => {expect (BaseFieldLayoutComponent.find ('span'). hasClass ('tooltip-icon')). ​​toBeTruthy ();});
  • Prova de fieldLink Prop
  • Assegureu-vos que fieldLink és nul per defecte
it ('check prop is null per defecte', () => {const BaseFieldLayoutComponent = superficial ( ); expect (BaseFieldLayoutComponent.props (). fieldLink) .toBe (nul); });
  • Assegureu-vos que fieldLink es renderitzi correctament amb un valor personalitzat

3. Error de prova:

it ('comprova si el camp té un error', () => {const props = {meta: {tocat: cert, error: 'aquest camp és obligatori'}}), BaseFieldLayoutComponent = mount ( ); expect (BaseFieldLayoutComponent.find ('. error')). toHaveLength (1); });

Llista completa de proves: BaseFieldLayout.test.js

Linia inferior

Ara ja sabeu com utilitzar l'estructura del projecte per dur a terme proves exhaustives de components. Per la meva pròpia experiència, he intentat explicar què s’ha de provar en quin ordre i què es pot ometre a la cobertura de la prova. També vaig mostrar exemples de diversos components de la prova i vaig establir la seqüència de cobertura de base de codi.

Espero que trobeu útil aquest article i compartiu les vostres respostes. Gràcies per llegir.

Si trobeu útil aquesta publicació, toqueu a continuació :)