Enkla JavaScript-enhetstester i WordPress med Jest
WordPress har en lång erfarenhet av enhetsteste sin PHP-kod. Att skriva JavaScript-enhetstester och integrationstester för koden i teman och plugins har dock inte samma status. Låt oss se hur du testar JavaScript i våra WordPress-plugins och teman med Jest.
Det här är innehållet som vi kommer att täcka i den här artikeln:
JavaScript-enhetstester i WordPress
Så varför skriva enhetstester och integrationstester? De är bra att se till att en funktion, klassmetod eller till och med en React-komponent gör vad de ska göra. Det hjälper till att upptäcka fel i koden och hjälper också till att bevara integriteten när ändringar senare införs i koden genom att verifiera att den fortfarande fungerar som avsett efter uppdateringen.
WordPress- plugins och teman är oftast skrivna i PHP och kan använda PHPUnit-sviten för att köra tester, göra påståenden, håna funktioner och mer. Handboken har till och med ett avsnitt som förklarar hur man snabbt ställer in enhetstestning med WP-CLI.
För JavaScript finns det en sida om att köra QUnit-tester i handboken, även om det handlar mer om att testa JavaScript-koden i WordPress-kärnan.
Även om inget av detta är standardiserat för JavaScript i WordPress, kan vi skriva fantastiska enhetstester med hjälp av Jests testsvit. I den här artikeln lär vi oss hur man skriver JavaScript-enhetstester för ett exempelplugin som laddar 5 inlägg genom WP REST API med hjälp av fetch
funktionen från JavaScript och renderar dem i ett visst DOM-element på sidan.
Fördelar med att använda Jest för JavaScript-enhetstester i WordPress
Tidigare innebar att skriva JavaScript-enhetstester att ställa in Mocha för att köra tester, Chai för att göra påståenden och Sinon för att håna funktioner och spionera på dem. Även om de erbjuder stor flexibilitet är det mycket mer komplicerat att arbeta med tre paket än ett. Jest tillhandahåller allt detta i ett enda paket:
- du kan köra tester och deklarera dem med
describe
ochit
ellertest
- du kan göra påståenden med
expect
ochtoBe
ochtoHaveLength
många fler - du kan håna funktioner och spionera på dem, och det finns flera sätt att göra detta
Innan du går vidare
För att hålla den här artikeln fokuserad på att testa med Jest, finns det ytterligare inställningar utanför testprocessen som Babel eller Webpack som inte kommer att täckas här. Allt detta kan hittas i WP Jest Tests repo som medföljer den här artikeln. För att hålla saker kontextuella kommer varje avsnitt att länka till en av de relevanta filerna som vi kommer att skriva.
Översikt över PHP-sidan
PHP för exemplet plugin som vi kommer att använda för att lära oss hur man skriver JavaScript-enhetstesten är ganska standard. De enda intressanta raderna är de när vi ställer vår JavaScript-fil i kö och lägger till ett inline-skript för att skicka variabler till den:
Efter att ha sökt vår JavaScript-fil lägger vi till en global variabel wpJestTests
med wp_add_inline_script()
. Den här variabeln är särskilt intressant och svår att hantera eftersom den är extern till vår JavaScript-fil och vi måste håna den i våra tester.
Ställ in Jest-tester
Vi måste först initiera npm
i vårt plugin-projekt för att kunna installera Jest med det. Navigera i kommandoraden till din plugin-mapp och kör:
npm init
och gå igenom serien med uppmaningar här
Redigera filen package.json som skapades och lägg till en ny post för att köra våra tester i scripts
avsnittet:
"test": "jest"
Detta kommer att vara kommandot vi kommer att använda för att berätta för Jest att köra våra JavaScript-enhetstester. Detta är en engångskörning, men Jest stöder också filvisning, så du kan ange ytterligare en:
"test-watch": "jest --watch"
Installera nu Jest som ett utvecklingsberoende genom att köra
npm install -D jest
Medan den installeras skapar du en fil med namnet jest.config.js
. Detta kommer att hålla all nödvändig konfiguration. Lägg till följande:
module.exports = {
verbose: true,
setupFiles: [
'/__mocks__/globals.js'
],
moduleNameMapper: {
'.(css|less|sass|scss)$': '/__mocks__/styleMock.js'
}
};
Låt oss gå igenom var och en:
verbose
: indikerar om varje enskilt test ska rapporteras under körningen. Alla fel kommer också fortfarande att visas längst ner efter körning. Observera att om det bara finns en testfil som körs är den som standardtrue
.setupFiles
: en lista över sökvägar till moduler som kör någon kod för att konfigurera eller ställa in testmiljön. Varje setupFile kommer att köras en gång per testfil. Eftersom varje test körs i sin egen miljö, kommer dessa skript att köras i testmiljön omedelbart innan själva testkoden körs. Vi kommer att använda detta för att deklarera globala variabler renderade av PHP och WordPress med kommandon somwp_add_inline_script
ellerwp_localize_script
.moduleNameMapper
: det här är en karta från reguljära uttryck till modulnamn (eller arrayer av modulnamn) som gör att statiska resurser, som bilder eller stilar, kan försvinna med en enda modul.
Du har säkert märkt referensen: detta är en speciell token som ersätts av Jest med roten till ditt projekt, vilket vanligtvis är platsen för din package.json
.
Vi kommer att gå på djupet i de kommande två avsnitten men skapa först mappen och dessa två filer som refereras till ovan:
- skapa en mapp med namnet
__mocks__
- inuti mappen, skapa filerna
styleMock.js
ochglobals.js
Mock stilar importeras för Jest-tester
Om du, som detta plugin, använder Webpack för att kompilera allt inklusive stilar och du importerar .scss
filen i .js
filen:
import './main.scss';
du måste använda styleMock.js för att håna SASS-filer när du importerar dem i vår JavaScript-fil, annars kommer Jest att krascha eftersom det inte kommer att kunna lösa modulen. Du behöver inte mycket för den här filen, lägg bara till
Jest kommer att använda denna mock varje gång den hittar en .scss
import och kommer att mappa dem till mock, så att du kan gå vidare med tester utan att bry dig om stilarna.
Konfigurera globaler för Jest
Låt oss arbeta nu i filen globals.js. En av fördelarna med att använda Jest är att den redan levereras med en redan konfigurerad jsdom
, en ren JavaScript-implementering av webbstandarder, som simulerar en DOM-miljö som om du var i webbläsaren, och vi kommer att använda den för att håna DOM-element för våra tester.
Skapa en mapp __mocks__
och en globals.js
fil i den. Lägg till detta i filen:
import { JSDOM } from 'jsdom';
const dom = new JSDOM();
global.document = dom.window.document;
global.window = dom.window;
global.window.wpJestTests = undefined;
Detta kommer att förklara och håna vissa objekt och metoder som du senare kommer att använda i dina tester. Den sista är av särskilt intresse
global.window.wpJestTests = undefined;
Det här är den globala variabeln vi skrev med wp_add_inline_script
. Du måste håna den som en global variabel för att kunna använda den i dina tester.
Översikt över JavaScript-filen
WordPress-pluginet har en enda JavaScript-fil main.js i en /src
mapp. Detta transpileras senare och matas ut i en /js/front.js
fil som är vad PHP kommer att ladda. JavaScript laddar fem WordPress-inlägg med fetch
, en standard JavaScript-funktion, genom WP REST API och infogar dess titel, med en länk till inlägget, i en div.entry-content
.
Du kommer att exportera funktionen som gör allt:
så att du kan använda den i dina tester i Jest.
Skriver JavaScript-enhetstester med Jest, äntligen!
Nu kan du börja skriva prov! Jest kan hitta tester på många sätt:
- om filnamnet är
test.js
- eller har prefixet namnet på filen den testar, som
main.test.js
- om de är
.js
filer som finns i en mapp med namnet__tests__
Skapa __tests__
mappen och inuti den, en front.test.js
. Du kan se den färdiga JavaScript-filen för Jest-testerna i följeslagaren. Låt oss gå igenom det i block. Den första raden importerar JS-filen som vi vill testa:
import { wpJestTestsInit } from '../src/main';
Därefter rensar vi alla hånar, så vi kör aldrig med smutsiga hånar som bär värden från tidigare tester. Att göra detta kan leda till fel eftersom till exempel, om vi spionerar på hur många gånger en hånad funktion anropades, kan vi få en felaktig läsning om vi inte rensar hånet mellan test och test:
Det första testet vi kommer att skriva, gör grundläggande påståenden när vissa saker misslyckas. Till exempel, om den globala wpJestTests
variabeln som vi skrev med wp_add_inline_script
inte skrevs av någon anledning:
I den här koden,
describe
skapar en grupp som består av flera relaterade testertest
är det som faktiskt utför ett testexpect
omsluter vårt testämne och ger tillgång till ett antal "matchare" som låter dig göra olika påståenden om dess innehålltoBe
är en av dessa matchare. Jest har många matchare inkluderade, och det finns även andra som du kan lägga till med ett tredjepartspaket.
Det första testet definierar inget för wpJestTests
så dess värde kommer att vara det du definierade i globals.js
. Eftersom det är undefined
, kan vi inte arbeta så vi vill bekräfta att funktionen returnerar utan att göra något.
Det andra testet definierar wpJestTests
och hånar document.querySelector
metoden att returnera undefined
vilket är vad det skulle returnera om det inte kunde hitta ett element i DOM. I sådana fall vill vi bekräfta att vi återvänder utan att göra något, och att vår funktion mocking document.querySelector
anropades en gång.
Mock apport i Jest-tester
Nästa uppsättning tester börjar med
och inuti detta har vi en annan rivningsfunktion:
unlike afterEach
this kommer att köras efter att alla tester i detta describe
block har körts. Eftersom vår JavaScript-fil använder fetch
för att ladda inläggen måste vi verifiera att den anropades och att den returnerade det vi begärde, så vi kommer att håna fetch
funktionen:
Vi hånar det första löftet som löser svaret och det andra till en JSON-representation av data. Dessa data liknar vad vi får från WP REST API. Med tanke på att vår kod bara behöver titeln och länken, hånar vi det.
JavaScript-integreringstest med Jest i asynkron kod som använder hämta
Vi kan nu skriva testet med den mocked fetch
. Det finns en stor skillnad med detta test jämfört med de andra JavaScript-enhetstesten: det här är ett integrationstest. Tidigare tester som utforskats här säkerställde helt enkelt att en komponent fungerade bra. Vi kontrollerade att om den globala initialvariabeln inte var definierad, skulle vår komponent inte återges. Detta är annorlunda eftersom vi kommer att testa hur hela systemet fungerar när den initiala tillståndsvariabeln är definierad, vilket utlöser en datatransaktion och slutligen infogar inläggets rubriker med deras länkar i dokumentet.
Redan från början är detta annorlunda: den anonyma funktionen som skickas till test
tar emot en done
parameter. Detta är faktiskt en funktion som kommer att anropas när vi avslutar testet. Jest kommer att vänta tills done
det anropas innan testet avslutas. Om done
aldrig anropas kommer testet att misslyckas med ett timeout-fel. Det är intressant för oss eftersom vi testar kod som involverar fetch
, som är en asynkron funktion.
Det globala wpJestTests
är definierat och vår mocked document.querySelector
returnerar nu vad som liknar ett HTML-element, med jämn classList
och dess add
underordnade metod.
Vi ringer wpJestTestsInit
och förväntar oss att det slutar på rätt sätt. Nu, eftersom fetch
det är asynkront, kommer vi att använda process.nextTick
från Node.js. I nextTick
Node.js är kön som kommer att köras efter att alla händelser i den aktuella händelseslingan har avslutats. Detta är bra eftersom alla våra löften skulle vara lösta då, vilket är precis vad vi behöver för att testa den här koden som involverar fetch
.
Resten är fler påståenden för att säkerställa att vi querySelector
hittat något att arbeta med, som fetch
verkligen hette, att en klass lades till i listan och att rubrikerna och länkarna till våra inlägg infogades i motsvarande HTML-element. När allt är klart ringer vi done
och vårt asynkrona test slutar.
Kör dina Jest-tester
Nu kan du skriva
npm run test
och Jest kommer att köra JavaScript-enhetstesten för ditt WordPress-plugin
Slutsats
Så Jest är en bra och enkel lösning för att skriva tester som täcker JavaScript-koden för våra WordPress-plugins eller teman. Men det finns mer. Om vi skriver en React-app för vårt plugin kanske vi vill göra påståenden om det. Jest kan hjälpa upp till en viss del också, och om vi behöver mer kan vi lägga till Enzyme i våra verktyg och börja skriva integrationstester med det.
Vänligen donera!
Om du tyckte att det här var användbart, köp gärna en kaffe till mig så att jag kan hålla mig vaken och skapa fler användbara tutorials för dig!
3,00 USD