Responsive Skärmdumpar Med Casper

Att fånga skärmdumpar är irriterande, men det mesta måste det göras och vanligtvis är det du - Utvecklaren - som måste göra det. Att ta några skärmdumpar är inte så illa, men vi kan till exempel säga att du nu arbetar på en webbplats med Responsive Web Design och du måste ta fem gånger så många skärmdumpar på olika visningsportar. Den där, två andra irriterande uppgiften har nu börjat äta i din lunchtid.


Intro

Idag kommer jag att springa genom att skriva ett snabbt och enkelt skript för att ta några skärmdumpar av vilken sida som helst på olika visningsportar och spara bilderna till skivan. Detta såg jag först vid mediaqueri.es och började implementera det i min byggprocess. Det är inte idealiskt för riktig testning, eftersom det fungerar mer som ett sanitytest och ger en bra överblick för vad jag kanske arbetar med att involvera Responsive Web.

När en byggnad är igång kan ett litet manus med PhantomJS och CasperJS gå och ta en skärmdump i olika visningsportar som jag har definierat och ger mig en snabb översikt över vilken sida som helst. Det är särskilt bra när du arbetar inom ett större lag och du kanske inte har tid innan varje byggnad går och kolla varje enskild sida och modul för hur det ser ut på olika upplösningar. Det kommer också att ge dig något att möjligen visa klienten med jämna mellanrum, för att visa hur deras webbplats böjer sig vid olika visningsportar.

Obs! PhantomJS är en huvudlös WebKit-webbläsare och allt som görs skulle använda WebKit-rendering, så det är inte en verklig representation av hur webbplatsen skulle göra på olika enheter som kan köra olika webbläsare och samtidigt som du kan ändra användaragentsträngen som skickats till webbplatsen laddas, ändras inte återgivningsmotorn.

PhantomJS har ett bra JavaScript API byggt med testning i åtanke. För en bra introduktion till PhantomJS och att använda den för testning finns en handledning här på nätet och var noga med att kontrollera den officiella webbplatsen och dokumentationen.

CasperJS är en verktygslåda som sitter på toppen av PhantomJS och underlättar processen att skriva Phantom-skript genom att tillhandahålla funktioner, metoder och syntaktiskt socker.


Installation

Du kanske redan har Phantom installerat, speciellt om du redan testar din klientsidkod, om inte, det är ganska rakt framåt och du kan få mer detaljerade instruktioner på den officiella webbplatsen

För Windows-användare finns en körbar för att hämta och köra.

För Mac-användare finns det både binära eller du kan installera med Homebrew:

brygga uppdatering & & brygga installationsfantomier

För Linux-användare finns det ett 64-bitars binärt eller du har möjlighet att kompilera PhantomJS från källan.

När du har installerat kan du öppna en terminal och kontrollera att allt är OK genom att springa:

fantom - version

som bör återvända:

1.8.0

När Phantom är installerat kan du gå vidare och installera CasperJS också. För Mac-användare kan du återigen använda Homebrew:

brygga installera casperjs

För Windows-användare måste du lägga till din VÄG fil med "; C: \ casperjs \ batchbin" (Ändra den här sökvägen beroende på var du vill lagra CasperJS). Inom batchbin katalog, det heter en batchfil casperjs.bat, Det här är det manus som kör dina Casper-skript utan att behöva installera Ruby eller Python för att köra det. När du behöver köra Casper-skriptet, använd bara casperjs.bat scriptname.js hellre än casperjs scriptname.js.

Kontrollera sedan:casperjs - version avkastning:1.0.0

Båda dessa versionsnummer är uppdaterade från tidpunkten för skrivandet av denna artikel.


Hej PhantomJS

Nu när vi har båda dessa körningar, låt oss göra några snabba Hello Worlds för att se till att både Phantom och Casper kör som förväntat.

Skapa en ny katalog och inuti den, gör två JavaScript-filer, hellophantom.js och hellocasper.js. Öppna dessa i redaktören efter eget val och börja med att se till att Phantom faktiskt körs korrekt.

Vi ska börja i hellophantom.js fil och skriv ett snabbtest för att ta tag i titeln på en webbsida. Jag kommer inte att täcka PhantomJS API i detalj, det här kommer bara att ge dig en snabb introduktion och testa vår installation. Om du har PhantomJS redan, kan du hoppa över den här delen.

Först måste vi ställa in ett par variabler, en som instansierar modulen "webbsida" och en annan precis som en "URL" -variabel.

var page = require ('webbsida'). skapa (), url = "http://net.tutsplus.com";

Därefter kan vi skapa den funktion som navigerar till webbsidan, vi skickar URL-adressen som ett argument och en återuppringningsfunktion. Vi får status i vår återuppringning (framgång eller misslyckande) på öppna metod.

 page.open (url, funktion (status) );

Nu kan vi ringa utvärderingsfunktionen för att få titeln på sidan. Vi kan returnera resultatet till en variabel genom att tilldela funktionen till den:

page.open (url, funktion (status) var title = page.evaluate (function () return document.title;););

Slutligen kommer vi bara att logga ut det så att vi kan se resultatet i terminalen och sedan gå ur Phantom-processen.

 console.log ('Hej, Värld! Sidtitel på' + url + 'är' + titel); phantom.exit ();

Vårt färdiga skript kommer att se ut så här.

 var page = require ('webbsida'). skapa (), url = "http://net.tutsplus.com"; page.open (url, funktion (status) var title = page.evaluate (funktion () return document.title;); console.log ('Hej, Värld! Sidtiteln på' + url + 'är' + titel); phantom.exit (););

CD i katalogen där det här skriptet är beläget och du kan köra det med följande kommando:

fantomis hellophantom.js

Efter några sekunder får du följande resultat i din terminal:

 Hej världen! Sidtiteln på http://net.tutsplus.com är webbutvecklingstutorials, från nybörjare till avancerad | Nettuts+

Det är bra, men innan vi går vidare kan vi bara göra denna kod lite mer flexibel med en snabb re-factor. Det finns några moduler som vi kan använda och en av dem är systemmodulen. Några av systemmodulens egenskaper ger dig tillgång till saker som Process ID som PhantomJS körs på eller OS används, men den vi är intresserade av är den args fast egendom.

De args egenskapen returnerar en rad kommandoradsargument. Det första objektet i matrisen är alltid skriptnamnet, men vi kan skicka några antal argument från kommandoraden och använda dem i vårt skript. Så vi kan skicka den webbadress som vi vill öppna, med fantom, i kommandoraden, så vi kan använda skriptet när som helst utan att behöva redigera det varje gång.

Vi behöver bara först kräva systemmodulen och ändra sedan url variabel för att vara det argument vi passerar genom:

system = kräver ('system'), url = system.args [1];

och nu kan vi köra skriptet med följande kommando:

phantomjs hellophantom.js http://net.tutsplus.com

Hej casper

Nu när vi vet att Phantom arbetar, kan vi fortsätta att testa Casper. Vi kommer att replikera samma test script, bara den här gången kommer vi att använda Casper API.

Först måste vi inställa en casper-instans:

var casper = kräver ("casper"). skapa ();

och ta sedan ur webbadressen från ett av argumenten som skickats från terminalen. Casper har sin egen kommandoradsparser som sitter på toppen av den som kommer med Phantom och vi kan få tillgång till alla argument som passerat genom kommandoraden, precis som vi gjorde tidigare. Den enda skillnaden är att vårt första argument kommer att vara det första vi passerar och inte skriptnamnet (som det var med Phantom)

var url = casper.cli.args [0];

Casper CLI API kan också använda namngivna alternativ samt positionsargument, vi kan använda det här om vi ville ställa in några alternativ eller vara mer ordnade med vårt skript, till exempel:

casperjs hellocasper.js argumentOne argumentTwo --option1 = this --option2 = that

och vi kan få dessa namngivna alternativ med cli.get ( 'option'), så vi kunde göra något av följande, för att passera i både argument och alternativ (om vi hade några config-alternativ som måste ställas in):

 var argumentOne = casper.cli.args [0]; var argumentTwo = casper.cli.args [1]; var thisOption = casper.cli.get ('option'); var thatOption = casper.cli.get ('option2');

För tillfället kommer jag bara att använda positionsargumentet för att få webbadressen. Nästa kommer vi att springa Start() metod för att göra någon form av navigering. Startmetoden tar en strängadress och en återuppringningsfunktion.

casper.start (url, funktion () this.echo ('Hej, Värld! Sidtiteln på' + url + 'är'););

Om du inte vill ha all din funktionalitet kan du använda sedan() metod. Varje sedan() Metodsamtal läggs till som ett steg i stapeln och körs linjärt, så snarare än ovanstående kan du ha:

 casper.start (url); casper.then (funktion () this.echo ('Hej, Värld! Sidtiteln på' + url + 'är'););

Jag föredrar att använda sedan(), som jag tycker är lättare att läsa, men det är acceptabelt och det är bara en smakfråga.

För att få titeln på sidan finns det redan en getTitle () metod tillgänglig för oss, så vi kan bara använda det i vår eko.

 casper.start (url); casper.then (funktion () this.echo ('Hej, Värld! Sidtiteln på' + url + 'är' + this.getTitle ()););

Slutligen kör vi våra steg med springa() metod, vilket är en obligatorisk metod som behövs för att ditt Casper-skript ska kunna springa. Denna metod kan också ha en valfri onComplete återuppringning för att köras när alla steg är klara. Om du använde återuppringningen måste du se till att du avslutar Casper-processen med hjälp av utgång() metod. Här är ett exempel på båda:

 // detta behöver inte använda avgångsmetoden. casper.run (); // ELLER // det här behöver utgångsmetoden casper.run (funktion () this.echo ('Allt i stacken har slutat'); this.exit ();)

Alternativt kan du bara köra utgångsmetoden efter ekot:

casper.run (funktion () this.echo ('Allt i stacken har slutat'). exit ();)

Återigen, bara en fråga om smak.

Nu ska vårt fullständiga HelloCasper.js-skript se ut så här:

var casper = kräver ("casper"). skapa (); var url = casper.cli.args [0]; casper.start (url, funktion () this.echo ('Hej, Värld! Sidtiteln på' + url + 'är' + this.getTitle ());); casper.run (funktion () this.echo ('Allt i stacken har slutat.'). exit (););

Vi kan nu köra Casper-skriptet med följande kommando:

casperjs hellocasper.js http://net.tutsplus.com

Det gör inget annat än vad vi redan gjorde med Phantom, Casper ger oss bara ett trevligt API (med några extra tillägg) för att sitta ovanpå Phantom och gör koden vi skriver lite mer ordentlig och läsbar, det här är särskilt användbart när du kommer in i skrivskript som måste navigera på en webbplats.

Låt oss nu dyka in för att spara några snapshots av vår skärm.


Snapshot Basics

Jag ska börja med en fil som heter casperscreens.js och instantiate Casper. Sätt sedan upp en matris som innehåller våra önskade visningsbredder som vi vill fånga skärmdumpar på. Varje objekt i matrisen kommer att bestå av en annan matris som kommer att ha bredden och höjden vi vill ställa in.

viewportSizes = [[320,480], [320,568], [600,1024], [1024,768], [1280,800], [1440,900]]

Jag kommer också att ställa in ett var för att få URL-adressen från kommandoraden och sedan vill jag köra en regex på webbadressen för att skapa en katalog för att spara skärmdumparna. Jag ska bara ta bort http: // dela och ersätt perioder med bindestreck. Då ska vi springa casper.start ().

 saveDir = url.replace (/ [^ a-zA-Z0-9] / gi, '-'). ersätt (/ ^ https? - + /, "); casper.start ();

Nu ska vi använda en loop och för varje visningsstorlek, ta en skärmdump av den angivna webbadressen. Vi ska ställa in visningsporten till de storlekar som definieras i det matrisobjekt vi är på - öppna URL-adressen - vänta 5000 millisekunder för att säkerställa att sidan har laddats - och ta sedan in två typer av skärmdumpar.

Den första är den faktiska höjden och bredden som definieras, för det här använder vi fånga() metod som tar två argument - en sträng för utdatafilen och ett objekt argument för att ställa in vilken del av sidan som ska klippas. Den andra är för en fullständig sida skärmdump med bara den definierade bredden och vi gör det här med hjälp av captureSelector () metod som fångar området inom den definierade väljaren, i vårt fall använder vi bara kropp och den här metoden tar två argument, den första är filnamnet och den andra är väljaren.

Även om den faktiska definierade skärmdumpen är användbar, har jag funnit att det är bra att även ha en hel sida kromlös skärmdump, så att du kan se hur hela sidan rinner.

casper.each (viewportSize, function (self, viewportSize, i) // sätt två vars för visningsportens höjd och bredd när vi slår igenom varje objekt i visningsfältet array width = viewportSize [0], height = viewportSize [1] ; // ge lite tid för sidan att ladda casper.wait (5000, funktion () // ställa in visningsporten till önskad höjd och bredd this.viewport (bredd, höjd); casper.thenOpen (url, funktion this.echo ('Opening at' + width); // Ställ in två vars, en för hela sidan spara, en för den faktiska viewporten spara var FPfilename = saveDir + '/ fullpage-' + width + ".png"; var ACfilename = sparaDir + '/' + bredd + '-' + höjd + ".png"; // Fångningsväljare tar upp hela kroppen this.captureSelector (FPfilnamn, 'body'); // fångar snaps ett definierat urval av sida this.capture (ACfilename, topp: 0, vänster: 0, bredd: bredd, höjd: höjd); this.echo ('snapshot taken'););););

Slutligen kallar vi springa() metod och i återuppringningsfunktionen kommer jag bara att echo att fångsten är klar.

casper.run (funktion () this.echo ('Avslutade fångar för' + url) .exit (););

Det fullständiga skriptet ska nu se ut så här:

 var casper = kräver ("casper"). skapa (), viewportSizes = [[320,480], [320,568], [600,1024], [1024,768], [1280,800], [1440,900]], url = casper.cli.args [0], saveDir = url.replace (/ [^ a-zA-Z0-9] / gi, '-') ersätt (/ ^ https? - + /, "); casper .start (); casper.each (viewportSize, function (self, viewportSize, i) // sätt två vars för visningsportens höjd och bredd när vi går igenom varje objekt i visningsfältet var bredden = viewportSize [0], height = viewportSize [1]; // ge lite tid för sidan att ladda casper.wait (5000, funktion () // ställa in visningsporten till önskad höjd och bredd this.viewport (bredd, höjd); casper.thenOpen (casper.thenOpen url, funktion () this.echo ('Opening at' + bredd); // Ställ in två vars, en för hela sidan spara, en för den faktiska viewporten spara var FPfilename = sparaDir + '/ fullsida-' + bredd + ".png"; var ACfilename = sparaDir + '/' + bredd + '-' + höjd + ".png"; // Capture selector fångar hela kroppen this.captureSelector (FPfilnamn, 'body'); // capture snaps ett definierat urval o f sidan this.capture (ACfilename, topp: 0, vänster: 0, bredd: bredd, höjd: höjd); this.echo ("snapshot taken"); ); ); ); casper.run (funktion () this.echo ('Avslutade fångar för' + url) .exit (););

Och nu kan vi köra det här skriptet med följande kommando:

casperjs casperscreens.js http://todomvc.com

Jag har valt att fånga några skärmar från todomvc.com helt enkelt för att det är en lyhörd webbplats som kan visa vilken typ av resultat vi letar efter.

Om du navigerar till katalogen där skriptet kördes kommer du att se att en ny katalog har skapats och inuti är alla dina PNGs.



Sammanfatta

Så vi har lyckats skriva en ganska liten bit av JavaScript som kommer att spara mycket besvär, nästa gång chefen eller klienten vill ha en massa skärmdumpar samtidigt som vi tillhandahåller ytterligare ett skript som vi kan lägga till i verktygslådan när vi gör några test . Visst, det här visar bara oss en WebKit-rendering, men för många är det tillräckligt bra.

Prova nu att integrera detta i din byggprocess, köra den tillsammans med dina andra tester och använd skärminspelningsfunktionen för att inte bara testa din webbplats, men hur en användares resa kan se på olika skärmar. Kolla även Grunt-plugin grunt-casper om Grunt är en del av din byggprocess.

Om du är fan av CoffeeScript kan du även försöka skriva om det här skriptet i CoffeeScript-syntaxen, bara se till att filen slutar med .kaffe förlängning:

 casperjs casperscreen.coffee http://example.com

Och du behöver inte ens oroa dig för att förbereda dina CoffeeScript, Casper-skript.

Det finns så mycket mer till både CasperJS och PhantomJS, så kolla in deras respektive webbplatser och se hur de kan hjälpa till med din testning.