2.droppdf.com2.droppdf.com/files/6uxtx/angularjs-test-driven-development.pdf · table of contents...
TRANSCRIPT
![Page 3: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/3.jpg)
TableofContents
AngularJSTest-drivenDevelopment
Credits
AbouttheAuthor
AbouttheReviewers
www.PacktPub.com
Supportfiles,eBooks,discountoffers,andmore
Whysubscribe?
FreeaccessforPacktaccountholders
Preface
Whatthisbookcovers
Whothisbookisfor
Conventions
Readerfeedback
Customersupport
Downloadingtheexamplecode
Errata
Piracy
Questions
1.IntroductiontoTest-drivenDevelopment
AnoverviewofTDD
FundamentalsofTDD
Measuringsuccess
Breakingdownthesteps
Measuretwicecutonce
Divingin
Settingupthetest
Creatingadevelopmentto-dolist
Testfirst
Makingitrun
www.it-ebooks.info
![Page 4: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/4.jpg)
Makingitbetter
Testingtechniques
Testingwithaframework
TestingdoubleswithJasminespies
Stubbingareturnvalue
Testingarguments
Refactoring
Buildingwithabuilder
Self-testquestions
Summary
2.TheKarmaWay
JavaScripttestingtools
Karma
Protractor
JavaScripttestingframeworks
Jasmine
Selenium
Mocha
BirthofKarma
TheKarmadifference
ImportanceofcombiningKarmawithAngularJS
InstallingKarma
Installationprerequisites
ConfiguringKarma
CustomizingKarma’sconfiguration
ConfirmingKarma’sinstallationandconfiguration
Commoninstallation/configurationissues
TestingwithKarma
ConfirmingtheKarmainstallation
UsingKarmawithAngularJS
GettingAngularJS
www.it-ebooks.info
![Page 5: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/5.jpg)
Bower
Bowerinstallation
InstallingAngularJS
InstallingAngularmocks
InitializingKarma
TestingwithAngularJSandKarma
Adevelopmentto-dolist
Testingalistofitems
Testfirst
Assemble,Act,andAssert(3A’s)
Makeitrun
Makeitbetter
Addingafunctiontothecontroller
Testfirst
Assemble,Act,andAssert(3A’s)
Makeitrun
Makeitbetter
Self-testquestions
Summary
3.End-to-endTestingwithProtractor
AnoverviewofProtractor
OriginsofProtractor
Endoflife
ThebirthofProtractor
LifewithoutProtractor
Protractorinstallation
Installationprerequisites
InstallingProtractor
InstallingWebDriverforChrome
Customizingconfiguration
Confirminginstallationandconfiguration
www.it-ebooks.info
![Page 6: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/6.jpg)
Commoninstallation/configurationissues
HelloProtractor
TDDend-to-end
Thepre-setup
Thesetup
Testfirst
Installingthetestwebserver
ConfiguringProtractor
Gettingdowntobusiness
Specification
Thedevelopmentto-dolist
Testfirst
Assemble,Act,Assert(3A’s)
Runningthetest
Makeitrun
Makeitbetter
Cleaningupthegaps
Asyncmagic
Loadingapagebeforetestexecution
Assertiononelementsthatgetloadedinpromises
TDDwithProtractor
Self-testquestions
Summary
4.TheFirstStep
Preparingtheapplication’sspecification
Settinguptheproject
Settingupthedirectory
SettingupProtractor
SettingupKarma
Settinguphttp-server
Top-downorbottom-upapproach
www.it-ebooks.info
![Page 7: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/7.jpg)
Testingacontroller
Asimplecontrollertestsetup
Initializingthescope
Bringonthecomments
Testfirst
Assemble
Act
Assert
Makeitrun
Addingthemodule
Addingtheinput
Controller
Makeitpass
Makeitbetter
ImplementingtheSubmitbutton
ConfiguringKarma
Testfirst
Assemble
Act
Assert
Makeitrun
Makeitbetter
Backupthetestchain
Bindtheinput
Onwardsandupwards
Testfirst
Assemble
Act
Assert
Makeitrun
Fixingtheunittests
www.it-ebooks.info
![Page 8: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/8.jpg)
Makeitbetter
Couplingofthetest
Self-testquestions
Summary
5.FlipFlop
Fundamentals
Protractorlocators
CSSlocators
Buttonandlinklocators
Angularlocators
URLlocationreferences
Creatinganewproject
SettingupheadlessbrowsertestingforKarma
Preconfiguration
Configuration
Walk-throughofAngularroutes
SettingupAngularJSroutes
Definingdirections
ConfiguringngRoute
Definingtheroutecontrollers
Definingtherouteviews
Assemblingtheflipfloptest
Makingtheviewsflip
Assertingaflip
Makingflipfloprun
Makingflipflopbetter
SearchingtheTDDway
Decidingontheapproach
Walk-throughofsearchquery
Thesearchquerytest
ThesearchqueryHTMLpage
www.it-ebooks.info
![Page 9: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/9.jpg)
Thesearchapplication
Showmesomeresults!
Creatingthesearchresultroutes
Testingthesearchresults
Assemblingthesearchresulttest
Selectingasearchresult
Confirmingasearchresult
Makingthesearchresulttestrun
Creatingalocation-awaretest
Makingthesearchresultbetter
ConfirmingtherouteID
SettinguptherouteIDunittest
ConfirmingtheID
Makingtherouteparameter’stestrun
Self-testquestions
Summary
6.TellingtheWorld
Beforetheplunge
Karmaconfiguration
Filewatching
Usingabottom-upapproach
Services
Publishingandsubscribingmessages
Emitting
Testingemit
Testingbroadcast
Testingbroadcast
Publishingandsubscribing–thegoodandbad
Thegood
Communicatingthroughevents
Reducingcoupling
www.it-ebooks.info
![Page 10: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/10.jpg)
Harnessingthepowerofevents
Theplan
Rebranding
Seeingrecentlyvieweditems
Testfirst
AssemblingSearchController
Selectingaproduct
Expectingeventstobepublished
Makingthesearchcontrollerrun
Recentlyviewedunittest
Testfirst
AssemblingRecentlyViewedController
Invokingarecentlyvieweditem
ConfirmingRecentlyViewedController
MakingRecentlyViewedControllerrun
End-to-endtesting
Testfirst
Assemblingtherecentlyviewedend-to-endtest
Selectingasearchresult
Confirmingrecentlyvieweditems
MakingtherecentlyViewedItemstestpass
Makingrecentlyvieweditemsbetter
Creatingaproductcart
Publishertestfirst
AssemblingsearchDetailController
Invokingthesavingofaproduct
Confirmingthesaveevent
MakingthesaveProducttestpass
Testforthesubscriberfirst
Assemblingtheproductcarttest
Invokingasavedcartevent
www.it-ebooks.info
![Page 11: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/11.jpg)
Confirmingthesavedcart
Makingthecartcontrollertestrun
End-to-endtesting
Assemblingthecart’send-to-endtest
Invokingasavetocartaction
Confirmingproductshavebeensaved
Makingthecart’send-to-endtestpass
Self-testquestions
Summary
7.GiveMeSomeData
REST–thelanguageoftheWeb
GettingstartedwithREST
Testingasynchronouscalls
CreatingasynchronouscallsinKarma
CreatingasynchronouscallsinProtractor
MakingRESTrequestsusingAngularJS
TestingwithAngularJSREST
Testingtheproductservice
Testing$httpwithKarma
MockingrequestswithProtractor
DisplayingproductswithREST
Unittestingproductrequests
Settinguptheproject
Karmaconfiguration
UsinganAPIbuilderpattern
Theproductdataservice
Theproductdatacontroller
Assemblingtheproductcontrollertest
Gettingproducts
Assertingproductdataresults
Makingtheproductdatatestsrun
www.it-ebooks.info
![Page 12: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/12.jpg)
Testingmiddle-to-end
Testfirst
Assemblingtheproducttest
Gettingproducts
Expectingproductdataresults
Makingtheproductdatarun
Testingend-to-end
Gettingtheproductdata
Self-testquestions
Summary
A.IntegratingSeleniumServerwithProtractor
Installation
Protractorconfiguration
RunningSelenium
Letitrun
Testfirst
Assemble
Assert
Makeitrun
Summary
B.AutomatingKarmaUnitTestingonCommit
GitHub
Testsetup
Testscripts
Settingthehook
Creatingthehook
AddingaTravisconfigurationfile
References
C.Answers
Chapter1,IntroductiontoTest-drivenDevelopment
Chapter2,TheKarmaWay
www.it-ebooks.info
![Page 13: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/13.jpg)
Chapter3,End-to-endTestingwithProtractor
Chapter4,TheFirstStep
Chapter5,FlipFlop
Chapter6,TellingtheWorld
Chapter7,GiveMeSomeData
Index
www.it-ebooks.info
![Page 15: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/15.jpg)
AngularJSTest-drivenDevelopmentCopyright©2015PacktPublishing
Allrightsreserved.Nopartofthisbookmaybereproduced,storedinaretrievalsystem,ortransmittedinanyformorbyanymeans,withoutthepriorwrittenpermissionofthepublisher,exceptinthecaseofbriefquotationsembeddedincriticalarticlesorreviews.
Everyefforthasbeenmadeinthepreparationofthisbooktoensuretheaccuracyoftheinformationpresented.However,theinformationcontainedinthisbookissoldwithoutwarranty,eitherexpressorimplied.Neithertheauthor,norPacktPublishing,anditsdealersanddistributorswillbeheldliableforanydamagescausedorallegedtobecauseddirectlyorindirectlybythisbook.
PacktPublishinghasendeavoredtoprovidetrademarkinformationaboutallofthecompaniesandproductsmentionedinthisbookbytheappropriateuseofcapitals.However,PacktPublishingcannotguaranteetheaccuracyofthisinformation.
Firstpublished:January2015
Productionreference:1230115
PublishedbyPacktPublishingLtd.
LiveryPlace
35LiveryStreet
BirminghamB32PB,UK.
ISBN978-1-78439-883-5
www.packtpub.com
www.it-ebooks.info
![Page 16: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/16.jpg)
CreditsAuthor
TimChaplin
Reviewers
Md.ZiaulHaq
NiveJayasekar
TimPei
AndiSmith
CommissioningEditor
PramilaBalan
AcquisitionEditor
ReshmaRaman
ContentDevelopmentEditor
ManasiPandire
TechnicalEditor
MadhunikitaSunilChindarkar
CopyEditors
GladsonMonteiro
AdithiShetty
StutiSrivastava
ProjectCoordinator
LeenaPurkait
Proofreaders
SimranBhogal
MariaGould
AmeeshaGreen
PaulHindle
Indexer
HemanginiBari
ProductionCoordinator
www.it-ebooks.info
![Page 18: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/18.jpg)
AbouttheAuthorTimChaplinlivesandbreathessoftwaresolutionsandinnovations.Duringtheday,heworkswithFortune100enterpriseapplications,andintheevening,heperfectshiscraftbycontributingtoanddistributingopensourcesoftware,writing,andconstantlylookingforwaystoincreasehisknowledgeoftechnologyandtheworld.Atanearlyage,Timbegandevelopingsoftwareandhasbeenhookedonitsince.TimisanestablishedconferencespeakerwhohasextensiveexperienceindevelopingandleadingAngularJSprojects.HehasawidebackgroundofJavaScript,C#,Java,andC++languages.Timspecializesinleadingcodequalityandtestingthroughoutallhisapplications.AfterattendingCaliforniaStateUniversity,Chico,hehasgoneontoworkinShanghai,LosAngeles,andLondon.
Iwouldliketothankmywife,Pierra,foralwaysmakingmethinkanddreambigger.Iwouldalsoliketothankmyfamilyfortheirconstantloveandsupport.Pops,thisone’sforyoubabe.
www.it-ebooks.info
![Page 19: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/19.jpg)
AbouttheReviewersMd.ZiaulHaqisaseniorsoftwareengineerfromDhaka,Bangladesh,whohasbeenworkingwiththeoDeskcoreplatformdevelopmentteamasaseniorJavaScriptdevelopersince2011.Helikestoworkmostlyonthefrontend,thoughheisafull-stackdeveloper.JavaScriptishispassionandhelikestocodeinitalldaylong.Heiswellknownasjquerygeekinthewebcommunity.
Md.Ziaulstartedhiscareerin2005asasoftwaredeveloper.HehasworkexperiencewithUNICEFlocallyandinternationally,whereheworkedwithUNICEF’swebCMS.Heiscurrentlypursuingamaster’sdegreeincomputersciencefromUnitedInternationalUniversity,Dhaka,Bangladesh.
Iwouldliketothankmywife,Richi,andmynewbornson,Arabi,whoismyinspiration.
NiveJayasekarstartedprogramminginhighschool.Inherlastyearofhighschool,shewon$10,500ataHackathonforbuildingamobileartificial-intelligenceapp.ShehasinternedatFacebookandLinkedIn,andwillsoongraduatefromCarnegieMellonUniversitywithadegreeincomputerscienceandaminorinmachinelearning.Sheisalwaysinterestedinbuildinggame-changingproducts.Shehas5yearsofexperiencebuildingwebandmobileapplicationsusingPython,AngularJS,Java,andObjectiveC.
I’dliketothankthepeopleatPacktPublishing,LeenaPurkaitandKirtiPatil,fortheirhelpinproducingthisbook.
TimPieisacomputerscienceandbusinessadministrationdoubledegreestudentattheUniversityofWaterloo,Ontario.Hehasgainedawiderangeoftechnicalskillsthroughpastprojectsandinternships,includingcloudcomputing,datamining,andfullstackwebdevelopment.Tim’scurrenttechnicalinterestisfocusingonbuildingwebapplicationsusingmodernwebtechnologies,specificallyHTML5andwebcomponents.
I’dliketothankmyparentsfortheirconstantsupportofmypursuits,whileprovidingmegreatadvicealongtheway.
AndiSmith(@andismith)isaseniorarchitectwhospecializesinfrontendsolutionsatideasandinnovationagency,AKQA.
Andihasover15yearsofexperiencebuildingfortheWebandhasworkedwithclientssuchasNike,Ubisoft,Sainsburys,Barclays,Heineken,andMINI.HehasalsocreatedanumberofopensourcepluginsandsitessuchasGruntResponsiveImages(http://www.andismith.com/grunt-responsive-images/)andSecretsoftheBrowserDeveloperTools(http://devtoolsecrets.com/).
Andimaintainsablogfocusedonfrontenddevelopmentathttp://www.andismith.com/.
Iwouldliketothankmywife,Amy,forallherloveandsupport.
www.it-ebooks.info
![Page 21: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/21.jpg)
Supportfiles,eBooks,discountoffers,andmoreForsupportfilesanddownloadsrelatedtoyourbook,pleasevisitwww.PacktPub.com.
DidyouknowthatPacktofferseBookversionsofeverybookpublished,withPDFandePubfilesavailable?YoucanupgradetotheeBookversionatwww.PacktPub.comandasaprintbookcustomer,youareentitledtoadiscountontheeBookcopy.Getintouchwithusat<[email protected]>formoredetails.
Atwww.PacktPub.com,youcanalsoreadacollectionoffreetechnicalarticles,signupforarangeoffreenewslettersandreceiveexclusivediscountsandoffersonPacktbooksandeBooks.
https://www2.packtpub.com/books/subscription/packtlib
DoyouneedinstantsolutionstoyourITquestions?PacktLibisPackt’sonlinedigitalbooklibrary.Here,youcansearch,access,andreadPackt’sentirelibraryofbooks.
www.it-ebooks.info
![Page 22: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/22.jpg)
Whysubscribe?FullysearchableacrosseverybookpublishedbyPacktCopyandpaste,print,andbookmarkcontentOndemandandaccessibleviaawebbrowser
www.it-ebooks.info
![Page 23: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/23.jpg)
FreeaccessforPacktaccountholdersIfyouhaveanaccountwithPacktatwww.PacktPub.com,youcanusethistoaccessPacktLibtodayandview9entirelyfreebooks.Simplyuseyourlogincredentialsforimmediateaccess.
www.it-ebooks.info
![Page 24: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/24.jpg)
PrefaceThebookwillprovidethereaderwithacompleteguidetothetest-drivendevelopment(TDD)approachforAngularJS.Itwillprovidestep-by-step,clearexamplestocontinuallyreinforceTDDbestpractices.ThebookwilllookatbothunittestingwithKarmaandend-to-endtestingwithProtractor.Itwillnotonlyfocusonhowtousethetools,butalsoonunderstandingthereasontheywerebuilt,andwhytheyshouldbeused.Throughout,therewillbefocusonwhen,where,andhowtousethesetools,constantlyreinforcingtheprinciplesoftheTDDlifecycle(test,execute,refactor).
www.it-ebooks.info
![Page 25: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/25.jpg)
WhatthisbookcoversThisbookisbasicallysplitintotwoparts.TheinitialchaptersfocusontheTDDlifecycle,andhowKarmaandProtractorfitintothelifecycleanddevelopmentofanAngularJSapplication.Asweproceed,you’llgetastep-by-stepapproachtoAngularJSTDDusingKarmaandProtractor.EachofthechaptersbuildsuponthepreviousoneandintroduceshowtotestseveraldifferentAngularJScomponents.
Chapter1,IntroductiontoTest-drivenDevelopment,isanintroductiontotheconceptsofTDDandtestingtechniques.
Chapter2,TheKarmaWay,explorestheoriginsofKarmaandwhyitisanessentialtoolforanyAngularJSproject.
Chapter3,End-to-endTestingwithProtractor,introducesthesimplicityofProtractor,anend-to-endtestingtoolbuiltspecificallyforAngularJS.
Chapter4,TheFirstSteps,coverstheTDDjourneyandshowsthefundamentalsandtoolsinaction.
Chapter5,FlipFlop,expandstoincludetestingformultiplecontrollers,partialviews,locationreferences,CSS,andHTMLelementbuildingontheinitialfoundationalaspectslearnedinthepreviouschapter.
Chapter6,TellingtheWorld,divesintocommunicatingacrosscontrollers,andtestingservicesandbroadcasting.
Chapter7,GiveMeSomeData,divesintohowtoapplyseveraloftheconceptsshownpreviously,andextendthemtopulldatausinganexternalAPI.
AppendixA,IntegratingSeleniumServerwithProtractor,walksthroughsettingupandconfiguringProtractortouseastandaloneSeleniumserver.
AppendixB,AutomatingKarmaUnitTestingonCommit,covershowtosetupTravisCI,aplatformforcontinuousintegration,andsettingupKarmatotestyourapplication.
www.it-ebooks.info
![Page 26: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/26.jpg)
WhothisbookisforThisbookisforthedeveloperwhowantstogobeyondthebasictutorials,andwantstotaketheplungeintoAngularJSdevelopment.ThisbookisforthedeveloperwhohasexperiencewithAngularJSandhaswalkedthroughthebasictutorialsbutwantstounderstandthewidercontextofwhen,why,andhowtoapplytestingtechniquesandbestpracticestocreatequality-cleancode.Togetthemostoutofthisbook,itispreferredthatthereaderhasbasicunderstandingofHTML,JavaScript,andAngularJS.
www.it-ebooks.info
![Page 27: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/27.jpg)
ConventionsInthisbook,youwillfindanumberofstylesoftextthatdistinguishbetweendifferentkindsofinformation.Herearesomeexamplesofthesestylesandanexplanationoftheirmeaning.
Codewordsintext,databasetablenames,foldernames,filenames,fileextensions,pathnames,dummyURLs,userinput,andTwitterhandlesareshownasfollows:“Createawebpageandimportcalculator.jsfortesting.”
Ablockofcodeissetasfollows:
<!DOCTYPEhtml>
<html>
<head>
<title></title>
</head>
<body>
<scriptsrc="calculator.js"></script>
</body>
</html>
Anycommand-lineinputoroutputiswrittenasfollows:
$nodecalculator.js
Newtermsandimportantwordsareshowninbold.Wordsthatyouseeonthescreen,inmenusordialogboxesforexample,appearinthetextlikethis:“Traditionally,testswererunbyhavingtomanuallylaunchabrowserandcheckforresultsbycontinuallyhittingtheRefreshbutton.”
NoteWarningsorimportantnotesappearinaboxlikethis.
TipTipsandtricksappearlikethis.
www.it-ebooks.info
![Page 28: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/28.jpg)
ReaderfeedbackFeedbackfromourreadersisalwayswelcome.Letusknowwhatyouthinkaboutthisbook—whatyoulikedordisliked.Readerfeedbackisimportantforusasithelpsusdeveloptitlesthatyouwillreallygetthemostoutof.
Tosendusgeneralfeedback,simplye-mail<[email protected]>,andmentionthebook’stitleinthesubjectofyourmessage.
Ifthereisatopicthatyouhaveexpertiseinandyouareinterestedineitherwritingorcontributingtoabook,seeourauthorguideatwww.packtpub.com/authors.
www.it-ebooks.info
![Page 29: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/29.jpg)
CustomersupportNowthatyouaretheproudownerofaPacktbook,wehaveanumberofthingstohelpyoutogetthemostfromyourpurchase.
www.it-ebooks.info
![Page 30: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/30.jpg)
DownloadingtheexamplecodeYoucandownloadtheexamplecodefilesfromyouraccountathttp://www.packtpub.comforallthePacktPublishingbooksyouhavepurchased.Ifyoupurchasedthisbookelsewhere,youcanvisithttp://www.packtpub.com/supportandregistertohavethefilese-maileddirectlytoyou.
www.it-ebooks.info
![Page 31: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/31.jpg)
ErrataAlthoughwehavetakeneverycaretoensuretheaccuracyofourcontent,mistakesdohappen.Ifyoufindamistakeinoneofourbooks—maybeamistakeinthetextorthecode—wewouldbegratefulifyoucouldreportthistous.Bydoingso,youcansaveotherreadersfromfrustrationandhelpusimprovesubsequentversionsofthisbook.Ifyoufindanyerrata,pleasereportthembyvisitinghttp://www.packtpub.com/submit-errata,selectingyourbook,clickingontheErrataSubmissionFormlink,andenteringthedetailsofyourerrata.Onceyourerrataareverified,yoursubmissionwillbeacceptedandtheerratawillbeuploadedtoourwebsiteoraddedtoanylistofexistingerrataundertheErratasectionofthattitle.
Toviewthepreviouslysubmittederrata,gotohttps://www.packtpub.com/books/content/supportandenterthenameofthebookinthesearchfield.TherequiredinformationwillappearundertheErratasection.
www.it-ebooks.info
![Page 32: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/32.jpg)
PiracyPiracyofcopyrightmaterialontheInternetisanongoingproblemacrossallmedia.AtPackt,wetaketheprotectionofourcopyrightandlicensesveryseriously.Ifyoucomeacrossanyillegalcopiesofourworks,inanyform,ontheInternet,pleaseprovideuswiththelocationaddressorwebsitenameimmediatelysothatwecanpursuearemedy.
Pleasecontactusat<[email protected]>withalinktothesuspectedpiratedmaterial.
Weappreciateyourhelpinprotectingourauthors,andourabilitytobringyouvaluablecontent.
www.it-ebooks.info
![Page 33: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/33.jpg)
QuestionsYoucancontactusat<[email protected]>ifyouarehavingaproblemwithanyaspectofthebook,andwewilldoourbesttoaddressit.
www.it-ebooks.info
![Page 34: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/34.jpg)
Chapter1.IntroductiontoTest-drivenDevelopmentAngularJSisattheforefrontofclient-sideJavaScripttesting.EveryAngularJStutorialincludesanaccompanyingtest,andeventtestmodulesarepartofthecoreAngularJSpackage.TheAngularteamisfocusedonmakingtestingfundamentaltowebdevelopment.
Thischapterintroducesyoutothefundamentalsoftest-drivendevelopmentwithAngularJSincluding:
Anoverviewoftest-drivendevelopment(TDD)TheTDDlifecycle:testfirst,makeitrun,makeitbetterCommontestingtechniques
www.it-ebooks.info
![Page 35: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/35.jpg)
AnoverviewofTDDTDDisnotusedonlytodevelopsoftware.Thefundamentalprinciplescanbeseeninmanyindustries.ThissectionwillexplorethefundamentalsofTDDandhowtheyareappliedbyatailor.
www.it-ebooks.info
![Page 36: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/36.jpg)
FundamentalsofTDDKnowwhattocodebeforeyoucode.Thismaysoundcliché,butthisisessentiallywhatTDDgivesyou.TDDbeginsbydefiningexpectations,thenmakesyoumeettheexpectations,andfinallyforcesyoutorefinethechangesaftertheexpectationshavebeenmet.
HereareacoupleofclearbenefitsofusingTDD:
Knowingbeforeyoucode:Atestprovidesaclearvisionofwhatcodeneedstodoinordertobesuccessful.Settinguptestsfirstallowsfocusononlycomponentsthathavebeendefinedintests.Confidenceinrefactoring:Refactoringinvolvesmoving,fixing,andchangingaproject.Testsprotectthecorelogicfromrefactoringbyensuringthatthelogicbehavesindependentlyofthecodestructure.Documentation:Testsdefineexpectationsthataparticularobjectorfunctionmustmeet.Theexpectationactsasacontract,andcanbeusedtoseehowamethodshouldorcanbeused.Thismakesthecodereadableandeasiertounderstand.
www.it-ebooks.info
![Page 37: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/37.jpg)
MeasuringsuccessTDDisnotjustasoftwaredevelopmentpractice.Thefundamentalprinciplesaresharedbyothercraftsmenaswell.Oneofthesecraftsmenisatailor,whosesuccessdependsonprecisemeasurementsandcarefulplanning.
BreakingdownthestepsHerearethehigh-levelstepsatailortakestomakeasuit:
1. Testfirst:
DeterminingthemeasurementsforthesuitHavingthecustomerdeterminethestyleandmaterialtheywantfortheirsuitMeasuringthecustomer’sarms,shoulders,torso,waist,andlegs
2. Makingthecuts:
MeasuringthefabricandcutSelectingthefabricbasedonthedesiredstyleMeasuringthefabricbasedonthecustomer’swaistandlegsCuttingthefabricbasedonthemeasurements
3. Refactoring:
Comparingtheresultingproducttotheexpectedstyle,reviewing,andmakingchangesComparingthecutandlooktothecustomer’sdesiredstyleMakingadjustmentstomeetthedesiredstyle
4. Repeating:
Testfirst:DeterminingthemeasurementsforthepantsMakingthecuts:MeasuringthefabricandmakingthecutsRefactor:Makingchangesbasedonthereviews
TheprecedingstepsareanexampleofaTDDapproach.Themeasurementsmustbetakenbeforethetailorcanstartcuttinguptherawmaterial.Imagineforamomentifthetailordidn’tuseatest-drivenapproachanddidn’tuseameasuringtape(testingtool).Itwouldberidiculousifthetailorstartedcuttingbeforemeasuring.
Asadeveloper,doyou“cutbeforemeasuring”?Wouldyoutrustatailorwithoutameasuringtape?Howwouldyoufeelaboutadeveloperwhodoesn’ttest?
MeasuretwicecutonceThetailoralwaysstartswithmeasurements.Whatwouldhappenifthetailormadecutsbeforemeasuring?Whatwouldhappenifthefabricwascuttooshort?Howmuchextratimewouldgointothetailoring?Measuretwice,cutonce.
Softwaredeveloperscanchoosefromanendlessamountofapproachestousebefore
www.it-ebooks.info
![Page 38: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/38.jpg)
startingdeveloping.Onecommonapproachistoworkoffaspecification.Adocumentedapproachmayhelpindefiningwhatneedstobebuilt;however,withouttangiblecriteriaforhowtomeetaspecification,theactualapplicationthatgetsdevelopedmaybecompletelydifferentthanthespecification.WithaTDDapproach(testfirst,makeitrun,andmakeitbetter),everystageoftheprocessverifiesthattheresultmeetsthespecification.Thinkabouthowatailorcontinuestouseameasuringtapetoverifythesuitthroughouttheprocess.
TDDembodiesatest-firstmethodology.TDDgivesdeveloperstheabilitytostartwithacleargoalandwritecodethatwilldirectlymeetaspecification.Developlikeaprofessionalandfollowthepracticesthatwillhelpyouwritequalitysoftware.
www.it-ebooks.info
![Page 39: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/39.jpg)
DivinginItistimetodiveintosomeactualcode.Thiswalk-throughwilltakeyouthroughaddingthemultiplicationfunctionalitytoacalculator.RemembertheTDDlifecycle:testfirst,makeitrun,andmakeitbetter.
SettingupthetestTheinitialcalculatorisinafilecalledcalculator.jsandisinitializedasanobjectasfollows:
varcalculator={};
ThetestwillberunthroughawebbrowserusingabasicHTMLpage.Createawebpageandimportcalculator.jstotestit.SavethewebpageastestRunner.html.Torunthetest,openabrowserandruntestRunner.html.HereisthecodefortestRunner.html:
<!DOCTYPEhtml>
<html>
<head>
<title></title>
</head>
<body>
<scriptsrc="calculator.js"></script>
</body>
</html>
Nowthattheprojectissetup,thenextstepistocreatethedevelopmentto-dolist.
Creatingadevelopmentto-dolistAdevelopmentto-dolisthelpsorganizeandfocusyourtasks.Italsoprovidesaplacetowritedownideasduringthedevelopmentprocess.
Hereistheinitialstepforcreatingadevelopmentto-dolist:
Addmultiplicationfunctionality:3*3=9
Theprecedinglistdescribeswhatneedstobedone.Italsoprovidesaclearexampleofhowtoverifymultiplication:3*3=9.
TestfirstAlthoughyoucanwritethemultiplicationfunctionquickly,rememberthatoncethehabitofTDDissetinplace,itwillbejustasquicktowritethetestandcode.Herearethestepsforthefirsttest:
1. Opencalculator.js.2. Createanewfunctiontotestmultiplying3*3:
functionmultipleTest1(){
//Test
www.it-ebooks.info
![Page 40: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/40.jpg)
varresult=calculator.multiply(3,3);
//AssertResultisexpected
if(result===9){
console.log('TestPassed');
}
else{
console.log('TestFailed');
}
};
Thetestcallsamultiplyfunction,whichstillneedstobedefined.Itthenassertsthattheresultsareasexpectedbydisplayingapassorfailmessage.Remember,inTDD,youarelookingattheuseofthemethodandexplicitlywritinghowitshouldbeused.Thisallowsyoutodefinetheinterfacethroughausecase,asopposedtoonlylookingatthelimitedscopeofthefunctionbeingdeveloped.
ThenextstepintheTDDlifecyclewillbefocusedonmakingthetestrun.
MakingitrunThisstepisaboutmakingthetestrun,justasthetailordidwiththesuit.Themeasurementsweretakenduringtheteststep,andnowtheapplicationcanbemoldedtofitthemeasurements.Herearethestepstorunthetest:
1. OpenthebrowserwithtestRunner.html.2. OpentheJavaScriptdeveloperConsolewindow.
Thetestthrowsanerror,asshowninthefollowingscreenshot:
Theerrorthrownisexpectedasthecalculatorapplicationcallsafunctionthathasn’tbeencreatedyet:calculator.multiply.
InTDD,thefocusisonaddingthesmallestchangetogetatesttopass.Thereisnoneedtoactuallyimplementthemultiplicationlogic.Thismayseemunintuitive.Thepointisonceapassingtestexists,itshouldalwayspass.Whenamethodcontainsfairlycomplexlogic,itiseasiertorunapassingtestagainstittoensureitmeetstheexpectations.
Whatisthesmallestchangethatcanbemadetomakethetestpass?Byreturningtheexpectedvalueof9,thetestshouldpass.Althoughthiswon’taddthemultiplyfunction,itwillconfirmtheapplicationwiring.Inaddition,afteryouhavepassedthetest,makingfuturechangeswillbeeasyasyouhavetosimplykeepthetestpassing!
Now,addthemultiplyfunctionandhaveitreturntherequiredvalue9:
www.it-ebooks.info
![Page 41: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/41.jpg)
varcalculator={
multiply:function(){
return9;
}
};
Inthebrowser,theJavaScriptconsolererunsthetest.Theresultshouldbeasfollows:
Yes!Thetestpassed.Timetocrossoutthefirstitemfromtheto-dolist:
Addmultiplicationfunctionality:3*3=9
Nowthatthereisapassingtest,thenextstepwillbetoremovethehardcodedvalueinthemultiplyfunction.
MakingitbetterTherefactoringstepneedstoremovethehardcodedreturnvalueofthemultiplyfunction.Therequiredlogicisasfollows:
varcalculator={
multiply:function(amount1,amount2){
returnamount1*amount2;
}
};
Rerunthetestsandconfirmthetestpasses.Excellent!Nowthemultiplyfunctioniscomplete.Hereisthefullcodeforthecalculatorandtest:
varcalculator={
multiply:function(amount1,amount2){
returnamount1*amount2;
}
};
varmultipleTest1=function(){
varresult=calculator.multiply(3,3);
if(result===9){
console.log('TestPassed');
}
else{
console.log('TestFailed');
}
};
www.it-ebooks.info
![Page 43: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/43.jpg)
TestingtechniquesItisimportanttounderstandsomefundamentaltechniquesandapproachestotesting.Thissectionwillwalkyouthroughacoupleofexamplesoftechniquesthatwillbeleveragedinthisbook.Thisincludes:
TestingdoubleswithJasminespiesRefactoringBuildingpatterns
Inaddition,hereareadditionaltermsthatwillbeused:
Functionundertest:Thisisthefunctionbeingtested.Itisalsoreferredtoassystemundertest,objectundertest,andsoon.The3A’s(Arrange,Act,andAssert):Thisisatechniqueusedtosetuptests,firstdescribedbyBillWake(http://xp123.com/articles/3a-arrange-act-assert/).The3A’swillbediscussedfurtherinChapter2,TheKarmaWay.
www.it-ebooks.info
![Page 44: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/44.jpg)
TestingwithaframeworkAlthoughasimplewebpagecanbeusedtoperformtests,asseenearlierinthischapter,itismucheasiertouseatestingframework.Atestingframeworkprovidesmethodsandstructurestotest.Thisincludesastandardstructuretocreateandruntests,theabilitytocreateassertions/expectations,theabilitytousetestdoubles,andmore.ThisbookusesJasmineasthetestframework.Jasmineisabehavior-driventestingframework.ItishighlycompatiblewithtestingAngularJSapplications.InChapter2,TheKarmaWay,wewilltakeamorein-depthlookatJasmine.
www.it-ebooks.info
![Page 45: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/45.jpg)
TestingdoubleswithJasminespiesAtestdoubleisanobjectthatactsandisusedinplaceofanotherobject.Takealookatthefollowingobjectthatneedstobetested:
varobjectUnderTest={
someFunction:function(){}
};
Usingatestdouble,youcandeterminethenumberoftimessomeFunctiongetscalled.Hereisanexample:
varobjectUnderTest={
someFunction:function(){}
};
jasmine.spyOn(objectUnderTest,'someFunction');
objectUnderTest.someFunction();
objectUnderTest.someFunction();
console.log(objectUnderTest.someFunction.count);
TheprecedingcodecreatesatestdoubleusingaJasminespy(jasmine.spyOn).ThetestdoubleisthenusedtodeterminethenumberoftimessomeFunctiongetscalled.AJasminetestdoubleoffersthefollowingfeaturesandmore:
ThecountofcallsonafunctionTheabilitytospecifyareturnvalue(stubareturnvalue)Theabilitytopassacalltotheunderlyingfunction(passthrough)
Throughoutthisbook,youwillgainfurtherexperienceintheuseoftestdoubles.
StubbingareturnvalueThegreatthingaboutusingatestdoubleisthattheunderlyingcodeofamethoddoesnothavetobecalled.Withatestdouble,youcanspecifyexactlywhatamethodshouldreturnforagiventest.Hereisanexamplefunction:
varobjectUnderTest={
someFunction:function(){return'stubme!';}
};
Theprecedingobject(objectUnderTest)hasafunction(someFunction)thatneedstobestubbed.HereishowyoucanstubthereturnvalueusingJasmine:
jasmine.spyOn(objectUnderTest,'someFunction')
.and
.returnValue('stubbedvalue');
Now,whenobjectUnderTest.someFunctioniscalled,stubbedvaluewillbereturned.Hereishowtheprecedingstubbedvaluecanbeconfirmedusingconsole.log:
varobjectUnderTest={
www.it-ebooks.info
![Page 46: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/46.jpg)
someFunction:function(){return'stubme!';}
};
//beforethereturnvalueisstubbed
Console.log(objectUnderTest.someFunction());
//displays'stubme'
jasmine.spyOn(objectUnderTest,'someFunction')
.and
.returnValue('stubbedvalue');
//Afterthereturnvalueisstubbed
Console.log(objectUnderTest.someFunction());
//displays'stubbedvalue'
TestingargumentsAtestdoubleprovidesinsightsintohowamethodisusedinanapplication.Asanexample,atestmightwanttoassertwhatargumentsamethodwascalledwithorthenumberoftimesamethodwascalled.Hereisanexamplefunction:
varobjectUnderTest={
someFunction:function(arg1,arg2){}
};
Herearethestepstotesttheargumentstheprecedingfunctioniscalledwith:
1. Createaspysothattheargumentscalledcanbecaptured:
jasmine.spyOn(objectUnderTest,'someFunction');
2. Thentoaccessthearguments,dothefollowing:
//Gettheargumentsforthefirstcallofthefunction
varcallArgs=objectUnderTest.someFunction.call.argsFor(0);
console.log(callArgs);
//displays['param1','param2']
3. Hereishowtheargumentscanbedisplayedusingconsole.log:
varobjectUnderTest={
someFunction:function(arg1,arg2){}
};
//createthespy
jasmine.spyOn(objectUnderTest,'someFunction');
//Callthemethodwithspecificarguments
objectUnderTest.someFunction('param1','param2');
//Gettheargumentsforthefirstcallofthefunction
varcallArgs=objectUnderTest.someFunction.call.argsFor(0);
console.log(callArgs);
//displays['param1','param2']
www.it-ebooks.info
![Page 48: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/48.jpg)
RefactoringRefactoringistheactofrestructuring,rewriting,renaming,andremovingcodeinordertoimprovethedesign,readability,maintainability,andoverallaestheticofapieceofcode.TheTDDlifecyclestepof“makingitbetter”isprimarilyconcernedwithrefactoring.Thissectionwillwalkyouthrougharefactoringexample.Hereisanexampleofafunctionthatneedstoberefactored:
varabc=function(z){
varx=false;
if(z>10)
returntrue;
returnx;
}
Thisfunctionworksfineanddoesnotcontainanysyntacticalorlogicalissues.Theproblemisthatthefunctionisdifficulttoreadandunderstand.Refactoringthisfunctionwillimprovethenaming,structure,anddefinition.Theexercisewillremovethemasqueradingcomplexityandrevealthefunction’struemeaningandintention.Herearethesteps:
1. Renamethefunctionandvariablenamestobemoremeaningful,thatis,renamexandzsothattheymakesense:
varisTenOrGreater=function(value){
varfalseValue=false;
if(value>10)
returntrue;
returnfalseValue;
}
2. Now,thefunctioncaneasilybereadandthenamingmakessense.3. Removeunnecessarycomplexity.Inthiscase,theifconditionalstatementcanbe
removedcompletely:
varisTenOrGreater=function(value){
returnvalue>10;
};
4. Reflectontheresult.
Atthispoint,therefactoriscomplete,andthefunction’spurposeshouldjumpoutatyou.Theremainingquestionthatshouldbeaskedis“whydoesthismethodexistinthefirstplace?”.
Thisexampleonlyprovidedabriefwalk-throughofthestepsthatcanbetakentoidentifyissuesincodeandhowtoimprovethem.Otherexampleswillbeusedthroughoutthisbook.
www.it-ebooks.info
![Page 49: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/49.jpg)
BuildingwithabuilderThebuilderpatternusesabuilderobjecttocreateanotherobject.Imagineanobjectwithtenproperties.Howwilltestdatabecreatedforeveryproperty?Willtheobjecthavetoberecreatedineverytest?
Abuilderobjectdefinesanobjecttobereusedacrossmultipletests.Thefollowingcodesnippetprovidesanexampleoftheuseofthispattern.Thisexamplewillusebuilderobjectinthevalidatemethod:
varbook={
id:null,
author:null,
dateTime:null
};
Thebookobjecthasthreeproperties:id,author,anddateTime.Fromatestingperspective,youwouldwanttheabilitytocreateavalidobject,thatis,onethathasallthefieldsdefined.Youmayalsowanttocreateaninvalidobjectwithmissingproperties,oryoumaywanttosetcertainvaluesintheobjecttotestthevalidationlogic,thatis,dateTimeisanactualdate.
HerearethestepstocreateabuilderforthedateTimeobject:
1. Createabuilderfunction:
varbookBuilder=function();
2. Createavalidobjectwithinthebuilder:
varbookBuilder=function(){
var_resultBook={
id:1,
author:'AnyAuthor',
dateTime:newDateTime()
};
}
3. Createafunctiontoreturnthebuiltobject:
varbookBuilder=function(){
var_resultBook={
id:1,
author:"AnyAuthor",
dateTime:newDateTime()
};
this.build=function(){
return_resultBook;
}
}
4. Createanotherfunctiontosetthe_resultBookauthorfield:
varbookBuilder=function(){
www.it-ebooks.info
![Page 50: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/50.jpg)
var_resultBook={
id:1,
author:'AnyAuthor',
dateTime:newDateTime()
};
this.build=function(){
return_resultBook;
};
this.setAuthor=function(author){
_resultBook.author=author;
};
};
5. Makethefunctionfluentsothatcallscanbechained:
this.setAuthor=function(author){
_resultBook.author=author;
returnthis;
};
6. AsetterfunctionwillalsobecreatedfordateTime:
this.setDateTime=function(dateTime){
_resultBook.dateTime=dateTime;
returnthis;
};
Now,bookBuildercanbeusedtocreateanewbookasfollows:
varbuiltBook=bookBuilder.setAuthor('TimChaplin')
.setDateTime(newDate())
.build();
Theprecedingbuildercannowbeusedthroughoutyourteststocreateasingleconsistentobject.Hereisthecompletebuilderforyourreference:
varbookBuilder=function(){
var_resultBook={
id:1,
author:'AnyAuthor',
dateTime:newDateTime()
};
this.build=function(){
return_resultBook;
};
this.setAuthor=function(author){
_resultBook.author=author;
returnthis;
};
this.setDateTime=function(dateTime){
_resultBook.dateTime=dateTime;
returnthis;
};
www.it-ebooks.info
![Page 51: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/51.jpg)
};
TipDownloadingtheexamplecode
Youcandownloadtheexamplecodefilesfromyouraccountathttp://www.packtpub.comforallthePacktPublishingbooksyouhavepurchased.Ifyoupurchasedthisbookelsewhere,youcanvisithttp://www.packtpub.com/supportandregistertohavethefilese-maileddirectlytoyou.
www.it-ebooks.info
![Page 52: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/52.jpg)
Self-testquestionsQ1.Atestdoubleisanothernameforaduplicatetest.
1. True2. False
Q2.TDDstandsfortest-drivendevelopment.
1. True2. False
Q3.Thepurposeofrefactoringistoimprovecodequality.
1. True2. False
Q4.Atestobjectbuilderconsolidatesthecreationofobjectsfortesting.
1. True2. False
Q5.The3A’sareasportsteam.
1. True2. False
www.it-ebooks.info
![Page 53: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/53.jpg)
SummaryThischapterprovidedanintroductiontoTDD.ItdiscussedtheTDDlifecycle(testfirst,makeitrun,makeitbetter)andshowedhowthesamestepsareusedbyatailor.Finally,itlookedoversomeofthetestingtechniquesthatwillbediscussedthroughoutthisbookincluding:
TestdoublesRefactoringBuildingpatterns
AlthoughTDDisahugetopic,thisbookissolelyfocusedontheTDDprinciplesandpracticestobeusedwithAngularJS.Inthenextchapter,youwillstartthejourneyandseehowtosetuptheKarmatestrunner.
www.it-ebooks.info
![Page 54: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/54.jpg)
Chapter2.TheKarmaWayJavaScripttestinghashitthemainstream,thankstoKarma.KarmamakesitseamlesstotestJavaScript.AngularJSwascreatedaroundtesting.ThischapterexplorestheoriginsofKarmaandwhyithastobeusedinanyAngularJSproject.Bytheendofthischapter,youwillnotonlyunderstandtheproblemthatKarmasolves,butalsowalkthroughacompleteexampleusingit.
www.it-ebooks.info
![Page 55: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/55.jpg)
JavaScripttestingtoolsKnowingwhatthedifferenttestingtoolsareishalfthebattle.Inthissection,youwilllearnaboutthetwoprimarytoolsthatwillbediscussedandusedthroughoutthebook.Theyare:
Karma:ThisisatestrunnerProtractor:Thisisanend-to-endtestingframework
www.it-ebooks.info
![Page 56: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/56.jpg)
KarmaBeforediscussingwhatKarmais,itisbesttodiscusswhatitisn’t.Itisn’taframeworktowritetests.Itisatestrunner.WhatthismeansisthatKarmagivesyoutheabilitytoruntestsinseveraldifferentbrowsersinanautomatedway.Inthepast,developershadtoperformmanualstepstodothis,including:
1. Openingupabrowser2. PointingthebrowsertotheprojectURL3. Runningthetests4. Confirmingthatalltestshavepassed5. Makingchanges6. Refreshingthepage
WithKarma,automationgivesthedevelopertheabilitytorunasinglecommandanddeterminewhetheranentiretestsuitehaspassedorfailed.FromaTDDperspective,thisgivesyoutheabilitytofindandfixfailingtestsquickly.SomeoftheprosandconsofusingKarmacomparedtoamanualprocessareasfollows:
Pros Cons
Abilitytoautomatetestsinmultiplebrowsersanddevices. Additionaltooltolearn,configure,andmaintain.
Abilitytowatchfiles.
Onlinedocumentationandsupport.
Doesonething—runsJavaScripttests—anddoesitwell.
Easytointegratewithacontinuousintegrationserver.
AutomatingtheprocessoftestingandusingKarmaisextremelyadvantageous.IntheTDDjourneythroughthisbook,Karmawillbeoneofyourprimarytools.
www.it-ebooks.info
![Page 57: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/57.jpg)
ProtractorProtractorisanend-to-endtestingtool.Itallowsdeveloperstomimicuserinteractions.Itautomatesthetestingoffunctionalityandfeaturesthroughtheinteractionofawebbrowser.ProtractorhasspecificmethodstoassistwithtestingAngularJS,buttheyarenotexclusivetoAngularJS.SomeoftheprosandconsofusingProtractorareasfollows:
Pros Cons
Configurabletotestmultipleenvironments Documentationandexamplesarelimited
EasyintegrationwithAngularJS
Syntaxandtestingcanbesimilartothetestingframeworkchosenforunittesting
www.it-ebooks.info
![Page 58: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/58.jpg)
JavaScripttestingframeworksInthissection,youwilllearnaboutthetestingframeworksthatwillsupportyouinyourTDDpractices.Theseinclude:
JasmineSeleniumMocha
www.it-ebooks.info
![Page 59: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/59.jpg)
JasmineJasmineisaJavaScripttestingframework.ItcanbeeasilyintegratedandrunforwebsitesandisagnostictoAngularJS.Itprovidesspiesandotherfeatures.ItcanalsoberunonitsownwithoutKarma.Someoftheprosandconsareasfollows:
Pros Cons
DefaultintegrationwithKarma. Nofile-watchingfeatureavailablewhenrunningtests.Thismeansthattestshavetobererunbytheuserastheychange.
Providesadditionalfunctionstoassistwithtesting,suchastestspies,fakes,andthepass-throughfunctionality. ThelearningcurvecanbesteepforalltheProtractormethodsandfeatures.
Cleansreadablesyntaxthatallowsteststobeformattedinawaythatrelatestothebehaviorbeingtested.
Integrationwithseveraloutputreporters.
www.it-ebooks.info
![Page 60: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/60.jpg)
SeleniumSelenium(http://www.seleniumhq.org/)definesitselfas:
“Seleniumautomatesbrowsers.That’sit!”
Automationofbrowsersmeansthatdeveloperscaninteractwithbrowserseasily.Theycanclickonbuttonsorlinks,enterdata,andsoon.Seleniumisapowerfultoolsetthat,whenusedandsetupproperly,haslotsofbenefits;however,itcanbeconfusingandcumbersometosetitup.SomeoftheprosandconsofSeleniumareasfollows:
Pros Cons
Largefeatureset Hastoberunasaseparateprocess
Distributedtesting Severalstepstoconfigure
SaaSsupportthroughservicessuchasSauceLabs
Documentationandresourcesavailable
AsProtractorisawrapperaroundSelenium,itwon’tbediscussedindetail.ProtractorwillbefurtherintroducedinChapter3,End-to-endTestingwithProtractor.
www.it-ebooks.info
![Page 61: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/61.jpg)
MochaMochaisatestingframeworkoriginallywrittenforNode.jsapplicationsbutsupportsbrowsertestingaswell.ItisverysimilartoJasmineandmirrorsmuchofitssyntax.Let’sdiscusssomeoftheprosandconsofMocha:
Pros Cons
Easytoinstall Separateplugins/modulesrequiredforassertions,spies,andsoon
Gooddocumentationavailable AdditionalconfigurationrequiredtouseitwithKarma
Hasseveralreporters
Plugsinwithseveralnodeprojects
TheapproachofbeingjustatestrunnerandnotworryingaboutassertionsandmockingfitsintotheNode.jsmantra—smallindividualmodulesthatdoonething.ForNode.jsprojects,IprefertogowithMocha.ThereasonisthatyoucanaddnewNodePackageManager(npm)modulesforthespecificpluginsneeded.Whenworkingwithawebsite,andspecificallyAngularJS,IprefertouseJasmine.Itprovidesthefeaturesneededwithouthavingtoinstalladditionalnpmmodulestoanon-Node.jsproject.
www.it-ebooks.info
![Page 62: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/62.jpg)
BirthofKarmaWhenpickingupanewtool,itisimportanttounderstandwhereitcamefromandwhyitwasbuilt.ThissectiongivesyousomebackgroundoftheoriginsofKarma.
www.it-ebooks.info
![Page 63: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/63.jpg)
TheKarmadifferenceKarmawascreatedbyVojtechJína.Theprojectwasoriginallycalledtestacular.InVojtechJína’sthesis,hediscussesthedesign,purpose,andimplementationofKarma.Inhisthesis(JavasScriptTestRunner,page6,https://github.com/karma-runner/karma/raw/master/thesis.pdf),hedescribesKarmaas:
“…atestrunner,thathelpswebapplicationdeveloperstobemoreproductiveandeffectivebymakingautomatedtestingsimplerandfaster.Infact,Ihaveamuchhigherambitionandthisthesisisonlyapartofit-IwanttopromoteTestDrivenDevelopment(TDD)as“the”waytodevelopwebapplications,becauseIbelieveitisthemosteffectivewaytodevelophighqualitysoftware.”
KarmahastheabilitytoeasilyandautomaticallyrunJavaScriptunittestsonrealbrowsers.Traditionally,testswererunbyhavingtomanuallylaunchabrowserandcheckforresultsbycontinuallyhittingtheRefreshbutton.Thismethodwasawkwardandoftenresultedindeveloperslimitingtheamountofteststhatwerewritten.
WithKarma,adevelopercanwriteatestinalmostanystandardtestframework,chooseabrowsertorunagainst,setthefilestowatchforchanges,andbam!Continuousautomatedtesting.Simplychecktheoutputwindowforfailedorpassedtests.
www.it-ebooks.info
![Page 64: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/64.jpg)
ImportanceofcombiningKarmawithAngularJSKarmawasbuiltforAngularJS.PriortoKarma,therewasalackofautomatedtestingtoolsforweb-basedJavaScriptdevelopers.
Remember,Karmaisatestrunner,notatestframework.Itsjobistoruntestsandreportwhichtestswillpassorfail.Whyisthishelpful?Atestframeworkiswhereyouwillwriteyourtests.Apartfromdoingthis,youwillneedtobefocusedonrunningthetestseasilyandseeingresults.Karmaeasilyrunstestsacrossseveraldifferentbrowsers.Karmaalsohassomeotherfeatures,suchasfilewatching,whichwillbediscussedfurtherindetaillaterinthebook.
www.it-ebooks.info
![Page 65: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/65.jpg)
InstallingKarmaTimetostartusingKarma.Installationsandapplicationsareconstantlychanging.ThefollowingguideisintendedtobebriefinthehopethatyouwillgototheKarmawebsite,http://karma-runner.github.io/,andfindthelatestinstructions.
Themainfocusofthissectionwillbeonthespecificconfigurationusedinthisbookandnotanin-depthinstallationguide.
www.it-ebooks.info
![Page 66: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/66.jpg)
InstallationprerequisitesToinstallKarma,youneedtohaveNode.jsonyourcomputer.Node.jsrunsonGoogle’sV8engineandallowsJavaScripttoberunonseveraloperatingsystems.
Developerscanpublishnodeapplicationsandmodulesusingnpm.Thisallowsdeveloperstoquicklyintegrateapplicationsandmodulesintotheirapplications.
Karmarunsandisinstalledthroughthenpmpackage,andthereforeyouneedNode.jsbeforeyouuseorinstallKarma.ToinstallNode.js,gotohttp://nodejs.org/andfollowtheinstallationinstructions.
AssumingyouhaveNode.jsinstalled,typethefollowingcommandinthecommandprompttoinstallKarma:
$npminstallkarma-g
TheprecedingcommandusesnpmtoinstallKarmagloballyusing-g.WhatthismeansisthatyoucanuseKarmaonthecommandpromptbysimplytypingthefollowing:
$karma-–version
Bydefault,installingKarmawillinstallkarma-chrome-launcherandkarma-jasmineasdependencies.Ensurethatthesemodulesareinstalledgloballyaswell.
www.it-ebooks.info
![Page 67: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/67.jpg)
ConfiguringKarmaKarmacomesequippedwithanautomatedwaytocreateaconfigurationfile.Tousetheautomatedway,typethefollowingcommand:
$karmainit
Hereisasampleoftheoptionschosen:
CustomizingKarma’sconfigurationThefollowinginstructionsdescribethespecificconfigurationrequiredtogetKarmarunningfortheproject.Customizationincludesthetestframework(Jasmine),browser(Chrome)totestwith,andfilestotest.Tocustomizetheconfiguration,openupkarma.confandperformthefollowingsteps:
1. Ensurethattheenabledframeworksaysjasmineusingthefollowingcode:
frameworks:['jasmine'],
2. Configurethetestdirectory.Notethatthefollowingdefinitionneedstoincludethetestsrequiredtorunalongwithanypotentialdependencies.Thedirectorythatwillholdourtestsis/test/unit/:
files:[
'test/unit/**/*.js'
],
3. SetthetestbrowsertoChrome.Itwillthenbeinitializedandwillrunapopupaftereverytest:
www.it-ebooks.info
![Page 68: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/68.jpg)
browsers:['Chrome'],
ConfirmingKarma’sinstallationandconfigurationToconfirmKarma’sinstallationandconfiguration,performthefollowingsteps:
1. RunthefollowingcommandtoconfirmthatKarmastartswithnoerrors:
$karmastart
2. Theoutputshouldbesomethinglikethis:
$INFO[karma]:Karmav0.12.16serverstartedathttp://localhost:9876/
3. Inaddition,theoutputshouldstatethatnotestfileswerefound:
$WARN[watcher]:Pattern"test/unit/**/*.js"doesnotmatchanyfile.
4. Theoutputshoulddothisalongwithafailedtestmessage:
$Chrome35.0.1916(Windows7):Executed0of0ERROR(0.016secs/0
secs)
Thisisexpectedasnotestshavebeencreatedyet.ContinuetothenextstepifKarmaisstartedandyouwillseeyourChromebrowserwiththefollowingoutput:
Commoninstallation/configurationissuesIfJasmineorChromeLauncheraremissing,performthefollowingsteps:
Whenrunningthetest,anerrormightoccursayingmissingJasmineorChromeLauncher.Ifyougetthiserror,typethefollowingcommandtoinstallthemissingdependencies:
$npminstallkarma-jasmine-g
$npminstallkarma-chrome-launcher-g
Retrythetestandconfirmthattheerrorshavebeenresolved.
Thefollowingiswhatyouneedtodotoprovidepermissions(sudo/administrator):
Insomecases,youmightnotbeabletoinstallnpm_modulesgloballyusingthe–gcommand.Thisisgenerallyduetopermissionissuesonyourcomputer.TheresolutionistoinstallKarmadirectlyinyourprojectfolder.Usethesamecommandwithout–gtodothis:
$npminstallkarma
RunKarmausingtherelativepath:
www.it-ebooks.info
![Page 69: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/69.jpg)
$./node_modules/karma/bin/karma--version
NowthatKarmaisinstalledandrunning,it’stimetoputittouse.
www.it-ebooks.info
![Page 70: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/70.jpg)
TestingwithKarmaInthissection,youwillcreateatesttoconfirmKarmaisworkingasexpected.Todothis,performthefollowingsteps:
1. Createthetestdirectory.IntheKarmaconfiguration,testsweredefinedinthefollowingdirectory:
files:[
'test/unit/**/*.js'
],
Goaheadandcreatethetest/unitdirectory.
2. CreateanewfilenamedfirstTest.jsinthetest/unitdirectory.3. Writethefirsttestasfollows:
describe('whentestingkarma',function(){
it('shouldreportasuccessfultest',function(){
expect(true).toBeTruthy();
});
});
4. TheprecedingtestusesJasminefunctionsandhasthefollowingproperties:
describe:Thisprovidesabriefstringdescriptionofthethingsthatwillbetestedit:Thisprovidesabriefstringofthespecificassertionexpect:ThisprovidesawaytoassertvaluestoBeTruthy:Thisisoneofseveralpropertiesonanexpectationthatcanbeusedtomakeassertions
Thistesthasnorealvalueotherthantoconfirmtheoutputofapassingtest.
5. Bam!CheckyourconsolewindowandseethatKarmahasexecutedyourtest.Yourcommandlineshouldsaysomethinglikethis:
$INFO[watcher]:Addedfile"./test/unit/firstTest.js"
ThisoutputmeansthatKarmaautomagicallyrecognizedthatanewfilewasadded.Thenextoutputshouldsaysomethinglikethis:
$Chrome35.0.1916(Windows7):Executed1of1SUCCESS(0.02secs/
0.015secs)
Thismeansyourtesthaspassed!
www.it-ebooks.info
![Page 71: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/71.jpg)
ConfirmingtheKarmainstallationNowtheinitialsetupandconfigurationofKarmaiscomplete.Hereisareviewofthesteps:
InstalledKarmathroughthenpmcommandInitializedadefaultconfigurationthroughthekarmainitcommandConfiguredKarmawithJasmineandatest/unittestdirectoryStartedKarmaandconfirmeditcouldbeopenedwithChromeAddedaJasminetest,firstTest.js,toourtest/unittestdirectoryKarmarecognizedthatfirstTest.jshadbeenaddedtothetestdirectoryKarmaexecutedourfirstTest.jsandreportedouroutput
Withacoupleofsteps,youwereabletoseeKarmarunningandexecutingtestsautomatically.FromaTDDperspective,youcanfocusonmovingtestsfromfailingtopassingwithoutmucheffort.Noneedtorefreshthebrowser;justcheckthecommandoutputwindow.KeepKarmarunningandallyourtestsandfileswillautomaticallybeaddedandrun.
Inthenextsections,youwillseehowtoapplyKarmawithaTDDapproach.Ifyou’reOKwithKarmasofarandwanttomoveontoProtractor,continuetothenextchapter.
www.it-ebooks.info
![Page 72: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/72.jpg)
UsingKarmawithAngularJSHere,youwillwalkthroughaTDDapproachtoanAngularJScomponent.Bytheendofthischapter,youshouldbeableto:
FeelconfidentaboutusingKarmaanditsconfigurationUnderstandthebasiccomponentsofaJasminetestStarttounderstandhowtointegrateaTDDapproachinanAngularJSapplication
www.it-ebooks.info
![Page 73: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/73.jpg)
GettingAngularJSAneasymethodforinstallingAngularJSintoprojectsistouseBower.FeelfreetoinstallAngularJSintoyourprojectinanywayyouprefer.FollowingisabriefdescriptiononhowtoinstallanduseBower.
BowerBowerisapackagemanagerforJavaScriptcomponents.Bowerallowsclient-sideJavaScriptcomponentstobeversionedandautomaticallydownloadedintoyourprojects.Thisallowsyoutoupgradethird-partytoolsandcomponentsandprovideaneasy,standardwaytousetoolssuchasAngularJS,Bootstrap,andmanymore.
Bowerinstallation
Bowerisannpmmodule,justlikeKarma.EnsureyouhaveNode.jsinstalledbeforeyoutrytoinstallBowerusingthefollowingsteps:
1. EnsureyouhaveBowerinstalledusingthiscode:
$npminstallbower-g
2. Initializethebower.jsonconfigurationintherootoftheproject:
$bowerinit
//Thiswillcreateabower.jsonfilewhichcontainsthedependent
packages
//Answerdefaulttoallthequestions.
Theoutputshouldbesomethinglikewhatisshowninthefollowingscreenshot:
Thatisit.NowBowerisinstalledandreadytodownloadJavaScriptpackagesintoyourproject.
InstallingAngularJSUsethefollowingcommandtoinstallAngularJSusingBower:
www.it-ebooks.info
![Page 74: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/74.jpg)
$bowerinstallangular
Typethepreviouscommandinyourcommandpromptforthedirectoryyouwillbeworkingin.Aftertheinstallationiscomplete,lookatyourdirectoryandconfirmthatabower_componetsdirectorywascreated.Insidethis,thereshouldbeafolderforAngularJS:
InstallingAngularmocksAngularmocksallowsyoutotestAngularJScomponents.Theofficialdefinition,whichisfoundathttps://docs.angularjs.org/api/ngMock,isasfollows:
“ThengMockmoduleprovidessupporttoinjectandmockAngularservicesintounittests.Inaddition,ngMockalsoextendsvariouscorengservicessuchthattheycanbeinspectedandcontrolledinasynchronousmannerwithintestcode.”
ToinstallAngularmocks,simplyuseBower:
$bowerinstallangular-mocks
InitializingKarmaAkarma.conffileisrequiredtotellKarmahowitshouldrunfortheapplicationinquestion.Thebestwaytoinitializeitistorunthefollowingcommandinthecommandprompt:
$karmainit
Usethedefaultanswers.Afterkarma.confhasbeencreatedinthecurrentdirectory,openuptheconfiguration.TheoneconfigurationthatneedstochangeisthedefinitionofthefilesforKarmatouse.Usethefollowingdefinitioninthefilessection,whichdefinesthefilesrequiredtorunthetest:
files:[
'bower_components/angular/angular.js',
'bower_components/angular-mocks/angular-mocks.js',
'app/**/*.js',
'spec/**/*.js'
],
Theprecedingconfigurationloadsangular.js,JavaScriptfilesintheappdirectory,andyourtestsinthespecfolder.
EnsurethatKarmacanrunyourconfiguration:
$karmastart
Thecommandoutputshouldstatesomethinglikethis:
www.it-ebooks.info
![Page 75: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/75.jpg)
$Chrome35.0.1916(Windows7):Executed0of0ERROR(0.01secs/0secs)
Thatisit.KarmaisnowrunningforthefirstAngularJSapplication.
www.it-ebooks.info
![Page 76: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/76.jpg)
TestingwithAngularJSandKarmaThepurposeofthisfirsttestusingKarmaistocreateadynamicto-dolist.ThiswalkthroughwillfollowtheTDDstepswediscussedinChapter1,IntroductiontoTest-drivenDevelopment:testfirst,makeitrun,andmakeitbetter.ThiswillallowyoutogainmoreexperienceinusingTDDwithAngularJS.
www.it-ebooks.info
![Page 77: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/77.jpg)
Adevelopmentto-dolistBeforeyoustartthetest,setyourfocusonwhatneedstobedevelopedusingadevelopmentto-dolist.Thiswillallowyoutoorganizeyourthoughts.Hereistheto-dolist:
Maintainalistofitems:
Theexamplelistconsistsoftest,execute,andrefactor
Addanitemtothelist:
Theexamplelistafteryouaddtheitemistest,execute,refactor,andrepeat
Removeanitemfromthelist:
Theexamplelistafteryouaddandremovetheitemistest,execute,andrefactor
www.it-ebooks.info
![Page 78: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/78.jpg)
TestingalistofitemsThefirstdevelopmentitemistoprovideyouwiththeabilitytohavealistofitemsonacontroller.ThenextcoupleofstepswillwalkyouthroughtheTDDprocessofaddingthefirstfeatureusingtheTDDlifecyclethatistestfirst,makeitrun,makeitbetter.
TestfirstDeterminingwheretostartisoftenthehardestpart.Thebestwayistorememberthe3A’s(Assemble,Act,andAssert)andstartwiththebaseJasminetemplateformat.Thecodetodothisisasfollows:
describe('',function(){
beforeEach(function(){
});
it('',function(){
});
});
describe:Thisdefinesthemainfeaturewearetesting.Thestringwillexplainthefeatureinreadabletermsandthenthefunctionwillfollowwiththetest.beforeEach:Thisistheassemblestep.ThefunctiondefinedinbeforeEachwillgetexecutedbeforeeveryassert.Itisbesttoputthetestsetuprequiredbeforeeachtestinthisfunction.it:Thisistheactandassertstep.Intheitsection,youwillperformtheactionbeingtested,followedbysomeassertion.Theactstepdoesn’thavetogointotheitfunction.Dependingonthetest,itmightbemoresuitedinthebeforeEachfunction.
Assemble,Act,andAssert(3A’s)Nowthatthetemplateisthere,wecanstartfillinginthepieces.Wewillagainfollowthe3A’smantra.
Thefollowingarethetwopartsoftheassemblesection.
Inthefirstpart,weinitializethemoduleusingthefollowingcode:
...
beforeEach(function(){
module('todo');
});
...
ThiscodewillusetheAngularmocksJavaScriptlibrarytoinitializetheAngularJSmodulebeingtested.Wehaven’tdefinedthetodomodule,butwewilldothisafterwegetafailingtest.
ThesecondparttalksaboutthescopeofTodoController.TheTodoControllerscopewillcontainthelistofitemsonitsscopevariable.ItisrequiredthatthetesthasaccesstothescopeofTodoController.Angularmockswillbeusedtogetthis.Addthefollowing
www.it-ebooks.info
![Page 79: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/79.jpg)
codetobeforeEachtogetthecontroller’sscope:
//scope–holditemsonthecontroller
varscope={};
beforeEach(function(){
//...
//inject–accessangularcontrollerinject(function($controller){
//$controller–initializecontrollerwithtestscope
$controller('TodoController',{$scope:scope});
});
//...
});
Thefollowingisabriefexplanationofeachofthecodeelements:
scope:Thisvariableisusedtoholdandtestthelistitemsonthecontroller.inject:TheAngularmocksfunctionisusedtoaccessAngularJS’s$controller.ThisessentiallyallowsyoutogetaccessandinjectdependenciesintoAngularJSobjects.$controller:ThisinitializesthescopeofTodoController.Thetest’sscopevariablewillnowcontainthecontroller’sscope.
Inthecaseof“act”,thereisnomethodtoacton.Thescopeobjecthasalreadybeenretrievedaspartoftheassemblestep.
Inassert,therearetwopartsagain:
ThefirstassertionistoensuretheTodoControllerscopehasalistvariabledefinedwiththreeitems.Thelistvariablewillbeusedtoholdthelistofalltheitems:
it('shoulddefinealistobject',function(){
expect(scope.list).toBeDefined();
});
Thesecond,third,andfourthassertionswillbeusedtoconfirmwhetherthedatainthelistisinthecorrectorder,thatis,firstistest,secondisexecute,andthirdisrefactor:
//Secondtest
it('shoulddefinealistobject',function(){
expect(scope.list[0]).toEqual('test');
});
//Thirdtest
it('shoulddefinealistobject',function(){
expect(scope.list[1]).toEqual('execute');
});
//Fourthtest
it('shoulddefinealistobject',function(){
expect(scope.list[2]).toEqual('refactor');
});
MakeitrunThenextstepintheTDDlifecycleistomaketheapplicationrunandfixthecodesothat
www.it-ebooks.info
![Page 80: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/80.jpg)
thetestspass.Remember,thinkaboutthesmallestcomponentsthatcanbeaddedtomakethetestpassbyproceedingwiththefollowingsteps:
1. RunKarmabytypingthefollowingcommand:
$karmastart
2. Ifyouencounter[$injector:moduler]Failedtoinstantiatemoduletododuetoerror,thenitcanbeduetothefollowing:
Theprecedingerrormessageissayingthatthetodomodulehasn’tbeendefined.Sincetheerrormessageistellingyouwhatisrequired,thisistheperfectplacetostart.Createanewfileintheappdirectorynamedtodo.Theworkingdirectoryshouldnowlooksomethinglikethis:
Addthetodomoduletothebeginningofyournewfileasfollows:
angular.module('todo',[]);
ReviewtheconsolewindowwhereKarmaisrunning.Youshouldnowseeanewerror.
3. Error:The[ng:areq]argumentTodoControllerisnotafunction,gotundefined:
Thiserrormessageisdescribingexactlywhatneedstobedone.Thereisnoneedtodeciphererrormessagesorstacktraces.Simplyupdatethetodo.jsfilesoitcontainsanAngularJScontrollerasfollows:
angular.module('todo',[])
.controller('TodoController',[])
Inthepreviouscode,wedidn’ttryanddefinethelogicrequired;weonlyaddedthesmallestcomponenttomeettheerrormessage.Reviewtheconsolewindowforthenexterror.
4. Error:Theexpectedundefinedtobedefinedasfollows:
Thenewerrormessageisagainclear.Wecanalsoseethatthecodehasnowpasseduptothepointofourassertionatthefollowingpoint:
expect(scope.list).toBeDefined();
Asthereisnolistonthescope,youneedtoaddone.Updatetheapp/todo.jsfileasfollows:
www.it-ebooks.info
![Page 81: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/81.jpg)
.controller('TodoController',['$scope',function($scope){
$scope.list=[];
}])
Reviewtheconsolewindow.
5. Youshouldnowseeoneofthefourtestspass!ThismeansyouhavesuccessfullyusedTDDandKarmatogetyourfirsttesttopass.Nowyouneedtofixtheotherthree.ThenexterrorisExpectedundefinedtoequal'test':
Theerroroutputagaindescribesexactlywhatneedstohappen.Youjustneedtoinitializethearraywiththeelementstest,execute,andrun.Gotoapp/todo.jsandaddthedatatothearrayinitialization:
angular.module('todo',[])
.controller('TodoController',['$scope',function($scope){
$scope.list=['test','execute','refactor'];
}]);
ReviewtheoutputintheKarmawindow.
6. Excellent!Theoutputisingreenandstatesthatallthetestshavepassed.
Theresultmoduleandcontrollercodefromthisstepisasfollows:
//Amodulefortheapplication
angular.module('todo',[])
//Acontrollertomanagetheto-doitems.controller('TodoController',
['$scope',function($scope){
//theinitializationofitemsonthecontrollerscope
$scope.list=['test','execute','refactor'];
}]);
Nowthatthe“makeitrun”stepiscomplete,youcanmoveontothenextstepandmakeitbetter.
MakeitbetterUntilthispoint,therewasnothingrequiredtodirectlyrefactororthathadbeenidentifiedinthedevelopmentto-dolist.Areviewofthedevelopmentto-dolistshowsthatanitemcanbecrossedout:
Viewalistofto-dolistitems:
Theexamplelistconsistsoftest,execute,andrefactor
Addanitemtoato-do-list:
Theexamplelistafteryouaddtheitemwillconsistoftest,execute,refactor,andrepeat
Removeanitemfromato-do-list:
Theexamplelistafteryouaddandthenremovetheitemwillconsistoftest,execute,andrefactor
www.it-ebooks.info
![Page 82: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/82.jpg)
Nextupistherequirementtoaddanewitemtothelist.TheTDDrhythmwillbefollowedagain:testfirst,makeitrun,andmakeitbetter.
www.it-ebooks.info
![Page 83: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/83.jpg)
AddingafunctiontothecontrollerThenexttaskistogivethecontrollertheabilitytoadditemstothescopelist.Thiswillrequiretheadditionofamethodtothescope.Thiswalk-throughwillfollowthesameTDDstepsasdonepreviously.
TestfirstInsteadofcreatinganewfileandduplicatingsomeoftheassemblesteps,thefollowingtestwillbeinsertedunderthelastitmethod.Thereasonisbecausethesamemoduleandcontrollerwillbeused:
describe('whenusingato-dolist',function(){
varscope=null;
beforeEach(function(){
//...
});
//...
describe('',function(){
beforeEach(function(){
});
it('',function(){
});
});
});
Assemble,Act,andAssert(3A’s)Nowthatthetemplateisthere,wecanstartfillinginthegapsusingthe3A’smantra:
1. Assemble:Thereisnoinitializationorsetuprequired,asthemoduleandcontrollerscopewillbeinherited.
2. Act:Here,youneedtoactontheaddmethodwithanewitem.Weplacetheactfunctionintothebeforeeachfunction.Thisallowsustorepeatthesamestepif/whenmoretestsareadded:
beforeEach(function(){
scope.add('repeat');
});
3. Assert:Here,anitemshouldbeaddedtothelist,andthenyouneedtoconfirmthatthelastiteminthearrayisasexpected:
it('shouldadditemtolastiteminlist',function(){
varlastIndexOfList=scope.list.length-1;
expect(scope.list[lastIndexOfList]).toEqual('repeat');
});
www.it-ebooks.info
![Page 84: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/84.jpg)
MakeitrunThenextstepintheTDDlifecycleistomakeitrun.Remember,thinkaboutthesmallestcomponentsthatcanbeaddedtomakethetestpass,asfollows:
1. EnsureKarmaisrunninginyourconsolebytypinginthefollowingcommand:
$karmastart
2. ThefirsterrorwillstateTypeError:undefinedisnotafunction:
Theerrorreferstothefollowinglineofcode:
scope.add('repeat');
Theerroristellingyouthattheaddmethodhasn’tbeendefined.Theaddfunctionwillneedtobeaddedtotheapp/todo.jscode.Thecontrollerhasalreadybeendefined,sotheaddfunctionneedstobeplacedonthecontroller’sscope:
angular.module('to-do',[])
.controller('TodoController',['$scope',function($scope){
//...
$scope.add=function(){};
}]);
Noticehowtheaddfunctiondoesn’tcontainanylogic.Thesmallestcomponenthasbeenaddedtogetthetesttosatisfytheerrormessage.Reviewtheconsolewindowforthenexterror.
3. Error:Expected'refactor'toequal'repeat':
Havealookatthefollowingexpectation:
it('shouldadditemtolastiteminlist',function(){
varlastIndexOfList=scope.list.length-1;
expect(scope.list[lastIndexOfList]).toEqual('repeat');
});
Thefailedassertioninstep2istellingusthatbasedontheprecedingexpectation,theexpectedresultofrepeatisnotwhatthelastiteminthelisthas.Thesmallestpossiblethingthatcanbeaddedtomakethisassertionpassistopushrepeattotheendofthelistintheaddfunction.Hereishowtodothis:
//...
$scope.add=function(){
$scope.list.push('repeat');
};
//...
Reviewtheconsoletoseewhatthenextoutputsays.
4. Success!Allfivetestshavenowpassed.
Theresultingcodeaddedtogettheteststopassisasfollows:
www.it-ebooks.info
![Page 85: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/85.jpg)
//Amodulefortheapplication
angular.module('todo',[])
//Acontrollertomanagetheto-doitems
.controller('TodoController',['$scope',function($scope){
//theinitializationofitemsonthecontrollerscope
$scope.list=['test','execute','refactor'];
$scope.add=function(){
$scope.list.push('repeat');
};
}]);
MakeitbetterThemainthingthatweneedtorefactoristhattheaddfunctionstillhasn’tbeenfullyimplemented.Itcontainsahardcodedvalue,andtheminutewesendinadifferentitemintotheaddfunction,thetestwillfail.
KeepKarmarunningsowecankeeppassingthetestsaschangesaremade.Themainissuewiththecurrentaddmethodisasfollows:
Itdoesn’tacceptanyparameterItdoesn’tpushaparameterontothelistbutusesahardcodedvalue
Theresultantaddfunctionshouldnowlookasfollows:
$scope.add=function(item){
$scope.list.push(item);
};
ConfirmthattheKarmaoutputstilldisplayssuccess:
$Chrome35.0.1916(Windows7):Executed5of5SUCCESS(0.165secs/0.153
secs)
www.it-ebooks.info
![Page 86: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/86.jpg)
Self-testquestionsSelf-testquestionswillhelpyoufurthertestyourknowledgeofusingTDDwithAngularJSandKarma.
Q1.HowdoyouuseKarmatocreateaconfigurationfile?
1. karmaconfig2. karmainit3. karma–configkarma.conf.js
Q2.TheJasminetestmethodnamedbeforegetsexecutedbeforeeverytest.
1. True2. False
Q3.BowerisusedtoinstallKarma.
1. True2. False
Q4.The3A’sstandforwhichoneofthese?
1. Agroupofsuperheroes2. Assemble,Act,andAssert3. Accept,approve,andact
www.it-ebooks.info
![Page 87: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/87.jpg)
SummaryInthischapter,wereviewedJavaScripttestingframeworksandtoolsanddiscussedhowVojtechJínacreatedKarma.Wesawhowtoinstall,configure,andrunKarma.Finally,youhavewalkedthroughanexampleofusingKarmawithTDD.Inthenextchapter,youwilllearnaboutend-to-endtestingwithProtractor.
www.it-ebooks.info
![Page 88: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/88.jpg)
Chapter3.End-to-endTestingwithProtractorUnittestingisonlyoneaspectoftesting.Inthischapter,wewilllookatend-to-endtestingapplications,throughalllayersofanapplication.YouwillbeintroducedtoProtractor,theend-to-endtestingtoolfromtheAngularJSteam.Wewilllookintowhyitwascreatedandtheproblemsitsolves.Finally,wewillseehowtoinstall,configure,anduseProtractorwithTDD.
www.it-ebooks.info
![Page 89: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/89.jpg)
AnoverviewofProtractorProtractorisanend-to-endtestingtoolthatrunsusingNode.jsandisavailableasannpmpackage.BeforetalkingaboutProtractorspecifically,youneedtounderstandwhatend-to-endtestingis.End-to-endtestingistestinganapplicationagainstalltheinterconnectedmovingpartsandlayersofanapplication.Thisdiffersfromunittests,wherethefocusisonindividualcomponentssuchascontrollers,services,directives,andsoon.Withend-to-endtesting,thefocusisonhowtheapplicationoramodule,asawhole,works,suchasconfirmingtheclickofabuttondoesx,y,andz.
Protractorallowstheend-to-endtestingofanapplication.Thisincludestheabilitytosimulatetheclickofabuttonandinteractwithanapplicationinthesamewayauserwould.Itthenallowsexpectationstobesetbasedonwhattheuserwouldexpect.Toputthisintocontext,thinkaboutthefollowinguserspecification:
AssumingIinputabcintothesearchbox,thefollowingshouldoccur:
ThesearchbuttonishitAtleastoneresultshouldbereceived
Theprecedingspecificationdescribesabasicsearchfeature.Nothingintheprecedingspecificationdescribesacontroller,directive,orservice;itonlydescribestheexpectedapplicationbehavior.Ifauserweretotestthespecification,theymayperformthefollowingsteps:
1. Pointthebrowsertothewebsite2. Selecttheinputfield3. Typeabcintheinputfield4. ClickontheSearchbutton5. Confirmthatthesearchoutputdisplaysatleastoneresult.
ThestructureandsyntaxofProtractormirrorsthatofJasmineandthetestsyouwroteinChapter2,TheKarmaWay.YoucanthinkofProtractorasawrapperaroundJasmine,withaddedfeaturestosupportend-to-endtesting.Towriteanend-to-endtestwithProtractor,wecanfollowthesamestepsasdescribedintheprecedingsteps,butwithcode.Herearethestepsincode:
1. Pointthebrowsertothewebsite:
browser.get('/');
2. Selecttheinputfield:
varinputField=element.all(by.css('input'));
3. Typeabcintheinputfield:
inputField.setText('abc');
4. ClickontheSearchbutton:
www.it-ebooks.info
![Page 90: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/90.jpg)
inputField.click();
5. Findthesearchresultdetailsonthepage:
varsearchResults=element.all(by.css('#searchResult');
6. Finally,theassertionneedstobemadethatatleastoneormoresearchresultsareavailableonthescreen:
expect(searchResults).count()>=1);
Asacompletetest,thecodewillbeasfollows:
describe('GivenIinput'abc'intothesearchbox',function(){
//1–Pointbrowsertowebsite
browser.get('/');
//2–Selectinputfield
varinputField=element.all(by.css('input'));
//3-Typeabcintoinputfield
inputField.setText('abc');
//4-Pushsearchbutton
inputField.click();
it('shoulddisplaysearchresults',function(){
//5-Findthesearchresultdetails
varsearchResults=element.all(by.css('#searchResult');
//6-Assert
expect(searchResults).count()>=1);
});
});
That’sit!WhenProtractorruns,itwillopenabrowser,gotothewebsite,followtheinstructions,andfinallychecktheexpectations.Thetrickwithend-to-endtestingishavingaclearvisiononwhattheuserspecificationis,andthentranslatingthatspecificationtocode.
Thepreviousexampleisahigh-levelviewofwhatwillbedescribedthroughoutthischapter.NowthatyouhavebeenintroducedtoProtractor,therestofthechapterwillshowhowProtractorworksbehindthescenes,howtoinstallit,andfinally,walkyouthroughacompleteexampleusingTDD.
www.it-ebooks.info
![Page 91: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/91.jpg)
OriginsofProtractorProtractorisnotthefirstend-to-endtestingtoolthattheAngularJSteambuilt.ThefirsttoolwascalledScenarioRunner.InordertounderstandwhyProtractorwasbuilt,weneedtofirstlookatitspredecessor:ScenarioRunner.
www.it-ebooks.info
![Page 92: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/92.jpg)
EndoflifeScenarioRunnerisinmaintenancemodeandhasreacheditsendoflife.IthasbeendeprecatedinplaceofProtractor.Inthissection,wewilllookatwhatScenarioRunnerwasandwhatgapsthetoolhad.
www.it-ebooks.info
![Page 93: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/93.jpg)
ThebirthofProtractorJulieRalphistheprimarycontributortoProtractor.AccordingtoJulieRalph,themotivationforProtractorwasbasedonthefollowingexperiencewithAngularScenarioRunner,onanotherprojectwithinGoogle(http://javascriptjabber.com/106-jsj-protractor-with-julie-ralph/):
WetriedusingtheScenarioRunner.Andwefoundthatitreallyjustcouldn’tdothethingsthatweneededtotest.Weneededtotestthingslikeloggingin.Andyourloginpageisn’tanAngularpage.AndtheScenarioRunnercouldn’tdealwiththat.Anditcouldn’tdealwiththingslikepopupsandmultiplewindows,navigatingthebrowserhistory,stufflikethat.
BasedonherexperiencewithScenarioRunner,JulieRalphdecidedtocreateProtractortofillthegaps.
ProtractortakesadvantageofthematurityoftheSeleniumproject,andwrapsupitsmethodssothatitcanbeeasilyusedforAngularJSprojects.Remember,Protractorisabouttestingthroughtheeyesoftheuser.Itwasdesignedtotestalllayersofanapplication:WebUI,backendservices,persistencelayer,andsoon.
www.it-ebooks.info
![Page 94: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/94.jpg)
LifewithoutProtractorUnittestingisnottheonlytestingthatneedstobewrittenandmaintained.Unittestsfocusonsmallindividualcomponentsofanapplication.Bytestingsmallcomponents,theconfidenceinthecodeandlogicgrows.Unittestsdon’tfocusonhowthecompletesystemworkswheninterconnected.
End-to-endtestingwithProtractorallowsthedevelopertofocusonthecompletebehaviorofafeatureormodule.Goingbacktothesearchexample,thetestshouldonlypassifthewholeuserspecificationpasses;enterdataintothesearchbox,clickontheSearchbutton,andseetheresults.
Protractorisnottheonlyend-to-endtestingframeworkoutthere,butitisthebestchoiceforAngularJSapplications.HereareafewreasonswhyyoushouldchooseProtractor:
ItisdocumentedthroughouttheAngularJStutorialsandexamples.ItcanbewrittenusingmultipleJavaScripttestingframeworks,includingJasmineandMocha.ItprovidesconveniencemethodsforAngularJScomponents,includingwaitingforapagetoload,expectationsonpromises,andsoon.ItwrapsSeleniummethodsthatautomaticallywaitforpromisestobefulfilled.ItissupportedbySaaS(SoftwareasaService)providerssuchasSauceLabs,whichisavailableathttps://saucelabs.com/.ItissupportedandmaintainedbythesamecompanythatmaintainsAngularJSandGoogle.
www.it-ebooks.info
![Page 95: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/95.jpg)
ProtractorinstallationIt’stimetostartgettingourhandsdirty,andinstallandconfigureProtractor.Installationsandapplicationsareconstantlychanging.Themainfocuswillbeonthespecificconfigurationusedinthisbook,andnotanin-depthinstallationguide.Thereareseveralvaryingdifferentconfigurations,sopleasereviewtheProtractorsiteforadditionaldetails.Pleasevisitthefollowingwebsitetofindthelatestinstallationandconfigurationguide:
http://angular.github.io/protractor/
Forthisbook,wewillonlybeusingthechromeOnlyconfiguration.ThechromeOnlyconfigurationdoesn’trequireseveralmovingparts,andallowsyoutogetuptospeedquickly.Asyourtestsgrowandyouarerequiredtosupportmultiplebrowsers,runningtestswithaSeleniumserverorusingsomethinglikeSauceLabsshouldbereviewed.AppendixA,IntegratingSeleniumServerwithProtractordescribeshowtosetupastandaloneSeleniumserver.
www.it-ebooks.info
![Page 96: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/96.jpg)
InstallationprerequisitesProtractorhasthefollowingprerequisites:
Node.js:ProtractorisaNode.jsmoduleavailableusingnpm.ThebestwaytoinstallNode.jsistofollowtheinstructionsontheofficialsiteathttp://nodejs.org/download/.Chrome:ThisisawebbrowserbuiltbyGoogle.Itwillbeusedtorunend-to-endtestsinProtractorwithouttheneedforaSeleniumserver.Followtheinstallationinstructionsontheofficialsiteathttp://www.google.com/chrome/browser/.SeleniumWebDriverforChrome:Thisisatoolthatallowsyoutointeractwithwebapplications.SeleniumWebDriverisprovidedwiththeProtractornpmmodule.WewillwalkthroughtheinstructionsasweinstallProtractor.
www.it-ebooks.info
![Page 97: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/97.jpg)
InstallingProtractorHerearethestepstoinstallProtractor:
1. OnceNode.jsisinstalledandavailableinthecommandprompt,typethefollowingcommandtoinstallProtractorinthecurrentdirectory:
$npminstallprotractor
ThepreviouscommandusesNode’snpmcommandtoinstallProtractorinthecurrentlocaldirectory.
2. Confirmthecurrentdirectorystructure:
TouseProtractorinthecommandprompt,usetherelativepathtotheProtractorbindirectory.
3. TestthattheProtractorversioncanbedeterminedasfollows:
$./node_modules/protractor/bin/protractor--version
InstallingWebDriverforChromeHerearethestepstoinstallWebDriverforChrome:
1. ToinstallSeleniumWebDriverforChrome,gotothewebdriver-managerexecutableintheProtractorbindirectorythatcanbefoundat./node_modules/protractor/bin/andtypethefollowing:
$./node_modules/protractor/bin/webdriver-managerupdate
2. Confirmthedirectorystructure.
ThepreviouscommandwillcreateaSeleniumdirectorycontainingtherequiredChromedriverusedintheproject.Thenode_modulesdirectoryshouldnowlooklikethefollowing:
www.it-ebooks.info
![Page 98: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/98.jpg)
Theinstallationisnowcomplete.BothProtractorandSeleniumWebDriverforChromehavebeeninstalled.Wecannowmoveontotheconfiguration.
www.it-ebooks.info
![Page 99: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/99.jpg)
CustomizingconfigurationInthissection,wewillbeconfiguringProtractorusingthefollowingsteps:
1. Startwithastandardtemplateconfiguration.
Fortunately,theProtractorinstallationcomeswithsomebaseconfigurationsinitsinstallationdirectory.Goingbacktothelocalnode_modulesdirectory,youshouldfindtheexampleChromeconfigurationintheexamplefolder:
Theexampledirectorycontainsexampleconfigurations.TheonethatwewilluseiscalledchromeOnlyConf.js.ThechromeOnlyconfigurationwillallowustorunend-to-endtestsinChromewithouttheneedforaSeleniumserver.Asdiscussedearlier,runningaSeleniumserverisanotheroptionthatwillnotbediscussedinthisbook.
2. Reviewtheexampleconfigurationfile:
ThechromeOnlyparametershouldbesettotrue,asfollows:
exports.config={
//...
chromeOnly:true,
//...
};
ThechromeDriverparameterwillhavetobemodifiedtopointtothedriverweinstalled,asfollows:
exports.config={
//...
chromeDriver:'../selenium/chromedriver',
//...
};
Thecapabilitiesparametershouldonlyspecifythenameofthebrowser:
exports.config={
//...
capabilities:{
'browserName':'chrome'
},
//...
www.it-ebooks.info
![Page 100: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/100.jpg)
};
Thefinalimportantconfigurationisthesourcefiledeclaration:
exports.config={
//...
specs:['example_spec.js'],
//...
};
Excellent!NowwehaveProtractorinstalledandconfigured.
ConfirminginstallationandconfigurationToconfirminstallation,Protractorrequiresatleastonefiledefinedinthespecsconfigurationsection.Beforeaddingarealtestandcomplicatingthings,createanemptyfileintherootdirectorycalledconfirmConfigTest.js.Then,addthetesttothespecssectionsoitlookslikethis:
specs:['confirmConfigTest.js'],
ToconfirmthatProtractorhasbeeninstalled,runProtractorbygoingtotherootofyourprojectdirectoryandtype:
$./node_modules/protractor/bin/protractorchromeOnlyConf.js
Ifeverythingwassetupcorrectlyandinstalled,youshouldseesomethingsimilartothisinyourcommandprompt:
Finishedin0.0002seconds
0tests,0assertions,0failures
Commoninstallation/configurationissuesThefollowingaresomecommonissuesthatyoumightcomeacrosswhileinstallingWebDriverforChrome:
Seleniumnotinstalledcorrectly:IfthetestshaveerrorsrelatedtotheSeleniumWebDriverlocation,youneedtoensurethatyoufollowedthestepstoupdateWebDriver.TheupdatestepdownloadstheWebDrivercomponentsintothelocalProtractorinstallationfolder.UntilWebDriverhasbeenupdated,youwon’tbeabletoreferenceitintheProtractorconfiguration.AneasywaytoconfirmtheupdateistolookintheProtractordirectoryandensurethataSeleniumfolderexists.Unabletofindtests:WhennotestsareexecutedbyProtractor,itcanbefrustrating.Thebestplacetostartisintheconfigurationfile.Makesuretherelativepathandanyfilenamesorextensionsarecorrect.
Foramorecompletelist,pleaserefertotheofficialProtractorsiteathttp://angular.github.io/protractor/.
www.it-ebooks.info
![Page 101: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/101.jpg)
HelloProtractorWiththeProtractorinstallationandconfigurationcomplete,youcanlookatwritingarealtest.ThissectionwillwalkyouthroughusingTDDwithProtractor.Attheendofthischapter,youshouldbeableto:
FeelconfidentinusingandconfiguringProtractorUnderstandthebasiccomponentsofaProtractortestStarttounderstandhowtointegrateaTDDapproachtoend-to-endtesting
www.it-ebooks.info
![Page 102: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/102.jpg)
TDDend-to-endTest-drivendevelopmentisnotasilverbullet.Itisafoundationofprinciplesandtechniquesusedtoimproveefficiency,quality,andmuchmore.KnowinghowtoapplyTDDisthefirststep,butknowingwhentoapplyitisjustasimportant.
WhenapplyingTDD,youarecouplingteststoyourlogicandcode.Asadeveloper,youhavetomakedecisionsonwhenthatcouplingmakessenseandwillbeadvantageoustoyourproject.Asyouworkthroughtheexamples,beawarethattheyshowyouhowtoapplyTDDtechniques.Asyouusethesepracticesinyourownprojects,youwillneedtodeterminethedepthandcouplingoftheteststhatyourprojectandspecificationsrequire.
Thepre-setupThecodeinthistestwillleveragetheunittestedcodefromChapter2,TheKarmaWay.Youwillneedtocopythecodetoanewdirectory.
Asareminder,theapplicationwasato-doapplicationthataddsanddeletesitemsfromalist.Ithasasinglecontroller,TodoController,thathasalistofitemsandanaddmethod.Theapplicationdidn’thaveanyHTMLorusercomponents.WewilluseaTDDapproachtoaddtheUIelements.Thecurrentcodedirectoryshouldbestructuredasfollows:
www.it-ebooks.info
![Page 103: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/103.jpg)
ThesetupThesetupwillmirrortheinstallationandconfigurationstepsfromearlier:
1. InstallProtractor.2. UpdateSeleniumWebDriver.3. ConfigureProtractorbasedontheexampleconfiguration.
FollowtheProtractorinstallationandconfigurationstepsyoulearnedintheprevioussectioninanewprojectdirectory.TheonlydifferenceisthattheProtractortestsshouldbeplacedinaspec/e2edirectory.Thiswillallowyoutoeasilyidentifythetestsinyourprojectstructure.Aftercreatingaspec/e2edirectoryupdate,theProtractorconfigurationspecsectionshouldbeasfollows:
exports.config={
//...
specs:['spec/e2e/**/*.js'],
//...
};
AfterconfirmingthatProtractorhasbeeninstalledandconfiguredproperly,youcanstartthefirsttest.
www.it-ebooks.info
![Page 104: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/104.jpg)
TestfirstNowthatProtractorhasbeensetup,thetestingcanbegin.End-to-endtestsareslowandtouchmultiplelayersoftheapplication.Theyalsorequirethefullapplicationtobesetupandrunninginordertotest.Thereareseveraltechniquesthatwecanleveragetomockalocalenvironment.MockingdataandAPIswillbediscussedinChapter7,GiveMeSomeData.Thisfirstend-to-endtestwillonlyhaveaWebUIlayer.Noadditionalmockingwillberequired.
Asmentionedearlier,Protractorrequiresarunningapplication.Thismeansthewebsiteneedstobeavailableforyoutopointyourbrowsertoit.AsimpleapproachtoservingstaticHTTPcontentistousethehttp-servernpmmodule.Thehttp-servermoduleisperfectforalocaldevelopmentenvironment,butprobablynotsuitedforthefinalapplicationinfrastructure.YourproductionwebsitemightbedevelopedinsomethinglikeExpress,IIS,orApache.
InstallingthetestwebserverToinstallourtestwebserver,wewillusethehttp-servernodemodule.Theadvantageofawebserversuchashttp-serveristhatitrequiresverylittleconfigurationandcanjuststartandrunthewebsite.Herearethestepstoinstallthewebserver:
1. Typethefollowingcommandinthecommandline:
$npminstallhttp-server
2. Nowcreateastubindex.htmlpageattherootoftheprojectwiththebasicHTMLcomponents:
<!DOCTYPEhtml>
<html>
<head>
<title></title>
</head>
<body>
</body>
</html>
3. NowruntheHTTPserverandensurethepageisloaded:
./node_modules/http-server/bin/http-server-p8080
4. Gotohttp://localhost:8080.Youshouldseeablankpagegetloaded,withnoerrorsinthecommandoronthewebpage.Ifyouseeerrors,ensurethatthedirectoryhastherequiredindex.htmlfile.Nowthatyouhaveaworkingwebsite,itistimetoconfigureProtractortouseit.
ConfiguringProtractorProtractorcanbeconfiguredwithabaseURLforanapplication.Byspecifyingabase
www.it-ebooks.info
![Page 105: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/105.jpg)
URL,testswilllookcleanerandcanbeeasilyconfiguredtousedifferentURLsforthesameapplication.Imagineadev,qa,andproductionURLthatusethesametests,buthavedifferentURLsthatneedtobetested.
Aswewillberunningthislocally,wewillneedtousehttp://localhost:8000asourbaseURL.UpdatetheProtractorconfigurationfileasfollows:
baseUrl:'http://localhost:8080/'
GettingdowntobusinessEnd-to-endtestingisdifferentthanunittesting.Testswillinteractwithdifferentlayersofanapplicationthroughoutasinglescenario.YoumayhaveanotherteamdesigningtheHTMLelements,CSS,andsoon.ThedevelopmentteamwillthenhavetointegratetheUIHTMLintothepage.TheTDDapproachwillallowyoutocreatetestsforseparatecomponentsindependently.Theideaisyouwanttobeabletestthefeaturesoftheapplicationthatmakesensetotest.Testingeverythingblindlycanbeawasteoftimeandarefactoringnightmare.
Inthiscase,westartwithablankcanvasofapageandwanttotestthebehavioroftheprimarycomponents.WewillfollowtheTDDlifecycle(test,execute,refactor).Intheupcomingsections,wewillcoverthefollowingsteps:
1. Reviewtheuserspecification.2. Writedownthemaintasksthatneedtobedeveloped.3. Writethetestforwhatwillbedeveloped.
Specification
Thepurposeofthisfirsttestistomanageadynamicto-dolist.
Thedevelopmentto-dolist
Wewillneedadevelopmentto-dolisttosetourfocusandorganizeourdevelopmenttasks.Performthefollowingsteps:
1. Viewtheto-dolistitems
Examplelist:test,execute,refactor
2. Addanitemtotheto-dolist
Examplelist:test,execute,refactor,repeat
3. Removeanitemfromtheto-dolist
Examplelist:test,execute,refactor
Ifyourecall,inourpreviousexample,wesetupthebackendmodulefortheto-dolistapplication.Inthiscase,wewillfocusonmanagingthelistfromtheuser’sperspective.
Testfirst
www.it-ebooks.info
![Page 106: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/106.jpg)
JustaswediscussedwiththeKarmatest,startwiththe3A’s(Assemble,Act,Assert).ProtractortestsarewritteninthesameJasminestyleandsetup,soyoudon’thavetolearnanynewsyntax.StartwiththebasicJasminetemplateformat:
describe('',function(){
beforeEach(function(){
});
it('',function(){
});
});
describe:Thisdefinesthemainfeaturewetest.Thefirstparameterisastringtoexplainthefeatureandthesecondparameteristhefunctionthatcontainstheteststeps.beforeEach:ThisisthetestsetupandAssemblesection.ThefunctiondefinedinbeforeEachwillbeexecutedbeforeeveryAssert.Thisiswhereweperformanysetupmocks,spies,andothercomponentsneededtotest.it:ThisistheActandAssertsection.Inthissection,youwillperformtheactualactionbeingtested,followedbyanassertion.
Assemble,Act,Assert(3A’s)
Followthe3A’smantra:
Assemble:Asthisisanend-to-endtest,wewillinitializebydirectingthetesttogotothepageundertest.Inthiscase,thepageis/.ThisisbecausewesetthebaseURLtobehttp://localhost:8080/intheconfigurationfile.Sothecodewilllooklikethefollowing:
beforeEach(function(){
browser.get('/');
});
Act:Inthefirsttest,toviewalistofto-doitems,thereisnobuttontobeclickedoractiontobedoneinordertogetthelist.Weshouldjustbrowsetothepageandseethelistofto-doitems.Assert:Thisisourfirstfailingtest,whichwewillwriteusingProtractor.Thetestneedstodeterminewhetherthelistofto-doitems,thatistest,execute,andrefactor,isavailableonthepage.InAngularJS,thiswillbedoneusingng-repeat,meaningeachiteminalistwillberepeatedwithsomespecialHTMLtodisplayanindividualitem.
AsProtractoristestingtheactualUI,youwillneedtohavetheabilitytoselectHTMLelements.OneofthebenefitsofProtractoristhatitwrapsupAngularJScomponentssothattheycanbeeasilytested.
Intheprecedingtest,wewillusetheelementselectorwiththeby.repeaterselection.Inourcase,thefirstassertionwilllooklikethis:
it('',function(){
vartodoListItems=element.all(by.repeater('iteminlist'));
expect(todoListItems.count()).toBe(3);
www.it-ebooks.info
![Page 107: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/107.jpg)
});
Thefirstlinewillselecttheto-dolistitemsavailableonthepage.ThesecondwillAssertthattheitemcountis3.Whenrunningthetest,ensurethewebserverisstillrunningusingthefollowingcommand:
$./node_modules/http-server/bin/http-server-p8080
Thecompletedtestlooksasfollows:
describe('',function(){
//ASSEMBLE
beforeEach(function(){
//ACT
browser.get('/');
});
it('',function(){
vartodoListItems=element.all(by.repeater('iteminlist'));
//ASSERT
expect(todoListItems.count()).toBe(3);
});
});
Runningthetest
Thestepstorunatestareasfollows:
1. RuntheProtractortestinadifferentcommandprompt,usingthefollowingcommand:
$protractorchromeOnlyConf.js
2. TheoutputshouldsaythatAngularJScouldnotbefound:
$Error:Angularcouldnotbefoundonthepagehttp://localhost:8080/
:retrieslookingforangularexceeded
Thiserrorindicatesthattheassertionsfailed.
3. Whenrunningthetest,youshouldseeaChromepop-upwiththepage.Youshouldalsoseethattheoutputfromthewebserversayssomethinglikethefollowing:
GET/”“Mozilla/5.0(WindowsNT6.1;WOW64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/36.0.1985.125Safari/537.36
Excellent!Nowyou’vegotafailingProtractortest,itistimetomakeitrun.
Makeitrun
ThenextstepintheTDDlifecycleistoexecuteandfixthecodesothatthetestspass.Asyouwalkthroughthetest,remembertousethesmallestcomponentsthatcanbeaddedtomakethetestpass:
1. Asthefirsterrorsays,Angularcan'tbefound.AddAngularJStothepagejustbeforetheclosingtagforthebodyasfollows:
//...
www.it-ebooks.info
![Page 108: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/108.jpg)
<scriptsrc="bower_components/angular/angular.js"></script>
</body>
//...
2. Rerunthetestusingthefollowingcommand:
$protractorchromeOnlyConf.js
Theoutputshouldnowdisplaythefollowing:
$Error:Angularcouldnotbefoundonthepagehttp://localhost:8080/
:angularneverprovidedresumeBootstrap
3. Sinceyouhaven’tspecifiedtheapplicationoraddedthetodo.jspage,let’saddthesecomponentstoitaftertheAngularJSscript:
//...
<bodyng-app="todo">
<scriptsrc="bower_components/angular/angular.js"></script>
<scriptsrc="app/todo.js"></script>
//...
4. Rerunthetestusingthefollowingcommand:
$protractorchromeOnlyConf.js
Theoutputshouldnowdisplaythatourexpectationsfailed:
$Expected0tobe3.
Great!Nowtherearenomoreexecutionerrorsinourpage,onlythefailedexpectationsonthenumberoflistitems.
5. Inordertoaddtheitemstothepage,wewillneedtoaddareferencetoTodoController,andthenaddng-repeatforeachitem.Thecodeintheindex.htmlpageshouldbeasfollows:
<divng-controller="TodoController">
<ulng-repeat="iteminlist">
<li>{{item}}</li>
</ul>
</div>
6. Rerunthetestasfollows:
$protractorchromeOnlyConf.js
Theoutputshouldnowdisplaythatourassertionandtestpassed:
$1test,1assertion,0failures
Thecompletedpagebodytagwillnowlookasfollows:
<bodyng-app="todo">
<divng-controller="TodoController">
<ulng-repeat="iteminlist">
<li>{{item}}</li>
www.it-ebooks.info
![Page 109: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/109.jpg)
</ul>
</div>
<scriptsrc="bower_components/angular/angular.js"></script>
<scriptsrc="app/todo.js"></script>
</body>
Makeitbetter
Thereisnothingthatwascalledouttorefactor.Lookingatourto-dolist,wetackledthefirsttwoitemsfromanend-to-endperspective.
1. Viewtheto-do-listitems:
Examplelist:test,execute,refactor
2. Addanitemtoato-do-list:
Examplelist:test,execute,refactor,repeat
3. Removeanitemfromato-do-list:
Examplelist:test,execute,refactor
Iwillleavethesecondandthirditemsasanexercise,sothatyoucanfurtherexploreandpracticeTDDwithProtractor.
www.it-ebooks.info
![Page 110: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/110.jpg)
CleaningupthegapsThereareacoupleofthingsthatwerediscussedinthischapterthatneedsomefurtherclarification.Thisincludesthefollowing:
Whereistheasynchronouslogic?HowtoreallyimplementTDDwithend-to-endtests.
www.it-ebooks.info
![Page 111: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/111.jpg)
AsyncmagicIntheprecedingtests,wesawsomemagicthatyoumightbequestioning.Herearesomeofthemagiccomponentsthatweglancedover:
LoadingapagebeforetestexecutionAssertiononelementsthatgetloadedinpromises
LoadingapagebeforetestexecutionIntheprevioustest,weusedthefollowingcodetospecifythatthebrowsershouldpointtothehomepage:
browser.get('/');
TheprecedingcommandwilllaunchthebrowserandnavigatetothebaseUrllocation.Oncethebrowserreachesthepage,itwillhavetoloadAngularJSandthenimplementtheAngularJS-specificfunctions.Ourtestsdon’thaveanywaitlogic,andthisispartofthebeautyofProtractorwithAngularJS.Thewaitingforpageloadingisalreadybuiltintheframeworkforyou.Yourtestscanthenbewrittenverycleanly.
AssertiononelementsthatgetloadedinpromisesTheassertionsandexpectationsalreadyhavepromisefulfillmentwritteninthem.Inthecaseofourtest,wewrotetheassertionsothatitexpectsthecounttobethree:
expect(todoListItems.count()).toBe(3);
However,inreality,wemayhavethoughtthatweneededtoaddasynchronoustestingtotheassertioninordertowaitforthepromisetobefulfilled,somethingmorecomplicatedlikethefollowing:
it('',function(done){
vartodoListItems=element.all(by.repeater('iteminlist'));
todoListItems.count().then(function(count){
expect(count).toBe(3);
done();
});
})
Theprecedingcodeislonger,moregranular,andhardertoread.Protractorhastheabilityforcertainelementsbuiltintoexpectationstomaketestsmoreconcise.
www.it-ebooks.info
![Page 112: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/112.jpg)
TDDwithProtractorWithourfirsttest,thereisacleardistinctionofend-to-endtestsandunittests.Withtheunittest,wefocusedonstrongcouplingthetesttothecode.Asanexample,ourunittestspiedonthescopeforaspecificcontroller,TodoController.WeusedAngularmockstoinitializethescopewithavariablewecouldthenevaluate:
inject(function($controller){
$controller('TodoController',{$scope:scope});
});
IntheProtractortest,wedon’tcareaboutwhichcontrollerwearetestingandourfocusisontheuserperspectiveofthetest.WefirststartwiththeselectionofaparticularelementwithintheDocumentObjectModel(DOM);inourcase,thatelementistiedtoAngularJS,ng-repeat.TheAssertisthatthenumberofelementsforaspecificrepeaterisequaltotheexpectedcount.
Withtheloosecouplingoftheend-to-endtest,wecanwriteatestthatfocusesontheuserspecification,whichinitiallydisplaysthreeelements,andthenhavethefreedomtowritethatinthepage,controllers,andsoon,inanywaywewant.
www.it-ebooks.info
![Page 113: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/113.jpg)
Self-testquestionsUseTDDwithProtractortodevelopthethirddevelopmentto-dolistitem:
Q1.Protractoruseswhichofthefollowingframeworks?
1. Selenium2. Unobtanium3. Karma
Q2.YoucaninstallAngularmocksbyrunningbowerinstallangular-mocks.
1. True2. False
Q3.WhatstepsdoestheTDDlifecycle,discussedinthisbook,consistof?
1. Testfirst,makeitrun,makeitbetter(refactor)2. Test,makeitbetter(refactor),makeitrun3. Makeitrun,test,makeitbetter
Additionally,ifyouwantmorepractice,addafunctionalitytotheapplicationtoremoveanitemfromtheto-dolist.
www.it-ebooks.info
![Page 114: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/114.jpg)
SummaryThischapterhasgivenyoutheskillsnecessarytoinstall,configure,andapplyTDDprinciplestoend-to-endtesting.WehaveseenhowwecanleveragetheexistingTDDlifecycle(test,makeitrun,makeitbetter)andtechniqueswithProtractor.ProtractorisanimportantpartoftestinganyAngularJSapplication.Itbridgesthegaptoensuretheuser’sspecificationsworkasexpected.Whenend-to-endtestsarewrittentotheuserspecifications,theconfidenceoftheapplicationandabilitytorefactorgrows.Intheupcomingchapters,wewillseehowtoapplyKarmaandProtractorinmoredepthwithsimplestraightforwardexamples.Thenextchapterwillwalkyouthroughtestingcontrollers,usingAngularmocks,andusingProtractortoenterkeystrokes.
www.it-ebooks.info
![Page 115: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/115.jpg)
Chapter4.TheFirstStepThefirststepisalwaysthehardest.Thischapterprovidesaninitialintroductorywalk-throughofhowtouseTDDtobuildanAngularJSapplicationwithacontroller,model,andscope.YouwillbeabletobegintheTDDjourneyandseethefundamentalsinaction.Uptothispoint,thisbookhasfocusedonafoundationofTDDandthetools.Now,wewillswitchgearsanddiveintoTDDwithAngularJS.ThischapterwillbethefirststepofTDD.WehavealreadyseenhowtoinstallKarmaandProtractor,inadditiontosmallexamplesandawalk-throughonhowtoapplyit.Thischapterwillfocusonthecreationofsocialmediacomments.ItwillalsofocusonthetestingassociatedwithcontrollersandtheuseofAngularmockstoAngularJScomponentsinatest.
www.it-ebooks.info
![Page 116: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/116.jpg)
Preparingtheapplication’sspecificationCreateanapplicationtoentercomments.Thespecificationoftheapplicationisasfollows:
GivenIampostinganewcomment,whenIclickonthesubmitbutton,thecommentshouldbeaddedtotheto-dolistGivenacomment,whenIclickonthelikebutton,thenumberoflikesforthecommentshouldbeincreased
Nowthatwehavethespecificationofapplication,wecancreateourdevelopmentto-dolist.Itwon’tbeeasytocreateanentireto-dolistofthewholeapplication.Basedontheuserspecifications,wehaveanideaofwhatneedstobedeveloped.HereisaroughsketchoftheUI:
Holdyourselfbackfromjumpingintotheimplementationandthinkingabouthowyouwilluseacontrollerwithaservice,ng-repeat,andsoon.Resist,resist,resist!Althoughyoucanthinkofhowthiswillbedevelopedinthefuture,itisneverclearuntilyoudelveintothecode,andthatiswhereyoustartgettingintotrouble.TDDanditsprinciplesareheretohelpyougetyourmindandfocusintherightplace.
www.it-ebooks.info
![Page 117: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/117.jpg)
SettinguptheprojectInpreviouschapters,wediscussedindetailhowaprojectshouldbesetup,explainedthedifferentcomponentsinvolved,andwalkedthroughtheentireprocessoftesting.Iwillskipthesedetailsandprovidealistinthefollowingsectionfortheinitialactionstogettheprojectsetup.
www.it-ebooks.info
![Page 118: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/118.jpg)
SettingupthedirectoryThefollowinginstructionsarespecifictosettinguptheprojectdirectory:
1. Createanewprojectdirectory.2. GetangularintotheprojectusingBower:
bowerinstallangular
3. Getangular-mocksfortestingusingBower:
bowerinstallangular-mocks
4. Initializetheapplication’ssourcedirectory:
mkdirapp
5. Initializethetestdirectory:
mkdirspec
6. Initializetheunittestdirectory:
mkdirspec/unit
7. Initializetheend-to-endtestdirectory:
mkdirspec/e2e
Oncetheinitializationiscomplete,yourfolderstructureshouldlookasfollows:
www.it-ebooks.info
![Page 119: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/119.jpg)
SettingupProtractorInChapter3,End-to-endTestingwithProtractor,wediscussedthefullinstallationandsetupofProtractor.Inthischapter,wewilljustdiscussthestepsatahigherlevel:
1. InstallProtractorintheproject:
$npminstallprotractor
2. UpdateSeleniumWebDriver:
$./node_modules/protractor/bin/webdriver-managerupdate
MakesurethatSeleniumhasbeeninstalled.
3. CopytheexamplechromeOnlyconfigurationintotherootoftheproject:
$cp./node_modules/protractor/example/chromeOnlyConf.js.
4. ConfiguretheProtractorconfigurationusingthefollowingsteps:
1. OpentheProtractorconfiguration.2. EdittheSeleniumWebDriverlocationtoreflecttherelativedirectoryto
chromeDriver:
chromeDriver:'./node_modules/protractor/selenium/chromedriver',
3. Editthefilessectiontoreflectthetestdirectory:
specs:['spec/e2e/**/*.js'],
5. SetthedefaultbaseURL:
baseUrl:'http://localhost:8080/',
Excellent!Protractorshouldnowbeinstalledandsetup.Hereisthecompleteconfiguration:
exports.config={
chromeOnly:true,
chromeDriver:'./node_modules/protractor/selenium/chromedriver',
capabilities:{
'browserName':'chrome'
},
baseUrl:'http://localhost:8080/',
specs:['spec/e2e/**/*.js'],
};
www.it-ebooks.info
![Page 120: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/120.jpg)
SettingupKarmaThedetailsforKarmacanbefoundinChapter2,TheKarmaWay.Hereisabriefsummaryofthestepsrequiredtoinstallandgetyournewprojectsetup:
1. InstallKarmausingthefollowingcommand:
npminstallkarma-g
2. InitializetheKarmaconfiguration:
karmainit
3. UpdatetheKarmaconfiguration:
files:[
'bower_components/angular/angular.js',
'bower_components/angular-mocks/angular-mocks.js',
'spec/unit/**/*.js'
],
NowthatwehavesetuptheprojectdirectoryandinitializedProtractorandKarma,wecandiveintothecode.Hereisthecompletekarma.conf.jsfile:
module.exports=function(config){
config.set({
basePath:'',
frameworks:['jasmine'],
files:[
'bower_components/angular/angular.js',
'bower_components/angular-mocks/angular-mocks.js',
'spec/unit/**/*.js'
],
reporters:['progress'],
port:9876,
autoWatch:true,
browsers:['Chrome'],
singleRun:false
});
};
www.it-ebooks.info
![Page 121: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/121.jpg)
Settinguphttp-serverAwebserverwillbeusedtohosttheapplication.Asthiswilljustbeforlocaldevelopmentonly,youcanusehttp-server.Thehttp-servermoduleisasimpleHTTPserverthatservesstaticcontent.Itisavailableasannpmmodule.Toinstallhttp-serverinyourproject,typethefollowingcommand:
$npminstallhttp-server
Oncehttp-serverisinstalled,youcanruntheserverbyprovidingitwiththerootdirectoryofthewebpage.Hereisanexample:
$./node_modules/http-server/bin/http-server
Nowthatyouhavehttp-serverinstalled,youcanmoveontothenextstep.
www.it-ebooks.info
![Page 122: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/122.jpg)
Top-downorbottom-upapproachFromourdevelopmentperspective,wehavetodeterminewheretostart.Theapproachesthatwewilldiscussinthisbookareasfollows:
Thebottom-upapproach:Withthisapproach,wethinkaboutthedifferentcomponentswewillneed(controller,service,module,andsoon)andthenpickthemostlogicaloneandstartcoding.Thetop-downapproach:Withthisapproach,weworkfromtheuserscenarioandUI.Wethencreatetheapplicationaroundthecomponentsintheapplication.
Therearemeritstobothtypesofapproachesandthechoicecanbebasedonyourteam,existingcomponents,requirements,andsoon.Inmostcases,itisbestforyoutomakethechoicebasedontheleastresistance.Inthischapter,theapproachofspecificationistop-down,everythingislaidoutforusfromtheuserscenarioandwillallowyoutoorganicallybuildtheapplicationaroundtheUI.
www.it-ebooks.info
![Page 123: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/123.jpg)
TestingacontrollerBeforegettingintothespecification,andthemind-setofthefeaturebeingdelivered,itisimportanttoseethefundamentalsoftestingacontroller.AnAngularJScontrollerisakeycomponentusedinmostapplications.
www.it-ebooks.info
![Page 124: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/124.jpg)
AsimplecontrollertestsetupWhentestingacontroller,testsarecenteredonthecontroller’sscope.Thetestsconfirmeithertheobjectsormethodsinthescope.Angularmocksprovideinject,whichfindsaparticularreferenceandreturnsitforyoutouse.Wheninjectisusedforthecontroller,thecontrollersscopecanbeassignedtoanouterreferencefortheentiretesttouse.Hereisanexampleofwhatthiswouldlooklike:
describe('',function(){
varscope={};
beforeEach(function(){
module('anyModule');
inject(function($controller){
$controller('AnyController',{$scope:scope});
});
});
});
Intheprecedingcase,thetest’sscopeobjectisassignedtotheactualscopeofthecontrollerwithintheinjectfunction.Thescopeobjectcannowbeusedthroughoutthetest,andisalsoreinitializedbeforeeachtest.
www.it-ebooks.info
![Page 125: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/125.jpg)
InitializingthescopeIntheprecedingexample,scopeisinitializedtoanobject{}.Thisisnotthebestapproach;justlikeapage,acontrollermightbenestedwithinanothercontroller.Thiswillcauseinheritanceofaparentscopeasfollows:
<bodyng-app='anyModule'>
<divng-controller='ParentController'>
<divng-controller='ChildController'>
</div>
</div>
</body>
Asseenintheprecedingcode,wehavethishierarchyofscopesthattheChildControllerfunctionhasaccessto.Inordertotestthis,wehavetoinitializethescopeobjectproperlyintheinjectfunction.Hereishowtheprecedingscopehierarchycanberecreated:
inject(function($controller,$rootScope){
varparentScope=$rootScope.$new();
$controller('ParentController',{$scope:parentScope});
varchildScope=parentScope.$new();
$controller('AnyController',{$scope:childScope});
});
Therearetwomainthingsthattheprecedingcodedoes:
The$rootScopescopeisinjectedintothetest.The$rootScopescopeisthehighestlevelofscopethatexists.Eachlevelofscopeiscreatedwiththe$new()method.Thismethodcreatesthechildscope.
Inthischapter,wewillusethesimplifiedversionandinitializethescopetoanemptyobject;however,itisimportanttounderstandhowtocreatethescopewhenrequired.
www.it-ebooks.info
![Page 126: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/126.jpg)
BringonthecommentsNowthatthesetupandapproachhavebeendecided,wecanstartourfirsttest.Fromatestingpointofview,aswewillbeusingatop-downapproach,wewillwriteourProtractortestsfirstandthenbuildtheapplication.WewillfollowthesameTDDlifecyclewehavealreadyreviewed,thatis,testfirst,makeitrun,andmakeitbetter.
www.it-ebooks.info
![Page 127: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/127.jpg)
TestfirstThescenariogivenisinawell-specifiedformatalreadyandfitsourProtractortestingtemplate:
describe('',function(){
beforeEach(function(){
});
it('',function(){
});
});
Placingthescenariointhetemplate,wegetthefollowingcode:
describe('GivenIampostinganewcomment',function(){
describe('WhenIpushthesubmitbutton',function(){
beforeEach(function(){
});
it('Shouldthenaddthecomment',function(){
});
});
});
Followingthe3A’s(Assemble,Act,Assert),wewillfittheuserscenariointhetemplate.
AssembleThebrowserwillneedtopointtothefirstpageoftheapplication.AsthebaseURLhasalreadybeendefined,wecanaddthefollowingtothetest:
beforeEach(function(){
browser.get('/');
});
Nowthatthetestisprepared,wecanmoveontothenextstep,Act.
ActThenextthingweneedtodo,basedontheuserspecification,isaddanactualcomment.Theeasiestthingistojustputsometextintoaninputbox.Thetestforthis,againwithoutknowingwhattheelementwillbecalledorwhatitwilldo,istowriteitbasedonwhatitshouldbe.
Hereisthecodetoaddthecommentsectionfortheapplication:
beforeEach(function(){
...
varcommentInput=$('input');
commentInput.sendKeys('acomment');
});
Thelastassemblecomponent,aspartofthetest,istopushtheSubmitbutton.ThiscanbeeasilyachievedinProtractorusingtheclickfunction.Eventhoughwedon’thaveapageyet,oranyattributes,wecanstillnamethebuttonthatwillbecreated:
www.it-ebooks.info
![Page 128: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/128.jpg)
beforeEach(function(){
...
varsubmitButton=element.all(by.buttonText('Submit')).click();
});
Finally,wewillhitthecruxofthetestandasserttheusers’expectations.
AssertTheuserexpectationisthatoncetheSubmitbuttonisclicked,thecommentisadded.Thisisalittleambiguous,butwecandeterminethatsomehowtheuserneedstogetnotifiedthatthecommentwasadded.Thesimplestapproachistodisplayallcommentsonthepage.InAngularJS,theeasiestwaytodothisistoaddanng-repeatobjectthatdisplaysallcomments.Totestthis,wewilladdthefollowing:
it('Shouldthenaddthecomment',function(){
varcomments=element(by.repeater('commentincomments')).first();
expect(comment.getText()).toBe('acomment');
});
Now,thetesthasbeenconstructedandmeetstheuserspecifications.Itissmallandconcise.Hereisthecompletedtest:
describe('GivenIampostinganewcomment',function(){
describe('WhenIpushthesubmitbutton',function(){
beforeEach(function(){
//Assemble
browser.get('/');
varcommentInput=$('input');
commentInput.sendKeys('acomment');
//Act
//Act
varsubmitButton=element.all(by.buttonText('Submit')).
click();
});
//Assert
it('Shouldthenaddthecomment',function(){
varcomments=element(by.repeater('commentin
comments')).first();
expect(comment.getText()).toBe('acomment');
});
});
});
www.it-ebooks.info
![Page 129: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/129.jpg)
MakeitrunBasedontheerrorsandoutputofthetest,wewillbuildourapplicationaswego.
1. Thefirststeptomakethecoderunistoidentifytheerrors.Beforestartingoffthesite,let’screateabarebonesindex.htmlpage:
<!DOCTYPEhtml>
<html>
<head>
<title></title>
</head>
<body>
</body>
</html>
Alreadyanticipatingthefirsterror,addAngularJSasadependencyinthepage:
<scripttype='text/javascript'
src='bower_components/angular/angular.js'></script>
</body>
2. Now,startingthewebserverusingthefollowingcommand:
$./node_modules/http-server/bin/http-server-p8080
3. RunProtractortoseethefirsterror:
$./node_modules/.bin/protractorchromeOnlyConf.js
4. OurfirsterrorstatesthatAngularJScouldnotbefound:
Error:Angularcouldnotbefoundonthepagehttp://localhost:8080/:
angularneverprovidedresumeBootstrap
Thisisbecauseweneedtoaddng-apptothepage.Let’screateamoduleandaddittothepage.
ThecompleteHTMLpagenowlooksasfollows:
<!DOCTYPEhtml>
<html>
<head>
<title></title>
</head>
<body>
<scriptsrc="bower_components/angular/angular.js"></script>
</body>
</html>
AddingthemoduleThefirstcomponentthatyouneedtodefineisanng-appattributeintheindex.htmlpage.
www.it-ebooks.info
![Page 130: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/130.jpg)
Usethefollowingstepstoaddthemodule:
1. Addng-appasanattributetothebodytag:
<bodyng-app='comments'>
2. Now,wecangoaheadandcreateasimplecommentsmoduleandaddittoafilenamedcomments.js:
angular.module('comments',[]);
3. Addthisnewfiletoindex.html:
<scriptsrc='app/commentController.js'></script>
4. ReruntheProtractortesttogetthenexterror:
$Error:Noelementfoundusinglocator:By.cssSelector('input')
Thetestcouldn’tfindourinputlocator.Youneedtoaddtheinputtothepage.
AddingtheinputHerearethestepsyouneedtofollowtoaddtheinputtothepage:
1. Allwehavetodoisaddasimpleinputtagtothepage:
<inputtype='text'/>
2. Runthetestandseewhatthenewoutputis:
$Error:Noelementfoundusinglocator:by.buttonText('Submit')
3. Justlikethepreviouserror,weneedtoaddabuttonwiththeappropriatetext:
<buttontype='button'>Submit</button>
4. Runthetestagainandthenexterrorisasfollows:
$Error:Noelementfoundusinglocator:by.repeater('commentin
comments')
Thisappearstobefromourexpectationthatasubmittedcommentwillbeavailableonthepagethroughng-repeat.Toaddthistothepage,wewilluseacontrollertoprovidethedatafortherepeater.
ControllerAswementionedintheprecedingsection,theerrorisbecausethereisnocommentsobject.Inordertoaddthecommentsobject,wewilluseacontrollerthathasanarrayofcommentsinitsscope.Usethefollowingstepstoaddacommentsobjectinthescope:
1. CreateanewfileintheappdirectorynamedcommentController.js:
angular.module('comments')
.controller('CommentController',['$scope',function($scope){
www.it-ebooks.info
![Page 131: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/131.jpg)
$scope.comments=[];
}])
2. AddittothewebpageaftertheAngularJSscript:
<scriptsrc='app/commentController.js'></script>
3. Now,wecanaddcommentControllertothepage:
<divng-controller='CommentController'>
4. Then,addarepeaterforthecommentsasfollows:
<ulng-repeat='commentincomments'>
<li>{{comment}}</li>
</ul>
5. RuntheProtractortestandlet’sseewhereweare:
$Error:Noelementfoundusinglocator:by.repeater('commentin
comments')
Hmmm!Wegetthesameerror.
6. Let’slookattheactualpagethatgetsrenderedandseewhat’sgoingon.InChrome,gotohttp://localhost:8080andopentheconsoletoseethepagesource(Ctrl+Shift+J).Youshouldseesomethinglikewhat’sshowninthefollowingscreenshot:
Noticethattherepeaterandcontrollerareboththere;however,therepeateriscommentedout.SinceProtractorisonlylookingatvisibleelements,itwon’tfindtherepeater.
7. Great!Nowweknowwhytherepeaterisn’tvisible,butwehavetofixit.Inorderforacommenttoshowup,ithastoexistonthecontroller’scommentsscope.Thesmallestchangeistoaddsomethingtothearraytoinitializeitasshowninthefollowingcodesnippet:
.controller('CommentController',['$scope',function($scope){
$scope.comments=['anything'];
www.it-ebooks.info
![Page 132: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/132.jpg)
}]);
8. Nowrunthetestandwegetthefollowing:
$Expected'anything'tobe'acomment'.
Wow!Wefinallytackledalltheerrorsandreachedtheexpectation.HereiswhattheHTMLcodelookslikesofar:
<!DOCTYPEhtml>
<html>
<head>
<title></title>
</head>
<bodyng-app='comments'>
<divng-controller='CommentController'>
<inputtype='text'/>
<ul>
<ling-repeat='commentincomments'>
{{comment.value}}
</li>
</ul>
</div>
<scriptsrc='bower_components/angular/angular.js'></script>
<scriptsrc='app/comments.js'></script>
<scriptsrc='app/commentController.js'></script>
</body>
</html>
Thecomments.jsmodulelooksasfollows:
angular.module('comments',[]);
HereiscommentController.js:
angular.module('comments')
.controller('CommentController',['$scope',function($scope){
$scope.comments=[];
}])
MakeitpassWithTDD,youwanttoaddthesmallestpossiblecomponenttomakethetestpass.Sincewehavehardcoded,forthemoment,thecommentstobeinitializedtoanything,changeanythingtoacomment;thisshouldmakethetestpass.Hereisthecodetomakethetestpass:
angular.module('comments')
.controller('CommentController',['$scope',function($scope){
$scope.comments=['acomment'];
}]);
…
Runthetest,andbam!Wegetapassingtest:
www.it-ebooks.info
![Page 133: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/133.jpg)
$1test,1assertion,0failures
Waitasecond!Westillhavesomeworktodo.Althoughwegotthetesttopass,itisnotdone.Weaddedsomehacksjusttogetthetestpassing.Thetwothingsthatstandoutare:
ClickingontheSubmitbutton,whichreallydoesn’thaveanyfunctionalityHardcodedinitializationoftheexpectedvalueforacomment
Theprecedingchangesarecriticalstepsweneedtoperformbeforewemoveforward.TheywillbetackledinthenextphaseoftheTDDlifecycle,thatis,makeitbetter(refactor).
www.it-ebooks.info
![Page 134: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/134.jpg)
MakeitbetterThetwocomponentsthatneedtobereworkedare:
AddingbehaviortotheSubmitbuttonRemovinghardcodedvalueofthecomments
www.it-ebooks.info
![Page 135: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/135.jpg)
ImplementingtheSubmitbuttonTheSubmitbuttonneedstoactuallydosomething.Wewereabletosidesteptheimplementationbyjusthardcodingthevalue.UsingourtriedandtrustedTDDtechniques,switchtoanapproachfocusedonunittesting.Sofar,thefocushasbeenontheUIandpushingchangestothecode.Wehaven’twrittenasingleunittest.
Forthisnextbitofwork,wewillswitchgearsandfocusondrivingthedevelopmentoftheSubmitbuttonthroughtests.WewillbefollowingtheTDDlifecycle(testfirst,makeitrun,makeitbetter).
ConfiguringKarmaWedidsomethingverysimilarfortheto-dolistapplicationinChapter2,TheKarmaWay.Iwon’tspendasmuchtimedivingintothecode,sopleasereviewthepreviouschaptersforadeeperdiscussiononsomeoftheattributes.HerearethestepsyouneedtofollowtoconfigureKarma:
1. Updatethefilessectionwiththeaddedfiles:
files:[
...
'app/comments.js',
'app/commentController.js',
...
],
2. StartKarma:
$karmastart
3. ConfirmthatKarmaisrunning:
$Chrome36.0.1985(Windows7):Executed1of1SUCCESS(0.018secs/
0.015secs)
TestfirstLet’sfirststartwithanewfileinthespec/unitfoldercalledcomments.js.Wewillusethebasetemplate:
describe('',function(){
beforeEach(function(){
});
it('',function(){
});
});
Accordingtothespecification,whentheSubmitbuttonisclicked,itneedstoaddacomment.Wewillneedtofillintheblanksofthethreecomponentsofatest(Assemble,Act,Assert).
www.it-ebooks.info
![Page 136: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/136.jpg)
Assemble
Thebehaviorwillneedtobepartofacontrollerforthefrontendtouseit.Theobjectundertestinthiscaseisthecontroller’sscopeobject;wewillneedtoaddthistotheassembleofthistest.TowireuptheAngularJScontrollerweneedtoinitializethemoduleandtheninjecttheCommentControllerscopeintothetest.AswedidinChapter2,TheKarmaWay,wewilldothesameinthefollowingcode:
varscope={};
beforeEach(function(){
module('comments');
inject(function($controller){
$controller('CommentController',{$scope:scope});
});
...
})
Now,thecontroller’sscopeobject,whichisundertest,isavailabletothetest.
Act
Thespecificationdeterminesthatweneedtocallaaddmethodinthescopeobject.AddthefollowingcodetothebeforeEachsectionofthetest:
beforeEach(function(){
…
scope.add('anyComment');
});
Nowfortheassertion.
Assert
Assertthatthecommentitemsinthescopeobjectnowcontainanycommentasthefirstelement.Addthefollowingcodetothetest:
it('',function(){
expect(scope.comments[0]).toBe('anycomment');
});
Savethefileandlet’smoveontothenextstepofthelifecycleandmakeitrun(execute).
MakeitrunNowthatwehavemostofthetestprepared,weneedtomakethetestpass.LookingattheoutputoftheconsolewhereKarmaisrunning,weseethefollowing:
$TypeError:undefinedisnotafunction…unit/comments.js:4:9
Lookingatthelinenumber,thatis4:9,ofourunittest,weseethatthisistheaddfunction.Let’sgoaheadandputinanaddfunctionintothecontroller’sscopeobjectusingthefollowingsteps:
1. Openthecontrollerscopeandcreateafunctionnamedadd:
$scope.add=function(){}
www.it-ebooks.info
![Page 137: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/137.jpg)
2. CheckKarma’soutputandlet’sseewhereweare:
$Expected'acomment'tobe'anycomment'.
3. Now,wehavehittheexpectation.Remembertothinkofthesmallestchangetogetthistowork.Modifytheaddfunctiontosetthe$scope.commentsarraytoanycommentwhencalled:
$scope.add=function(){
$scope.comments.unshift('anycomment');
};
TipUnshiftisastandardJavaScriptfunctionthataddsanitemtothefrontofanarray.
4. WhenwecheckKarma’soutput,weseethefollowing:
$Chrome36.0.1985(Windows7):Executed1of1SUCCESS
Success!Thetestpasses,butagainneedssomework.Let’smoveontothenextstageandmakeitbetter(refactor).
MakeitbetterThemainpointthatneedstoberefactoredistheaddfunction.Itdoesn’ttakeanyarguments!Thisshouldbestraightforwardtoadd,andsimplyconfirmthattheteststillruns.UpdatetheaddfunctionofCommentController.jstotakeanargumentandusethatargumenttoaddtothecommentsarray:
$scope.add=function(commentToAdd){
$scope.comments.unshift(commentToAdd);
};
ChecktheoutputwindowofKarmaandensurethattheteststillpasses.Thecompleteunittestlooksasfollows:
describe('',function(){
varscope={};
beforeEach(function(){
module('comments');
inject(function($controller){
$controller('CommentController',{$scope:scope});
});
scope.add('anycomment');
});
it('',function(){
expect(scope.comments[0]).toBe('anycomment');
})
});
TheCommentControllerfilenowlooksasfollows:
www.it-ebooks.info
![Page 138: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/138.jpg)
angular.module('comments')
.controller('CommentController',['$scope',function($scope){
$scope.comments=[];
$scope.add=function(commentToAdd){
$scope.comments.unshift(newComment);
};
}]);
BackupthetestchainWecompletedtheunittestandadditionoftheaddfunction.NowwecanaddthefunctiontospecifythebehavioroftheSubmitbutton.Thewaytolinktheaddmethodtothebuttonistotousetheng-clickattribute.ThestepstoaddbehaviortotheSubmitbuttonareasfollows:
1. Opentheindex.htmlpageandlinkitasfollows:
<buttontype="button"ng-click="add('acomment')">Submit</button>
Warning!Isthevaluehardcoded?Well,again,wewanttodothesmallestchangeandensurethattheteststillpasses.Wewillworkthroughourrefactorsuntilthecodeishowwewantit,butinsteadofabigbangapproach,wewanttomakesmallincrementalchanges.
2. Nowlet’sreruntheProtractortestandensurethatitstillpasses.Theoutputsaysitpasses,andweareokay.Thehardcodedvaluewasn’tremovedfromthecomments.Let’sgoaheadandremovethatnow.TheCommentsControllerfileshouldnowlookasfollows:
$scope.comments=[];
3. Runthetestandseethatwestillgetapassingtest.
Nowthelastthingweneedtomopupisthehardcodedvalueinng-click.Thecommentbeingaddedshouldbedeterminedbytheinputinthecommentinputtext.
BindtheinputHerearethestepsyouneedtofollowtobindtheinput:
1. Tobeabletobindtheinputintosomethingmeaningful,addanng-modelattributetotheinputtag:
<inputtype='text'ng-model='newComment'/>
2. Then,intheng-clickattribute,simplyusethenewCommentmodelastheinput:
<buttontype='button'ng-click='add(newComment)'>Submit</button>
RuntheProtractortestandconfirmthateverythinghaspassedandisgoodtogo.
www.it-ebooks.info
![Page 139: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/139.jpg)
OnwardsandupwardsNowthatwehavethefirstspecificationworkingend-to-endandunittested,wecanstartthenextspecification.Thenextspecificationstatesthattheuserswanttheabilitytolikeacomment.
Wewillusethesametop-downapproachandstartourtestfromaProtractortest.WewillcontinuetofollowtheTDDlifecycle,thatis,testfirst,makeitrun,makeitbetter.
www.it-ebooks.info
![Page 140: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/140.jpg)
TestfirstFollowingthepattern,wewillstartwithabasicProtractortesttemplate:
describe('',function(){
beforeEach(function(){
});
it('',function(){
});
});
Whenwefillinthespecification,wegetthefollowing:
describe('WhenIlikeacomment',function(){
beforeEach(function(){
});
it('shouldthenbeliked',function(){
});
});
Withthetemplateinplace,wearereadytoconstructthetest.
AssembleTheassemblyofthistestwillrequireacommenttoexist.Placethecommentwithintheexistingpostedcommenttest.Itshouldlooksimilartothis:
describe(''GivenIampostinganewcomment',function(){
describe('WhenIlikeacomment',function(){
…
});
});
ActTheuserspecificationwetestisthatthelikebuttonperformsanactionforaspecificcomment.Herearethestepsthatwillberequiredandthecoderequiredtodothem(notethatthefollowingstepswillbeaddedtothebeforeEachtext):
1. Storethefirstcommentsothatitcanbeusedinthetest:
varfirstComment=null;
beforeEach(function(){
…
2. Findthefirstcomment’slikebutton:
varfirstComment=element.all(by.repeater('commentin
comments').first();
varlikeButton=firstComment.element(by.buttonText('like'));
3. Thecodeforthelikebuttonwhenitisclickedisasfollows:
likeButton.click();
www.it-ebooks.info
![Page 141: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/141.jpg)
AssertThespecificationexpectationisthatoncethecommenthasbeenliked,itisliked.Thisisbestdonebyputtinganindicatorofthenumberoflikes,andensuringthecountis1.Thecodewillthenbeasfollows:
it('Shouldincreasethenumberoflikestoone',function(){
varcommentLikes=firstComment.element(by.binding('likes'));
expect(commentLikes.getText()).toBe(1);
});
Thecreatedtestnowlooksasfollows:
describe('WhenIlikeacomment',function(){
varfirstComment=null;
beforeEach(function(){
//Assemble
firstComment=element.all(by.repeater('commentincomments').first();
varlikeButton=firstComment.element(by.buttonText('like'));
//Act
likeButton.click();
});
//Assert
it('Shouldincreasethenumberoflikestoone',function(){
varcommentLikes=firstComment.element(by.binding('likes'));
expect(commentLikes.getText()).toBe(1);
});});
www.it-ebooks.info
![Page 142: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/142.jpg)
MakeitrunThetesthasbeenpreparedandisitchingtorun.Wewillnowrunthetestandfixthecodeuntilthetestpasses.Thefollowingstepswilldetailtheerrorandthefixcyclerequiredtomakethetestpath:
1. RunProtractor.2. Viewtheerrormessageinthecommandline:
$Error:Noelementfoundusinglocator:by.buttonText("like")
3. Astheerrorstates,thereisnolikebutton.Goaheadandaddthebutton:
<ling-repeat='commentincomments'>
{{comment}}
<buttontype="button">like</button>
</li>
4. RunProtractor.5. Viewthenexterrormessage:
$Expected'acommentlike'tobe'acomment'.
6. Byaddingthelikebutton,wecausedourothertesttofail.ThereasonisouruseofthegetText()method.Protractor’sgetText()methodgetstheinnertextincludinginnerelements.Tofixthis,wewillneedtoupdatetheprevioustesttoincludelikeaspartofthetest:
it('Shouldthenaddthecomment',function(){
varcomments=element.all(by.repeater('commentincomments')).first();
expect(comments.getText()).toBe('acommentlike');
});
7. RunProtractor.8. Viewthenexterrormessage:
$Error:Noelementfoundusinglocator:by.binding("likes")
9. Timetoaddalikesbinding.Thisoneisalittlemoreinvolved.Likesneedstobeboundtoacomment.Weneedtochangethewaythecommentsareheldinthecontroller.Commentsneedtoholdthecommentvalueandthenumberoflikes.Acommentshouldbeanobjectlikethis:{value:'',likes:0}.Again,thefocusofthisstepisjusttogetthetesttopass.Thenextstepistoupdatethecontroller’saddfunctiontocreatecommentsbasedontheobjectwedescribedintheprecedingsteps.OpencommentController.jsandedittheaddfunctionasfollows:
$scope.add=function(commentToAdd){
varnewComment={value:commentToAdd,likes:0};
$scope.comments.unshift(newComment);
};
10. Updatethepagetousethevalueforthecomment:
www.it-ebooks.info
![Page 143: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/143.jpg)
<ling-repeat='commentincomments'>
{{comment.value}}
11. BeforererunningtheProtractortest,weneedtoaddthenewcomment.likesbindingtotheHTMLpage:
<ling-repeat='commentincomments'>
…
{{comment.likes}}
12. NowreruntheProtractortestsandlet’sseewheretheerrorsare:
$Expected'acommentlike0'tobe'acommentlike'
13. Becausetheinnertextofthecommenthaschanged,weneedtochangetheexpectationofthetest:
it('Shouldthenaddthecomment',function(){
…
expect(comments.getText()).toBe('acommentlike0');
});
14. RunProtractor:
$Expected'0'tobe'1'.
15. Now,wearefinallydowntotheexpectationofthetest.Inordertomakethistestpass,thesmallestchangewillbetomakethelikebuttonupdatethelikesonthecommentarray.Thefirststepistoaddalikemethodonthecontroller,whichwillupdatethenumberoflikes:
$scope.like=function(comment){
comment.likes++;
};
16. LinkthelikemethodtotheHTMLpageusinganng-clickattributeonthebuttonasfollows:
<buttontype="button"ng-click='like(comment)'>like</button>
17. RunProtractorandconfirmthatthetestspass!
Thepagenowlooksasfollows:
Comparedtothedrawingatthebeginningofthischapter,allthefeatureshavebeencreated.NowthatwemadethetestpassinProtractor,weneedtochecktheunitteststo
www.it-ebooks.info
![Page 144: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/144.jpg)
ensurethatourchangesdidn’tbreaktheunittests.
FixingtheunittestsOneoftheprimarychangesrequiredwastomakethecommentanobject,consistingofavalueandnumberoflikes.Beforethinkingtoomuchabouthowtheunittestscouldhavebeenaffected,let’skickthemoff.Executethefollowingcommand:
$karmastart
Asexpected,theerrorisrelatedtothenewcommentobject:
$Expected{value:'anycomment',likes:0}tobe'anycomment'.
Reviewingtheexpectation,itseemsliketheonlythingrequiredisforcomment.valuetobeusedintheexpectationasopposedtothecommentobjectitself.Changetheexpectationasfollows:
it('',function(){
varfirstComment=scope.comments[0];
expect(firstComment.value).toBe('anycomment');
})
SavethefileandchecktheKarmaoutput.Confirmthatthetestpasses.BoththeKarmaandProtractortestspassandwehavecompletedtheprimaryuserbehaviorsofaddingacommentandlikingit.Youarefreenowtomoveontothenextstepandmakethingsbetter.
www.it-ebooks.info
![Page 145: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/145.jpg)
MakeitbetterAllinall,theapproachendedupwiththeresultwewanted.UsersarenowabletolikeacommentintheUIandseethenumberoflikes.Themajorcalloutfromarefactorstandpointisthatwehavenotunittestedthelikemethod.Reviewingourdevelopmentto-dolist,weseethattheto-dolistisanactionwewrotedown.Beforecompletelywrappingupthefeature,let’sdiscusstheoptionofaddingaunittestforthelikefunctionality.
CouplingofthetestAsalreadydiscussedinthisbook,testsaretightlycoupledtotheimplementation.Thisisagoodthingwhenthereisacomplicatedlogicinvolvedoryouneedtoensurethatcertainaspectsoftheapplicationbehaveincertainways.Itisimportanttobeawareofthecouplingandknowwhenitisimportanttobringitintotheapplicationandwhenitisnot.Thelikefunctionwecreatedsimplyincrementsacounteronanobject.Thiscanbeeasilytested;however,thecouplingwewillbringinwithaunittestwillnotgiveustheextravalue.Inthiscase,wewillnotaddanadditionalunittestforthelikemethod.Astheapplicationprogresses,wemayfindtheneedtoaddaunittestinordertodevelopandextendthefunction.HereareacoupleofthingsIconsiderwhenaddingatest:
Doesaddingatestoutweighthecostofmaintainingatest?Isthetestaddingvaluetothecode?
Doesithelpotherdevelopersbetterunderstandthecode?
Isthefunctionalitybeingtestedinsomeotherway?
Basedonourdecision,thereisnomorerefactoringortestingrequired.Inthenextsection,wewilltakeastepbackandreviewthemainpointsofthischapter.
www.it-ebooks.info
![Page 146: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/146.jpg)
Self-testquestionsQ1.The$newfunctionisusedtocreateachildscope:$scope.$new.
1. True2. False
Q2.Giventhefollowingcodesegment,howwouldyouselecttheitemsinthelist?
<ul>
<ling-repeat="iteminmyItems">
{{item.value}}
</li
</ul>
1. element.all(by.repeater('iteminitems')).2. element.all(by.repeater('iteminmyItems')).3. element.all('iteminitems').
Q3.TheAngularmocksinjectfunctionisusedto:
1. Resolveapplicationdependencies/references.2. Injectdependenciesintotheapplication.3. Noneoftheabove.
www.it-ebooks.info
![Page 147: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/147.jpg)
SummaryInthischapter,wewalkedthroughtheTDDtechniquesofusingProtractorandKarmatogether.Astheapplicationwasdeveloped,youwereabletoseewhere,why,andhowtoapplytheTDDtestingtoolsandtechniques.Theapproach,top-down,wasdifferentthanthebottom-upapproachdiscussedinChapter2,TheKarmaWayandChapter3,End-to-endTestingwithProtractor.Withthebottom-upapproach,thespecificationsareusedtobuildunittestsandthenbuildtheUIlayerontopofthat.Inthischapter,atop-downapproachwasshowntofocusontheuser’sbehavior.Thetop-downapproachteststheUIandthenfiltersthedevelopmentthroughtheotherlayers.Bothapproacheshavetheirmerit.WhenapplyingTDD,itisessentialtoknowhowtouseboth.InadditiontowalkingthroughadifferentTDDapproach,yousawsomeofthecoretestingcomponentsofAngularJSsuchas:
Testingacontrollerfromend-to-endandunitperspectivesUsingAngularmockstotestthescopeobjectofacontrollerProtractor’sabilityto:
Bindtong-repeaterandng-modelSendkeystrokestoinputcolumnsGetanelement’stextbyitsinnerHTMLcodeandallsubelements
Thenextchapterwillbuildonthetechniquesusedhereandlookintoheadlessbrowsertesting,advancedtechniquesforProtractor,andhowtotestAngularJSroutes.
www.it-ebooks.info
![Page 148: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/148.jpg)
Chapter5.FlipFlopAtthispoint,youshouldbefeelingconfidentintheinitialimplementationofanAngularJSapplicationusingTDD.Youshouldbefamiliarwithusingatest-firstapproach.Inthischapter,youwillcontinuetoexpandyourknowledgeofapplyingTDDwithAngularJSbylookingatthefollowing:
AngularJSroutesPartialviewsProtractorlocationreferenceswithCSS(CascadingStyleSheets)andHTMLelementsHeadlessbrowsertestingwithKarma
www.it-ebooks.info
![Page 149: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/149.jpg)
FundamentalsThischapterwillwalkyouthroughapplyingTDDtoroutesandpartialviewsforasearchapplication.Beforegettingintothewalk-through,youneedtobeawareofsomeofthetechniques,configurations,andfunctionsthatwillbeusedthroughoutthischapter,whichinclude:
ProtractorlocatorsHeadlessbrowsertesting
Afteryouhavereviewedtheseconcepts,youcanmoveontothewalk-through.
www.it-ebooks.info
![Page 150: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/150.jpg)
ProtractorlocatorsProtractorlocatorsarekeycomponentsthatyoumusttaketimetolearn.Thisbookwillnotbeabletoshowexamplesofallthedifferentlocators,butitwillprovideexamplesofthemostcommonones.
ProtractorlocatorsallowyoutofindelementswithinanHTMLpage.Inthischapter,youwillseethefollowinginaction:CSS,HTML,andAngularJS-specificlocators.Locatorsarepassedtotheelementfunction.Theelementfunctionwillfindandreturnelementsinapage.Thegenericlocatorsyntaxisasfollows:
element(by.<LOCATOR>);
Intheprecedingcode,<LOCATOR>isaplaceholder.Thefollowingsectionsdescribeacoupleoftheselocators.
CSSlocatorsCSSisusedtoaddlayout,color,formatting,andstyletoanHTMLpage.Fromanend-to-endtestingperspective,thelookandstyleofanelementmaybepartofaspecification.AsanexampleconsiderthefollowingHTMLsnippet:
<divclass="anyClass"id="anyId"></div>
//...
vare1=element(by.css('.anyClass'));
vare2=element(by.css('#anyId'));
vare3=element(by.css('div'));
vare4=$('div');
Allfourselectionswillselectthedivelement.
ButtonandlinklocatorsBesidesbeingabletoselectandinterpretthewaysomethinglooks,itisalsoimportanttobeabletofindbuttonsandlinkswithinapage.Thiswillallowatesttointeractwiththesiteeasily.Hereareacoupleofexamples:
Buttontextlocator:
<button>anyButton</button>
//...
varb1=element(by.buttonText('anyButton'));
Linktextlocator:
<ahref="#">anyLink</a>
//...
vara1=element(by.linkText('anyLink'));
AngularlocatorsOneofProtractor’skeystrengthsisthatitprovidestestingfunctionalityspecifictoAngularJS.Therepeaterlocatorwillselecttheelementswithintheapplicationwhereng-
www.it-ebooks.info
![Page 151: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/151.jpg)
repeatwasused.Thisisespeciallyusefulwhenlookingatthenumberofreturnedresultsandthevaluesofindividualresults.Onekeytousingthislocatoristhatthestringoftherepeaterlocatormustmatchtheng-repeatstringusedintheAngularJSapplication.Hereisanexampleofusingtherepeaterlocator:
//TheListintheapplicationtouseng-repeaton
<ling-repeat="iteminlist">
<div>
<ahref="#">link</a>
</div>
</li>
//...
varfirstItem=element.all(by.repeater('iteminlist')).first();
Theprecedingcodehighlightshowtofindthefirstelementinarepeater.Itshouldbeclearthatinthiscase,theelement.allfunctionfindsalltheelementsmatchingtheselector.Then,thefirst()methodisusedtoreturnthefirstelementfound.
URLlocationreferencesWhentestingAngularJSroutes,youneedtobeabletotesttheURLofyourtest.ByaddingtestsaroundtheURLandlocation,youensurethattheapplicationfollowsspecificroutes.Thisisimportantbecauseroutesprovideaninterfaceintoyourapplication.HereishowtogettheURLreferenceinaProtractortest:
varlocation=browser.getLocationAbsUrl();
Nowthatyouhaveseenhowtousethedifferentlocatorsitistimetoputtheknowledgetouse.
www.it-ebooks.info
![Page 152: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/152.jpg)
CreatinganewprojectItisimportanttogetaprocessandmethodtosetupyourprojectsquickly.Thelesstimeyou’rethinkingofthestructureofthedirectoryandtherequiredtools,themoretimeyou’redeveloping!
Somepeopleusetheangular-seed(https://github.com/angular/angular-seed)project,Yeoman,orcreateacustomtemplate.Althoughthesetechniquesareusefulandhavetheirmerit,whenstartingoutinAngularJS,itisessentialtounderstandwhatittakestobuildanapplicationfromthegroundup.Bybuildingthedirectorystructureandinstallingtoolsyourself,youwillunderstandAngularJSbetter.Youwillbeabletomakelayoutdecisionsbasedonyourspecificapplicationandneeds,asopposedtofittingintosomeothermold.AsyougrowandbecomeabetterAngularJSdeveloper,thisstepmaynotbeneededandwillbecomesecondnaturetoyou.
Inpreviouschapters,wediscussedhowtogettheprojectsetup,explainedthedifferentcomponentsinvolved,andwalkedthroughtheentireprocess.Iwillskipthesedetailsandexpectthatyoucanrecallhowtoperformthenecessaryinstallation.Toconfirmtheinstallation,hereisascreenshotoftheexpectedoutput:
www.it-ebooks.info
![Page 153: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/153.jpg)
SettingupheadlessbrowsertestingforKarmaInpreviouschapters,youwererunningKarmausingthedefaultconfiguration.ThedefaultChromeconfigurationlaunchesChromeoneverytest.Testingagainsttheactualcodeandbrowser,whichtheapplicationwillrunin,isapowerfultool.However,whenlaunching,abrowsermaynotbehowyoualwayswantedit.Fromaunittestperspective,youmaynotwantthebrowsertobelaunchedinawindow.Someofthereasonsaretestsmaytakealongtimetorunoryoumaynotalwayshaveabrowserinstalled.
Luckily,KarmacomesequippedwiththeabilitytoeasilyconfigurePhantomJS,aheadlessbrowser.AheadlessbrowserrunsinthebackgroundandwillnotdisplaywebpagesinaUI.ThePhantomJSheadlessbrowserisareallygreattooltousefortesting.Itcanevenbesetuptotakescreenshotsofyourtests!ReadmoreabouthowthisisdoneandtheWebKitusedonthePhantomJSsiteathttp://phantomjs.org/.ThesucceedingsetupconfigurationwillshowyouhowtosetupPhantomJSwithKarmatogetheadlessbrowsertesting.
PreconfigurationWhenKarmaisinstalled,itautomaticallyincludesthePhantomJSbrowserplugin.Foryourreference,thepluginislocatedathttps://github.com/karma-runner/karma-phantomjs-launcher.Thereshouldn’tbeanyadditionalinstallationorconfigurationrequired.However,ifyoursetupstatesthatitismissingkarma-phantomjs-launcher,youcaneasilyinstallitusingnpm:
$npminstallkarma-phantomjs-launcher
ConfigurationPhantomJSisconfiguredinthebrowsersectionoftheKarmaconfiguration.Openthekarma.conffileandupdateitwiththefollowingdetails:
browsers:['PhantomJS'],
Nowthattheprojecthasbeeninitializedandconfiguredwithheadlessbrowsertesting,youcanseeitinactionthroughthefollowingwalk-throughs.
www.it-ebooks.info
![Page 154: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/154.jpg)
Walk-throughofAngularroutesThiswalk-throughwillleverageAngularJSroutes.RoutesareanextremelyusefulfeatureofAngularJS.Theyallowyoutocontrolcertainaspectsoftheapplicationusingdifferentviews.Thiswalk-throughwillflipbetweenviewstoshowyouhowtouseTDDtobuildroutes.Thefollowingarethespecifications:
GivenaviewAthathasasinglebutton;thefollowingactionswilltakeplace:
ThebuttonispushedTheviewisswitchedtoviewB
GivenaviewBthathasasinglebutton;thefollowingactionswilltakeplace:
ThebuttonispushedTheviewisswitchedtoviewA
Essentially,thiswillbeanapplicationthatdoesaflipflopbetweenviews.
www.it-ebooks.info
![Page 155: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/155.jpg)
SettingupAngularJSroutesBeforeyouuseAngularJSroutes,youneedtoinstalltheAngularJSroutecomponent.YoucaninstallAngularJSroutesusingbowerasfollows:
$bowerinstallangular-route
AngularroutesrequiresAngular,asyoucanimagine.InordertouseitanHTMLpagewouldlookasfollows:
<!DOCTYPEhtml>
<html>
<head>
<title></title>
</head>
<body>
<scriptsrc="bower_components/angular/angular.js">
</script>
<script
src="bower_components/angular-route/angular-route.js"></script>
</body>
</html>
DefiningdirectionsAroutespecifiesaspecificlocationandexpectsaresult.FromanAngularJSperspective,theroutesmustfirstbespecifiedandthenassociatedtocertainelementswithinthem.
ConfiguringngRoute
InordertouseAngularJSroutes,wefirstneedtobringngRouteinasadependencyintotheapplication.Inapp/flipFlop.js,modifythecodetobringinngRouteasadependencyandreturnthemodule:
varflipFlop=angular.module('flipFlop',['ngRoute']);
Now,thesecondthingrequiredisweneedtoconfiguretheroutesthatweneed.Inourcase,weneedtworoutes:oneforviewAandoneforviewB.Therouteconfigurationwillthenlookasfollows:
flipFlop.config(['$routeProvider',function($routeProvider){
$routeProvider
.when('/view/a',{
templateUrl:'app/viewA.html',
controller:'ViewAController'
})
.when('/view/b',{
templateUrl:'app/viewB.html',
controller:'ViewBController'
})
.otherwise({
redirectTo:'/view/a'
});
www.it-ebooks.info
![Page 156: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/156.jpg)
}]);
Arouteisdefinedusingwhen,whichhasafirstargumentasastringforthefullroute.Thesecondargumentisanobject,whichtakestheHTMLpagefortheroute(templateURL)andthecontrollerfortheroute(controller).
Definingtheroutecontrollers
Forbothroutes,createanemptycontrollersothatitcanbeaplaceholderforthefuturecontroller.Herearethestepsyouneedtofollowtodefineroutecontrollers:
1. CreateanewfilefortheViewAcontroller(/app/ViewAController.js):
angular.module('flipFlop')
.controller('ViewAController',['$scope',function($scope){
}]);
2. CreateanothernewfilefortheViewBcontroller(/app/ViewBController.js):
angular.module('flipFlop')
.controller('ViewBController',['$scope',function($scope){
}]);
3. Addthetwocontrollerstotheindex.htmlpage:
<scriptsrc="app/viewAController.js"></script>
<scriptsrc="app/viewBController.js"></script>
Definingtherouteviews
RouteviewsarepartialHTMLelementsthatcanbedynamicallyplacedintoanapplication.Forthetwoviewswerequire,wewillputabasicdivtagforeachview,asshowninthefollowingsteps:
1. Createanewfileforapp/viewA.html:
<divid="viewA"></div>
2. Createanewfileforapp/viewB.html:
<divid="viewB"></div>
Thelastthingrequiredistoputaplaceholderwheretherouteviewwillbeplacedintheindex.htmlpage:
<divng-view></div>
Now,theroutesaresetupwiththeinitialviewsandcontrollers.WecancontinuewiththeProtractortest.
AssemblingtheflipfloptestFollowingthefirstofthe3A’s,Assemble,thefollowingstepswillshowyouhowtoassemblethetest.
www.it-ebooks.info
![Page 157: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/157.jpg)
1. StartwiththeProtractorbasetemplate:
describe('GivenaviewAthathasasinglebutton',function(){
describe('Whenthebuttonispushed',function(){
beforeEach(function(){
})
it(''shouldbeswitchedtoviewB'',function(){
})
})
})
2. Navigatetotherootoftheapplicationusingthefollowingcode:
browser.get('/index.html');
3. ThebeforeEachmethodneedstoconfirmthatthecorrectviewisbeingdisplayed.ThiscanbedoneusingaCSSlocatortolookforthedivtagofviewA.Theexpectationwilllookasfollows:
varviewA=element(by.css('#viewA'));
expect(viewA.isPresent()).toBeTruthy();
4. Then,addanexpectationthatviewBisnotvisible:
varviewB=element(by.css('#viewB'));
expect(viewB.isPresent()).toBeFalsy();
YouwillnoticehowtheselectionofviewAandviewBisdoneoutsideofthebeforeEachmethod,soitcanbeusedforotherexpectations.
Makingtheviewsflip
Theprecedingtestneedstoconfirmthatwhentheflipbuttonispushed,theviewshouldswitch.Inordertotestthis,youcanusetheby.buttonTextlocator.Hereiswhatitwilllooklike:
varbuttonToPush=element(by.linkText('flip'));
buttonToPush.click();
ThebeforeEachfunctionisnowcompleteandlooksasfollows:
varviewA=element(by.css('#viewA'));
varviewB=element(by.css('#viewB'));
beforeEach(function(){
browser.get('/index.htm');
expect(viewA.isPresent()).toBeTruthy();
varbuttonToPush=element(by.linkText('flip'));
buttonToPush.click();
})
Now,youcanaddtheassertion.
Assertingaflip
TheassertionwillagainuseProtractor’sCSSlocatortofindthatviewBisavailable:
www.it-ebooks.info
![Page 158: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/158.jpg)
it('shouldbeswitchedtoviewB',function(){
expect(viewB.isPresent()).toBeTruthy();
})
YoualsoneedtoconfirmthatviewAisnolongeravailable.AddtheexpectationthatviewAshouldnotexist:
it('shouldnotdisplayviewA',function(){
expect(viewA.isPresent()).toBeFalsy();
})
Thetesthasnowbeenassembled.
MakingflipfloprunNow,youwillseethestepsrequiredtomaketheflipfloprun:
1. Inanewconsolewindow,starthttp-server:
$./node_modules/http-server/bin/http-server-p8080
2. RunProtractor:
$./node_modules/protractor/bin/protractorprotractorConf.js
3. ThefirsterrorstatesError:Angularcouldnotbefoundonthepagehttp://localhost:8080/:angularneverprovidedresumeBootstrap.Whenyougetthiserror,proceedwiththefollowingsteps:
1. ThiserrormeansthatnoAngularJSapplicationhasbeenassociatedwiththeapplication.It’snowtimetocreatetheapplicationmoduleandaddittothepage.
2. Createanewfilenamed/app/flipFlop.js:
angular.module('flipFlop',[]);
3. Addthenewmoduletotheindex.htmlpage:
<scriptsrc="app/flipFlop.js"></script>
4. AddtheAngularJSapplicationidentifiertothepage:
<bodyng-app='flipFlop'>
5. ReruntheProtractortest.
4. TheerrorisError:Noelementfoundusinglocator:by.linkText("flip").Torectifythisperformthefollowingsteps:
1. Openuptheapp/viewA.htmlfileandaddalinktotheViewBroutewiththefliptext:
<divid="viewA">
<ahref="#/view/b">flip</button>
</div>
www.it-ebooks.info
![Page 159: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/159.jpg)
2. Rerunthetest.
5. TheProtractortestsnowpass.
MakingflipflopbetterForpractice,youshouldaddalinktoswitchbacktoviewAfromviewB.Thereisnothingthathasbeencalledoutthatneedstobechangedorrefactored.Themaintakeawayfromthiswalk-throughishowtouseProtractortotestroutes.Herearesomescreenshotsoftheapplication:
Theinitialindexpageisshowninthefollowingscreenshot:
Thefollowingiswhatyou’llseeaftertheviewhasbeenswitched:
www.it-ebooks.info
![Page 160: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/160.jpg)
SearchingtheTDDwayThiswalk-throughwillshowyouhowtobuildasimplesearchapplication.Thewalk-throughhastwocomponents.Thefirstdiscussesasearchquerycomponent.Thesecondusesroutestodisplaysearchresultdetails.
www.it-ebooks.info
![Page 161: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/161.jpg)
DecidingontheapproachThiswalk-throughusesthetop-downTDDapproach.Itstartswithwritingfailingtests,fromtheUIpointofviewusingProtractor,andthenworkingthroughtheapplicationwithacombinationofunitandend-to-endtests.
www.it-ebooks.info
![Page 162: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/162.jpg)
Walk-throughofsearchqueryTheapplicationbeingbuiltisasearchapplication.Thefirststepistosetupthesearchareawithsearchresults.ImagineIamperformingasearch.Thefollowingactionswilloccur:
AsearchqueryistypedinResultsaredisplayedontheleftsidebar
Thispieceoftheapplicationisverysimilartothetest,layout,andapproachyousawinChapter4,FirstSteps.Theapplicationwillneedtouseaninput,respondtoaclick,andconfirmtheresultingdata.Sincethetestsandcodeusethesamefunctionalityasthepreviousexample,itisnotworthprovidingacompletewalk-throughofthesearchfunctionality.Instead,thefollowingsectionwillshowtheresultingcodewithafewexplanations.
www.it-ebooks.info
![Page 163: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/163.jpg)
ThesearchquerytestThefollowingcoderepresentsthetestforthesearchqueryfunctionality:
describe('',function(){
//StorethesearchResultforuseinthetest
varsearchResult=null;
beforeEach(function(){
//ASSEMBLE
browser.get('/index.html');
varsearchResult=element.all(by.repeater('resultinresults'));
expect(searchResult.count()).toBe(0);
//ACT
varsearchQueryInput=$('input');
searchQueryInput.sendKeys('anyvalue');
varsearchButton=element(by.buttonText('search'));
searchButton.click();
});
//Assert
it('',function(){
expect(searchResult.count()).toBe(1);
});
});
Youshouldnoticeaparalleltoprevioustests.Thefunctionalityiswrittentomirrorthebehaviorofausertypinginthesearchbox.Thetestfindstheinputfield,typesavalue,andthenselectsthebuttonthatsaysSearch.Theassertionconfirmsthattheresultcontainsasinglevalue.ThenextsectionwilllookattheapplicationfromtheHTMLpage.
www.it-ebooks.info
![Page 164: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/164.jpg)
ThesearchqueryHTMLpageThefollowingcodeshowstheresultingbodyofthesearchqueryHTMLpage:
<bodyng-app="search">
<divng-controller="SearchController">
<inputtype="text"ng-model="searchQuery"></input>
<buttonng-click="search(searchQuery)">search</button>
<ul>
<ling-repeat="resultinresults">{{result}}</li>
</ul>
</div>
<scriptsrc="bower_components/angular/angular.js"></script>
<scriptsrc="app/search.js"></script>
<scriptsrc="app/searchController.js"></script>
</body>
ThemainhighlightsoftheHTMLpageare:
TheuseofthesearchControllerclass’modeltostorethesearchQueryclassintheinput:
<inputtype="text"ng-model="searchQuery"></input>
AssociatingthebuttonclickeventtothesearchController'ssearchfunction:
<buttonng-click="search(searchQuery)">search</button>
ThenextsectionwillshowtheresultingsearchmoduleandsearchController.
www.it-ebooks.info
![Page 165: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/165.jpg)
ThesearchapplicationHereistheresultofthesearchModulecode:
varsearchModule=angular.module('search',[]);
HereistheresultofthesearchControllercode:
angular.module('search')
.controller('SearchController',['$scope',function($scope){
$scope.results=[];
$scope.search=function(){
$scope.results=['AnyValue'];
};
}]);
TheprecedingAngularJScomponentsaresimilartowhathasalreadybeenshowninpreviouschapters.Nowthatyouhavereviewedtheexistingsearchpieceoftheapplication,youcanwalkthroughthestepstodisplaysearchresultdetailviews.Hereiswhatthesearchapplicationlookslikesofar:
www.it-ebooks.info
![Page 166: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/166.jpg)
Showmesomeresults!NowthattheSearchbuttonissetwiththerequiredfeatures,theresultingdetailsneedtobedisplayedwhenasearchresultisselected.Hereistheuserspecification.Giventhefollowingsearchresults:
IselectanitemfromthesearchresultsIwillseethedetailsinthemainpagecomponent
Followingthetop-downapproach,thefirststepwillbetheProtractortestsfollowedbythenecessarystepstogettheapplicationfullyfunctional.
www.it-ebooks.info
![Page 167: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/167.jpg)
CreatingthesearchresultroutesThisapplicationwilluseroutestoswitchbetweenviews.Asthisstepisprimarilyaboutconfiguration,itdoesn’tmakesensetowaituntilatestfails.Thefollowingstepswillbrieflyrecapthenecessarysteps,asyouhavealreadywalkedthroughthestepswiththeflipflopapplication:
1. Installangular-routesusingBower:
$bowerinstallangular-route
2. Addangularandangular-routetotheindex.htmlpage:
<scriptsrc="bower_components/angular/angular.js"></script>
<scriptsrc="bower_components/angular-route/angular-route.js"></script>
3. CreateangRoutemoduleasadependencyintheapplication(app/search.js):
varsearchModule=angular.module('search',['ngRoute']);
4. Configuretheroutesintheapp/search.jsfile.Addthefollowingrouteconfiguration:
searchModule.config(['$routeProvider',function($routeProvider){
$routeProvider
.when('/splash',{
templateUrl:'app/splash.html',
controller:'SplashController'
})
.when('/detail/:id',{
templateUrl:'app/searchDetail.html',
controller:'SearchDetailController'
})
.otherwise({
redirectTo:'/splash'
});
}]);
Theprecedingconfigurationcontainstworoutes.Oneforasplashscreen/landingpagethatwillbedisplayedwhentheuserfirstcomestothepage.Thesecondistheroutetogetthesearchdetails.
5. Addtheroutestubcontrollers:
1. CreateanewfileforSplashController(app/splashController.js):
angular.module('search')
.controller('SplashController',['$scope',function($scope){
}]);
2. CreateanewfileforSearchDetailController(app/searchDetailController.js):
angular.module('search')
.controller('SearchDetailController',['$scope',function($scope){
www.it-ebooks.info
![Page 168: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/168.jpg)
}]);
6. Addthedetailcontrollertotheindex.htmlpage:
<scriptsrc="app/searchDetailController.js"></script>
7. CreatethepartialviewHTMLfilesbyfollowingthesesteps:
1. Createanewfileforsplash.html:
<divid="splash"></div>
2. CreateanewfileforsearchDetail.html:
<divid="searchResultDetail"></div>
Theroutesforthetesthavenowbeencreated.Youcancontinuetothenextstepandbeginaddingthefunctionalitytolinksearchresultstotheresultdetails.
www.it-ebooks.info
![Page 169: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/169.jpg)
TestingthesearchresultsAsthespecificationstates,youwillneedtoleveragetheexistingsearchresults.Insteadofcreatingatestfromscratch,youcanaddtotheexistingsearchquerytest.Startwithabasetestembeddedinthesearchquerytestasfollows:
describe('GivenIamsearching',function(){
describe(''whenItypeinasearchquery'',function(){
...
describe('Givensearchresults',function(){
describe('WhenIselectanitemfromthesearchresults',function(){
beforeEach(function(){
});
it('shouldseethedetailsinthemainpagecomponent',function(){
});
});
});
})
})
Nowmoveontothenextstepandbuildthetest.
AssemblingthesearchresulttestInthiscase,thesearchresultsarealreadyavailablefromthesearchquerytest.Youdon’thavetoaddanymoresetupstepforthetest.
SelectingasearchresultTheobjectundertestistheresult.Thetestiswhentheresultisselectedandthentheapplicationmustdosomething.ThestepstowritethisinProtractorareasfollows:
1. Findaresultitemusingthefollowingcode:
varresultItem=element(by.repeater('resultinresults')).first();
2. Selecttheresultitem.Asyouwillberepresentingthedetailsusingaroute,youwillcreatealinktothedetailspageandclickonthelink.Herearethestepstocreatealink:
1. Selectthelinkwithintheresultitem.Thisusestheelementcurrentlyselectedandthenfindsanysubelementsthatmeetthecriteria.Thecodeforthisisasfollows:
varresultLink=resultItem.element(by.css('a'));
2. Nowtoselectthelinkaddthefollowingcode:
resultLink.click();
Confirmingasearchresult
www.it-ebooks.info
![Page 170: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/170.jpg)
Nowthatthesearchitemhasbeenselected,youwillneedtoverifythattheresultdetailspageisvisible.Thesimplestsolutionatthispointistoensurethatthedetailsviewisvisible.ThiscanbedoneusingProtractor’sCSSlocatortolookforthesearchdetailview.Thefollowingisthecodetobeaddedforconfirmingasearchresult:
it('Shouldseethedetailsinthemainpagecomponent',function(){
varresultDetail=element(by.css('#searchResultDetail'))
expect(resultDetail.isDisplayed()).toBeTruthy();
})
Hereisthecompletetest:
...
describe('WhenIselectanitemfromthesearchresults',function(){
beforeEach(function(){
varresultItem=element.all(by.repeater('resultinresults')).first();
varresultLink=resultItem.element(by.css('a'));
resultLink.click();
});
it('Shouldseethedetailsinthemainpagecomponent',function(){
varresultDetail=element(by.css('#searchResultDetail'))
expect(resultDetail.isDisplayed()).toBeTruthy();
});
});
Nowthatthetestissetup,youcancontinuetothenextphaseofthelifecycleandmakeitrun.
www.it-ebooks.info
![Page 171: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/171.jpg)
MakingthesearchresulttestrunForthisstepofthelifecycle,wewillexecuteProtractorandmakefixesintheapplicationinordertomakethetestrunsuccessfully.Herearethestepsyouneedtofollow:
1. Thefirsterror:Error:Noelementfoundusinglocator:by.cssSelector('a')
Weneedtoaddalinktotheresultitemlist,whichwillpointtothedetailsoftheresult.IntermsofAngularroutes,wewilladd#/detail/:resultIdasaprefix:
<ling-repeat="resultinresults"><ahref="#/detail/{{result.id}}">
{{result.name}}</a></li>
2. NowrerunthetestandwegetUnknownError:unknownerror:Elementisnotclickableatpoint(48,57).Otherelementwouldreceivetheclick:....
Thiserrorisnotasclear.Whenthishappens,andtheerrorisnotasspecificasrequired,youcanjumptothesiteitselfandlookattheJavaScriptconsoleforerrors.Gotohttp://localhost:8080.Hereisascreenshotofwhatyoushouldsee:
Themainproblemisthatthelinkisnotonthepage.Lookingbackatthecode,youcanseethatthesearchresultobjectisanarrayofstringsbutitneedstobeanarrayofobjectsthathaveanIDandname.Updatetheapp/searchController.jssearchfunctionasfollows:
$scope.search=function(){
$scope.results=[{id:1,name:'AnyValue'}];
};
Nowrerunthetest.
3. Therouteshavenowbeenconfiguredtothenewroute(#/detail/{{result.id}})andthetestsnowpass.
www.it-ebooks.info
![Page 173: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/173.jpg)
Creatingalocation-awaretestAstheapplicationusesroutes,theroutedetailviewwillneedtobetested.Inthiscase,youwillneedtoensuretheURLhastheIDofthesearchresult.Followthesestepstoaddthetest:
1. InthebeforeEachmethod,retrievetheIDofthesearchresultbasedonhrefofthelinkattribute:
varresultId=null;
beforeEach(function(){
…
resultId=resultLink.getAttribute('href').then(function(attr){
returnattr.match(/#\/detail\/(\d+)/)[1];
});
});
2. ResolvetheresultIdpromisecontainingtheIDoftheresult:
it('Shouldsettheurltotheselecteddetailview',function(){
resultId.then(function(id){
3. Withinthepromise,createexpectedUrl:
varexpectedUrl='/detail/'+id;
4. GetthelocationoftheURL:
browser.getLocationAbsUrl()
5. UsethepromisetochecktheexpectationontheURL:
.then(function(url){
expect(url.split('#')[1]).toBe(expectedUrl);
});
});
Location-awaretestscanbeveryhelpfulwhendealingwithroutes.Thetestscanbesimpleorcomplex,buthelpaligntherouteinterfacetoclearspecifications.
www.it-ebooks.info
![Page 174: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/174.jpg)
MakingthesearchresultbetterNowthatthereisapassingtest,somecleanupandrefactoringisneeded.Therearetwoprimarycallouts:
Nounittests.HowdoyouknowsearchResultDetailisspecifictothesearchresultweselect?
Uptothispoint,therehasn’tbeenaneedtocreateunitteststobuildtheapplication.ThefocushasbeenontheUIintheapplication.Therehasn’tbeenlogicoractionsneededtobuildonthebackend.Mostofthedevelopmenthasbeenfocusedonwiringupthefrontendandmakingsurethecomponentsinthespecificationareavailabletotheuser.
Theotheractionthatyouneedtolookatisthefactthatthereisnotawaytotestthataloadedviewactuallyreflectsdatafromtheselectedresult.Thiscanbetackledintwoparts.ThefirstpartistoensurethattheURLforthewindowpointstothecorrectroute.ThesecondpartwillbetodisplaytheIDnumberofthesearchresultontheview.
ConfirmingtherouteIDTheIDwillnotbedisplayedtotheusers;however,itisstillanintegralpartoftheapplication.Astheapplicationgrowsinthefollowingchapters,youwillbeleveragingtheIDtoextractfurtherdata.Thiswalk-throughwillfollowtheTDDlifecycleanduseKarmatobuildthefeature.
SettinguptherouteIDunittest
Toinjectthescopeintoacontroller,theinitialtestwilllookasfollows:
describe('',function(){
varscope={};
beforeEach(function(){
module('search');
inject(function($controller){
$controller('SearchController',{$scope:scope});
});
});
it('',function(){});
});
Inordertotesttheroutes,thetestwillleveragethe$routeParamsobject.The$routeParamsobjectgivesanobjectaccesstoinformationrelatingtotheroutethatbroughttheapplicationtothelocation.Forexample,the/detail/:idroutedefinitionandthe/detail/123,$routeParamsroutewillgiveyouthe{id:123}object.Forthetest,afake$routeParamsobjectcontainingtheIDofthedetailobjectwillbeused.Updatethetestsothatithasthefollowingfake$routeParamsobject,whichwillreturnanIDof1:
beforeEach(function(){
//...
varrouteParams={id:1};
$controller('SearchDetailController',{$scope:scope,$routeParams:
routeParams});
www.it-ebooks.info
![Page 175: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/175.jpg)
Nowthatthefake$routeParamsobjecthasbeeninjectedintothecontroller,youcancontinuetothenextphaseandmaketheassertion.
ConfirmingtheID
TheassertionisthatthescopehasadetailobjectwiththesameIDthat$routeParamsspecified.ThecodeforconfirmingtheIDisasfollow:
it('Shouldreturnresults',function(){
expect(scope.detail.id).toBe(1);
});
Makingtherouteparameter’stestrun
NowthatKarmaisrunningusingaheadlessbrowser,wecanstartKarmaintheconsoleandletitrunaswewalkthroughtheissues,asshowninthefollowingsteps:
1. StartKarma:
$karmastart
2. ThefirstissuewegetisthatngRoutecan’tbefound.Thisisbecauseweaddedangular-routetotheproject,buthaven’taddedittokarma.conf.Updatethekarma.confupdatethefilessectionwiththefollowingcode:
files:[
//...
'bower_components/angular-route/angular-route.js',
3. Afterrerunningthetest,weareleftwithTypeError:''undefined''isnotanobject(evaluatingscope.detail.id).Torectifythis,performthefollowingsteps:
1. Thiserrorinformsusthatthescope.detail.idobjectdoesn’texistinthecontroller.Wewillnowupdatethecontrollertoincludeit.Thefirststeptofixingthisistoadd$routeParamstosearchDetailController:
.controller('SearchDetailController',
['$scope','$routeParams',function($scope,$routeParams){
2. Now,inthecontroller,createthedetailobjectwiththe$routeParamsID:
$scope.detail={id:$routeParams.id};
3. ThedetailobjecthasnowbeencreatedusingtheIDoftheroute.Goaheadandrerunthetest.
Thetestpasses!
Theapplicationnowlookslikewhatisshowninthefollowingscreenshotwhenyoufirstopenit:
www.it-ebooks.info
![Page 176: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/176.jpg)
Afterasearchquery,theapplicationlookslikewhatisshowninthefollowingscreenshot:
Fordetailsoftheapplicationlooksasshowninthefollowingscreenshot(noticethattheURLcontainsthedetailroute):
www.it-ebooks.info
![Page 177: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/177.jpg)
Self-testquestionsQ1.GiventhefollowingHTMLcode,howwouldyouselectthesecondlistitem?
<ul>
<li>item1</li>
<li>item2</li>
</ul>
1. element.all(by.css('li')).second();.2. element(by.repeater('iteminlist'))[1];.3. element.all(by.css('li')).get(1);.
Q2.GiventhefollowingAngularJScomponent,howwouldyouselecttheelementandsimulateaclick?
<ahref="#">SomeLink</a>
1. $('a').click();.2. element(by.css('li)).click();.3. element(by.linkText('SomeLink')).click();.
Q3.WhenusingrouteswithAngularJSyouneedtoinstallangular-route.
1. True.2. False.
www.it-ebooks.info
![Page 178: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/178.jpg)
SummaryThischapterhasshownyouhowtouseTDDtobuildanAngularJSapplication.Theapproach,uptothispoint,hasfocusedonthespecificationfromauserperspectiveandusingTDDfromtop-downapproach.Thistechniquehelpsyougetusable,smallcomponentstestedandcompletedfortheusers.Asapplicationsgrow,sodoestheircomplexity.Aswemoveontothenextchapter,wewillexplorethebottom-upapproachandseewhentousethattechniqueoveratop-downapproach.
ThischapterhasshownyouhowTDDcanbeusedtodeveloproute-basedviews.Thisincludesutilizingmultiplecontrollersandviews.Routesallowyoutogetaniceseparationofyourcomponentsandviews.WehaveshowntheusageofseveralProtractorlocators,fromCSS,torepeaters,tolinktext,toinnerlocators.BesidesusingProtractor,wehavealsolearnedhowtoconfigureKarmawithaheadlessbrowser,andwegottoseeitinaction.
www.it-ebooks.info
![Page 179: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/179.jpg)
Chapter6.TellingtheWorldThebuildupofTDDfocusedonfundamentalcomponents,namelylifecycleandprocess,usingstep-by-stepwalk-throughs.Youhavetakenseveralapplicationsfromthegroundup,understandinghowtobuildAngularJSapplicationsandusetoolstotestthem.ItistimetoexpandfurtherintothedepthsofAngularJSandintegrateservices,broadcasting,androutes.
Thischapterwillbeslightlydifferentthantheothersintwoways:
Insteadofbuildingabrandnewapplication,wewillusethesearchapplicationfromChapter5,FlipFlop.Also,abottom-upapproachwillbeused.ThisconsistsofcreatingunittestsfirstandthenmovingtotheUI.
www.it-ebooks.info
![Page 180: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/180.jpg)
BeforetheplungeBeforethewalk-through,thecoreconceptsofthechapterwillbereviewedfirst.Itisimportantthatyouunderstandtheseconceptsbeforeyoumoveontothewalk-through.
www.it-ebooks.info
![Page 181: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/181.jpg)
KarmaconfigurationSofar,thedefaultKarmaconfigurationhasbeenused,butnoexplanationonthedefaultconfigurationhasbeengivenyet.Filewatchingisausefuldefaultbehaviorthatwillnowbereviewed.
FilewatchingFilewatchingisenabledbydefaultwhenthekarmainitcommandisused.FilewatchinginKarmaisconfiguredwiththefollowingdefinitioninthekarma.conf.jsfile:
autoWatch:true,
Thefilewatchingfeatureworksasexpectedandwatchesthefilesdefinedintheconfiguration’sfilesarray.Whenafileisupdated,changed,ordeleted,Karmawillrespondbyrerunningthetests.FromaTDDperspective,thisisagreatfeatureastestswillcontinuetorunwithoutanymanualintervention.
Themainpointtowatchoutforistheadditionoffiles.Ifthefilebeingaddeddoesn’tmatchthecriteriainthefilesarray,theautoWatchparameterwon’trespondtothechange.Asanexample,let’sconsiderthatthefilesaredefinedasfollows:
files:['dir1/**/*.js']
Ifthisisthecase,thewatcherwillfindallthefilesandsubdirectoryfilesendingin.js.Ifanewfileisinadifferentdirectory,notindir1,thenthewatcherwillnotbeabletorespondtothenewfilebecauseitisinadifferentdirectorythanwhatitwasconfiguredin.
www.it-ebooks.info
![Page 182: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/182.jpg)
Usingabottom-upapproachThetop-downapproachofTDDcanbeveryuseful.Ithelpsfocusonuser-facingcomponentsfirstandthenfillsupthebackendlayer.Oneofthecaveatstothisapproachisthatthespecificationbeingbuiltismoreuserfacingasopposedtoitbeingbasedonlogic.Thebottom-upapproachbuildsfromtheinnercomponentsouttotheUIandtheuser.Thiskindofapproachisextremelyimportantwhenworkingwithcomplicatedlogicandrequirements.Withthebottom-upapproach,youwillfirstbuildservices,controllers,anddirectiveswithallthecomplexitiesusingunittestsandKarma.Afterthis,youwillexpandtocreateend-to-endtestswithProtractor.
www.it-ebooks.info
![Page 183: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/183.jpg)
ServicesAngularJSservices,factories,andresourcesareallimportantcomponents.Servicesareusedtoabstractapplicationlogic.Theyareusedtoprovidesingleresponsibilityforaparticularaction.Singleresponsibilityallowscomponentstobeeasilytestedandchanged.Thisisbecausethefocusisononecomponentandnotalltheinnerdependencies.
HereisasummaryofsomeoftheotherAngularJScomponentsthathavebeenlookedatsofar:
Attributesanddirectives:ThesedriveactionsandflowfromtheUIControllers:ThisprovidesthegluebetweentheUIandlogicServices:Thisisolatesthelogic
www.it-ebooks.info
![Page 184: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/184.jpg)
PublishingandsubscribingmessagesOneofthegreatfeaturesofAngularJSisitsabilitytopublishandsubscribemessageswithinapage.Publishingandsubscribingmessagesisapowerfulcomponent,butlikewithanything,whenusedthewrongway,itcanleadtoamess.
Oneareawherethispatternisusefuliswhencommunicatingacrossboundariesinanapplication.ApplicationboundariesareimportantastheyallowtheUItohaveisolatedcode.ComplexityoccurswhenseparateUIcomponentsneedtobeawareofchangesinotherareasoftheUI.Withapublishingandsubscriptionmodel,applicationscancommunicateseamlesslyusingmessages.Thischapterwillfocusonpublishingandsubscribing.Youwillbeabletotakeacloserlookatwhatboundariesareanddeterminegoodplacestoleveragethisfeatureinyourownapplications.
Therearetwowaysinwhichmessagescanbepublished.Youcaneitheremitorbroadcast.Itisimportanttoknowthedifferenceasbothworkslightlydifferently,andtheymayaffecttheperformanceofyourapplication.
EmittingOnewaytopublisheventsistoemitthem.Thedocumentationathttps://docs.angularjs.org/api/ng/type/$rootScope.Scopegivesthefunctionalityofthe$emit()methodasfollows:
Dispatchesaneventnameupwardsthroughthescopehierarchynotifyingtheregistered$rootScope.Scopelisteners.
Theimportantthingtonoteis$emit()notifiesupthroughthescopesallthewaytothetopofthehierarchy.Thisisimportantbecauseifyouhaveanembeddedcontrollerscope,itisgoingtohavetopropagateallthewayuptoeverycontrollerandscope.Thiscancauseaperformanceissue.Hereisanexampleofhowtoemitanevent:
$scope.someAction=function(){
$scope.$emit('ANYEVENT');
};
Thebestwaytoseetheupwardpropagationoftheeventisthroughatest.Thenextsectionwillshowyouhowtounittesttheupwardeffectof$emit().
Testingemit
Thefollowingtestshavethreecontrollers:TopController,MiddleController,andBottomController.MiddleControllerwillemittheevent.Fromthis,anexpectationcanbemadethatTopControllerwillreceivetheeventandBottomControllerwon’t,astheemissionpropagatesinanupwardfashion.Herearethestepstotestthe$emit()method:
1. Createspiestotesttheemissionofevents:
vartopEventSpy=jasmine.createSpy();
varbottomEventSpy=jasmine.createSpy();
www.it-ebooks.info
![Page 185: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/185.jpg)
2. Thetestsetupfirstsetsthehierarchyofscopes:
inject(function($controller,$rootscope){
vartopScope=$rootscope.$new();
varmiddleScope=topScope.$new();
varbottomScope=middleScope.$new();
3. Thenthecontrollersaresetwiththeirrespectivescopes:
$controller('TopController',{$scope:topScope});
$controller('MiddleController',{$scope:middleScope});
$controller('BottomController',{$scope:bottomScope});
4. Setthespytocapturetheevents:
topScope.$on('MIDDLEEMIT',topEventSpy);
bottomScope.$on('MIDDLEEMIT',bottomEventSpy);
5. Emittheeventfromthemiddlescope:
middleScope.$emit('MIDDLEEMIT');
6. Addtheexpectationthatthetopspywascalledontheevents:
it('Shouldnotifytopcontroller',function(){
expect(topEventSpy.wasCalled).toBe(true);
});
7. Addtheexpectationthatthebottomspywasnotcalled:
it('Shouldnotnotifybottomcontroller',function(){
expect(bottomEventSpy.wasCalled).toBe(false);
});
Hereareacoupleofthingstonotefromtheprecedingtest:
ThisisaunittestthatwewillruninKarma.Theinjectmethodprovidesareferencetothe$controllerand$rootscopescopes.The$rootscopescopeisthetopmostscopeofanAngularJSapplication.Ifyou’reusing$rootscopetoemitevents,theywouldn’tneedtopropagateanymoreas$rootscopeisatthehighestlevel.Inthelaterexamples,$rootscopewillbeinjectedintothecontrollerandusedtolistentoandsendevents.Ascopecancreateanewchildscope.Achildscopeiscreatedusingthe$newmethod.Youcanimaginethistobeequivalenttoapagethathasembeddedcontainers:
<divng-controller="topController"
<divng-controller="middleController">
<divng-controller="bottomController">
</div>
</div>
</div>
Testingbroadcast
www.it-ebooks.info
![Page 186: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/186.jpg)
Thedocumentationathttps://docs.angularjs.org/api/ng/type/$rootScope.Scopestatesgivesthefunctionalityofthe$broadcast()methodasfollows:
Dispatchesaneventnamedownwardstoallchildscopes(andtheirchildren)notifyingtheregistered$rootScope.Scopelisteners.
Asopposedtothe$emitmethod,whichpusheseventsupthroughthescopechain,$broadcastpusheseventsdownthechain.Theotherimportantdistinctiontomakeisthatthe$broadcasteventcan’tbecancelled,but$emitcanbe.Thesearesmallintricaciesthatifnotunderstoodproperlycanhaveanegativeeffectontheapplication.Likewiththe$emitevent,thefollowingexampleshowsthewaybroadcastingworksthroughatest.
Testingbroadcast
Utilizingsimilartechniquesfromtheemissiontest,herearethestepstotestthebroadcastingofevents:
1. Createthespies:
vartopEventSpy=jasmine.createSpy();
varbottomEventSpy=jasmine.createSpy();
2. Initializethescopes:
vartopScope=$rootScope.$new();
varmiddleScope=topScope.$new();
varbottomScope=middleScope.$new();
3. Settherespectivecontrollerscopes:
$controller('TopController',{$scope:topScope});
$controller('MiddleController',{$scope:middleScope});
$controller('BottomController',{$scope:bottomScope});
4. Setthespiestolistenfortheevents:
topScope.$on('MIDDLEEMIT',topEventSpy);
bottomScope.$on('MIDDLEEMIT',bottomEventSpy);
5. BroadcasttheeventfrommiddleScope:
middleScope.$broadcast('MIDDLEEMIT');
6. Havetheexpectationthatthetopscopewasnottouched:
it('Shouldnotnotifytopcontroller',function(){
expect(topEventSpy.wasCalled).toBe(false);
});
7. Havetheexpectationthatthebottomscopereceivedthemessage:
it('Shouldnotifybottomcontroller',function(){
expect(bottomEventSpy.wasCalled).toBe(true);
});
TheprecedingexplanationshaveshowedhowtointegrateandtesttwotypesofAngularJS
www.it-ebooks.info
![Page 187: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/187.jpg)
events.Asyouprogressthroughtherestoftheeventtests,youwillfindthatthesetupandtechniquesusedherewillbeusedthroughouttherestofthechapter.
www.it-ebooks.info
![Page 188: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/188.jpg)
Publishingandsubscribing–thegoodandbadKnowingwhentousepublishingandsubscribingisonething,butknowingwhennottousethemisthedifficultpart.
ThegoodBeforelookingattheproblemsthatpublishingandsubscribingcanleadto,herearesomeofthebestscenarioswhereyoucanusethistechnique:
CommunicatingimportanteventstodifferentcomponentsoftheapplicationReducingcoupling
Communicatingthroughevents
Whenthinkingabouteventsthatneedtobecoupled,itisimportanttothinkaboutwhatactionsaredrivingtheapplication.Givenabankapplication,eventsmightbeassimpleasDEPOSITEDandWITHDREW.Thesetwosimpleeventsmaybeusedinmanyotherplaces.Thinkaboutyouwantingtosendane-mailtothecustomereverytimetheywithdreworautomaticallyupdatedsomereal-timereport.Insteadofpollingthepersistencelayer,areal-timenotificationmessagecanbeused.InAngularJS,thismeansthattheUIcanbemadeupofdifferentcomponentsthatcanrespondtochangesinonearea,forexample,UInotifications,updatingworkflows,enablingfeatures,oranythingyoucanthinkof.
Communicatingeventssothatothercomponentscanrespondtothemiskey.Whenyouwanttoeasilyrespondtoeventsandchanges,publishingandsubmittingisthewaytogo.Thefollowingisanothertesttoshowhowcommunicationcanbeused:
1. Createscopesforthecontrollers:
recentTransactionScope=$rootScope.$new();
atmScope=recentTransactionScope.$new();
2. Assignthescopestothecontrollers:
$controller('AtmController',{$scope:atmScope});
$controller('RecentTransactionsController',
{$scope:recentTransactionScope});
3. Setthespies:
spyOn(atmScope,'$emit').and.callThrough();
spyOn(recentTransactionScope.recent,'push');
4. Callthemethodbeingtested:
atmScope.withdraw(3.33);
5. Settheexpectationthattheeventwasemitted:
it('shouldemitanevent',function(){
expect(atmScope.$emit).toHaveBeenCalled();
});
www.it-ebooks.info
![Page 189: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/189.jpg)
6. Settheexpectationthattherecenttransactionsreceivedtheevent:
it('shouldsendeventtorecenttransactions',function(){
expect(recentTransactionScope.recent.push).toHaveBeenCalled();
});
Herearethecontrollerstofurtherclarifythecode:
1. TheAtmControllerproperty(publisher):
bankModule.controller('AtmController',['$scope',function($scope){
$scope.withdraw=function(amount){
$scope.$emit('WITHDREW',amount);
}
}]);
2. TheRecentTransactionsControllerproperty(subscriber):
bankModule.controller('RecentTransactionsController',['$scope',
function($scope){
$scope.recent=[];
$scope.$on('WITHDREW',function(amount){
$scope.recent.push(amount);
})
}]);
Asdiscussedwiththetests,AtmControlleremitstheWITHDREWeventafterawithdrawaloccurs.
Theprecedingstepsarejustasimpleexampleofhowpublishingandsubscribingcanhelpcommunicateimportantactivitiesacrossyourapplication.
Reducingcoupling
Communicationisoneaspectofthebenefitsofpublishingmessages.Messaginggivesyoudecreasedcoupling.Thinkabouttheprecedingbankapplicationthatcommunicateswhenawithdrawaloccurs.Themessagesmaybeusedformanydifferentaspectsoftheapplication,andsinceitisdecoupled,wedon’tneedtoworry.Ifwethinkaboutitanotherway,thewithdrawfunctiondoesn’tcareabouttherestoftheapplication.Itonlyfocusesonthefactthatitwillperformawithdrawalandthensendamessageuponitscompletion.Fromthesubscriptionperspective,therecenttransactionsdon’tcarewherethewithdrawalhappens.Itonlyhastofocusonwhatitneedstodowhenthishappens.
Decouplingtheapplicationcanbeextremelybeneficialfromatestingperspective.Takeanotherlookatthebankapplicationifyouwanttorefactorandseparateoutthetests.YoucouldcreateanewtestthatisspecifictotheRecentTransactionsproperty.Sincetheapplicationisdecoupled,itdoesn’tcareaboutAtmController.Thetestcanbeseparatedoutasfollows:
1. ThebeforeEachfunctioncanbereducedtoonlydealwiththescopeofrecentTransactionsControllerand$rootScope:
www.it-ebooks.info
![Page 190: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/190.jpg)
varrecentTransactionScope={};
varrootScope={};
beforeEach(function(){
module('bank');
inject(function($controller,$rootScope){
rootScope=$rootScope.$new();
recentTransactionScope=$rootScope.$new();
$controller('RecentTransactionsController',
{$scope:recentTransactionScope});
});
spyOn(recentTransactionScope.recent,'push');
rootScope.$emit('WITHDREW',3);
});
2. InthebeforeEachfunction,addaspytohelpwithtesting:
spyOn(recentTransactionScope.recent,'push');
3. InsteadofcallingtheAtmControllerclass’swithdrawfunction,wecancall$emiton$rootScope:
rootScope.$emit('WITHDREW',3);
4. TheafterEachfunctionandtheexpectationarethesameasshownpreviously:
afterEach(function(){
recentTransactionScope.recent.push.calls.reset();
});
it('shouldsendeventtorecenttransactions',function(){
expect(recentTransactionScope.recent.push).toHaveBeenCalled();
});
Thisexamplehasshownthatusingmessaging,youcandecoupletests.Decouplingapplicationtestsallowstheapplicationtogrowwithouthavingtonegativelyrefactortheentireapplication.Intheprecedingcase,ifAtmControllerischanged,therecentTransactionstestandtherecentTransactionscontrollerwon’tneedtobechanged.AslongastheWITHDREWeventispublished,recentTransactionswillnothavetobeupdated.
www.it-ebooks.info
![Page 191: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/191.jpg)
HarnessingthepowerofeventsPublishingandsubscribingeventscanleadtosomeuglyandhard-to-understandspaghetticode.Nowthatthefoundationsforthechapterhavebeenreviewed,youcandiveintoimplementingeventsintothesearchapplication.
www.it-ebooks.info
![Page 192: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/192.jpg)
TheplanThesearchapplicationfromChapter5,FlipFlop,isquitebasic.Atthispoint,itwillreturnasetofresults,andthenwhentheuserclicksonaresult,detailswillappear.Theapplicationprovidesafoundationforfuturedevelopment.Inthischapter,thefunctionalitywillbeexpandedtoincludepublishingandsubscribing.Hereistheplantoexpandthesearchapplication:
Thesearchapplicationwillberebrandedasastoreapplication,andthesearchresultswilldisplayalistofproducts.Whenaproductisselected,detailswillbedisplayed.Allselectedproductsfromthesearchwillbeavailableinanewviewfor“recentlyviewed”items.Thedetailedviewoftheproductwillhavetheoptionto“addtocart”,andtheproductwillthenbeavailableinthecartview.
Theplanissomewhatambitious,butwithalltheknowledgewehaveonTDDandAngularJS,thedevelopmentshouldflownicely.
www.it-ebooks.info
![Page 193: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/193.jpg)
RebrandingThesearchapplicationwillberebrandedintoastoreapplicationinsteadofrewritingthesearchfunctionalitythathasalreadybeenwritten.Inordertoleveragetheexistingsearchproject,itwillbecopiedintoanewprojectfile.Then,thenewprojectwillusetheteststodrivethedevelopmentchangesandrefactoring.Therefactorstepshavebeenleftout,butareviewofthecodewillshowhowthecodeandtestsweremodifiedtocreatetheproductapplication.
Therefactorstepsupdatedtheunittestsandapplicationtosupportthecorrectnamingfortheapplication.Itisimportanttotakeawaytwothingsfromthis:
Refactorsmalltointroducebigchanges.Smallincrementalchangeshelptoprogressivelygettothenextstageoftheapplication.Whenbigchangesoccur,itcanbeconfusingtoknowwhereandwhattochange.Withsmallchanges,eventhoughthesamecodeisrevisitedseveraltimes,youcanensurethetestspassateachstageinsteadofrippingtheapplicationapartcompletelyandthentryingtoputitallbacktogetheragain.TDDappliesduringrefactoringjustasmuchaswhendoingcoredevelopment.TherefactorstepsfollowedwerethesameastheTDDsteps.Startwithchangingthetesttomeetourspecificationandthenmakethecoderuntomeetthespecification.Applyingtheseprincipleshelpskeepproductivityandfocus.
Boththeunittestsandend-to-endtestspassfromtherefactorsteps.Itistimetoturntothefirstfeatureoftheapplication.
www.it-ebooks.info
![Page 194: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/194.jpg)
SeeingrecentlyvieweditemsNowthattheinitialrefactoringiscomplete,thenewfunctionalityoftheproductapplicationcanbeconsidered.Thefirstspecificationthatwillbeconsideredistheabilitytosee“recentlyviewed”items.Thespecificationisbrokendownintotwosteps,asfollows:
TheuserselectsaproducttoviewthedetailsTheywillbeabletoseetheviewedproducts
Thisisanexampleofwherebroadcastingwouldbeagoodcandidate.Intheprecedingcase,thespecificationisconcernedwithwhenaproducthasbeenselected.Inotherwords,whenaneventoccurs,asubsequentactionneedstohappen.UsingAngularJSevents($broadcast()/$emit()),theeventofselectingaproducttoviewcanbepublishedandthenconsumedbytherecentlyviewedcomponent.
ThestandardTDDlifecyclewillbeusedtobuildthiscomponent:testfirst,makeitrun,makeitbetter.Wewillbeusingabottom-upapproach(unittestfirst).Themainreasonforchoosingthisapproachisthattherearemultiplecontrollersinvolved,anditwillbeeasiertostartatthebottomandmakeourwayupthroughtheapplication.
TestfirstThefirsttestwewillbewritingisthattheSearchControllerclasswillpublishaneventwhenaproductisselected.Thefollowingsectionsdetailhowtowritethetest.
AssemblingSearchController
HerearethestepstoassembletheSearchControllerclass:
1. Startwiththeteststubusingthefollowingcode:
describe('',function(){
beforeEach(function(){
});
it(function(){
});
});
2. GetthescopeofSearchControllersothatanactioncanbeperformed:
describe('',function(){
beforeEach(function(){
module('product');
inject(function($controller,$rootScope){
varsearchControllerScope=$rootScope.$new();
$controller('SearchController',{$scope:searchControllerScope});
});
});
it(function(){
});
});
www.it-ebooks.info
![Page 195: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/195.jpg)
3. PlaceaspyontheSELECTEDPRODUCTevent:
varselectedProductSpy=jasmine.createSpy();
varsearchControllerScope={};
beforeEach(function(){
module('product');
inject(function($controller,$rootScope){
searchControllerScope=$rootScope.$new();
$controller('SearchController',
{$scope:searchControllerScope,$rootscope});
searchControllerScope.$on('SELECTEDPRODUCT',selectedProductSpy);
});
})
4. Addacleanupfunctiontoclearthescopeaftereachtestandclearthespy:
afterEach(function(){
searchControllerScope={};
selectedProductSpy.reset();
});
Selectingaproduct
ThetestrequiresthataSELECTEDPRODUCTeventhasbeenpublished.TheeventwilloccurwhentheselectedproductmethodiscalledwithproductId:
varfakeProduct={productId:1};
searchControllerScope.selectProduct(fakeProduct);
Expectingeventstobepublished
TheexpectationisthatselectedProductSpyhasbeencalled:
it('',function(){
expect(selectedProductSpy).toHaveBeenCalled();
});
MakingthesearchcontrollerrunNowwehavetomakethetestpassandrun.Herearethesteps:
1. StartKarmausingthefollowingcommand:
$karmastart
2. You’llgetanerror,namelyTypeError:'undefined'isnotafunction(evaluating'searchControllerScope.selectProduct(fakeProduct)').Torectifythis,performthefollowingstep:
1. AddthemethodtoSearchController:
$scope.selectProduct=function(){};
3. Thenyou’llgettheerrorExpectedspyunknowntohavebeencalled.Error:Expectedspyunknowntohavebeencalled.Torectifythis,performthe
www.it-ebooks.info
![Page 196: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/196.jpg)
followingsteps:
1. Theexpectationhasfailed,whichmeansthespywasnevercalled.OpenupSearchControllerandaddfunctionalitytotheselectProductmethodtoemitanevent:
$scope.selectProduct=function(productId){
$rootScope.$broadcast('SELECTEDPRODUCT',productId);
};
2. Rerunthetest.
4. Thetestwillpass.
Nowwhenaproductisselected,theeventisbroadcasted.Anyfunctionwantingtoknowwhensomethinggetsselectedcansimplylistenforthebroadcast.
RecentlyviewedunittestThenextstepistoaddanothertestfromthesubscriptionsideoftheeventtoRecentlyViewedController.
Testfirst
Again,thewalk-throughoftheteststepswillusethe3A’s.
AssemblingRecentlyViewedController
HerearethestepstoassembleRecentlyViewedController:
1. Startwiththeteststubusingthefollowingcode:
describe('',function(){
beforeEach(function(){
});
it(function(){
});
});
2. GetthescopeofRecentlyViewedControllersothatanactioncanbeperformed:
describe('',function(){
beforeEach(function(){
module('product');
inject(function($controller,$rootScope){
varrecentlyViewedScope=$rootScope.$new();
$controller('RecentlyViewedController',
{$scope:recentlyViewedScope});
});
});
it(function(){
});
});
3. Confirmthatthenumberofrecentlyviewedproductsisequalto0:
www.it-ebooks.info
![Page 197: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/197.jpg)
expect(recentlyViewedScope.recent.length).toBe(0);
Invokingarecentlyvieweditem
TheactionforthistestisthattheSELECTEDPRODUCTeventhasbeenpublished.Nowaddthepublishevent:
varfakeProductEvent={productId:1};
$rootscope.$broadcast('SELECTEDPRODUCT',fakeProductEvent);
ConfirmingRecentlyViewedController
Theassertionisthatthenumberofrecentlyviewedproductsisnowequalto1:
it('',function(){
expect(recentlyViewedScope.recent.length).toBe(1);
});
MakingRecentlyViewedControllerrunHerearethestepstorunRecentlyViewedController:
1. StartKarmausingthefollowingcommand:
$karmastart
2. You’llgetanerror,namelyError:[ng:areq]Argument'RecentlyViewedController'isnotafunction,gotundefined.Torectifythiserror,performthefollowingsteps:
1. CreatetherequiredcontrollerandcreateanewfilenamedRecentlyViewedController.js.
2. Then,addthefollowingdetails:
angular.module('product')
.controller('RecentlyViewedController',['$scope',function($scope){
}]);
3. Rerunthetest.
3. Thenyou’llgettheerrorTypeError:'undefined'isnotanobject(evaluating'recentlyViewedScoperecent.length'),whichmeansthatthefirstexpectation,thatistherecentproduct0,hasbeenhit.Astheobjectisundefined,addittotherecentlyViewedScopescope.
4. Thenyou’llgettheerrorExpected0tobe1.Error:Expected0tobe1.Torectifythis,performthefollowingsteps:
1. Theexpectationhasbeenhit.Nowthebehavioroftheeventneedstobeaddedtothecontroller.
2. Add$rootScopetothecontroller:
.controller('RecentlyViewedController',
['$scope','$rootScope',function($scope,$rootScope){
www.it-ebooks.info
![Page 198: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/198.jpg)
3. Subscribetotheeventfrom$rootScope:
$rootScope.$on('SELECTEDPRODUCT',function(productEvent){
})
4. NowaddproductEventtotherecentarray:
$rootScope.$scope.recent.push(productEvent)
5. Rerunthetest.
5. Thetestswillnowpass.
End-to-endtestingTheunittestsarecompleteandwillverifythatthepublisherandsubscribercanbothcommunicatewithevents.Nowthewalk-throughwilllookattheapplicationasawholeandwillshowyouhowtocreateanend-to-endtest.Thespecificationforrecentlyvieweditemsisthatinagivensearchresult:
AproductisselectedItwillbeavailableintherecentlyvieweditems
Now,itistimetomoveontoactuallycreatingthetest.
Testfirst
Asalways,startbytranslatingthespecificationinthetestusingthe3A’s,asthetestswillutilizetheexistingtests.Assemblingtherecentlyviewedend-to-endtest
BeforeyourepeatthecodefromChapter5,FlipFlop,youshouldnoticethatthefirsttestalreadysearchesforandretrievesthesearchresults.Therefore,therecentlyviewedtestcanbeembeddedwithintheexistingtestforasearchresultthatisalreadyavailable.Atthebottomoftheexistingfunctionofasearchquery,initializetheteststub:
describe('whenItypeinasearchquery',function(){
//...
describe('',function(){
beforeEach(function(){
});
it('',function(){
});
});
Thereisnothingelsetoassembleforthetest,andyoucanmoveontothenextstep.Selectingasearchresult
Now,searchResultneedstobeinvokedusingthefollowingsteps:
1. ThefirststepwillbetoselectthefirstsearchResultelement:
varfirstResult=searchResult.first();
www.it-ebooks.info
![Page 199: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/199.jpg)
2. Findthelinkwithinthefirstitem:
varresultLink=firstResult.element(by.css('a'));
3. Clickontheresult:
resultLink.click();
Confirmingrecentlyvieweditems
Nowthataproducthasbeenselectedandoneproducthasbeenaddedtotherecentlyvieweditemslist,weneedtoviewtherecentlyvieweditems.Herearethestepstodothis:
1. Gettherecentlyvieweditems:
varrecentlyViewedItems=element(by.repeater('itemsinrecent'));
2. Confirmthatthecountofrecentlyvieweditemsisequalto0:
expect(recentlyViewedItems.count()).toBe(1);
MakingtherecentlyViewedItemstestpass
Nowthetestneedstopass.Herearethestepstodothis:
1. Startthewebsite:
./node_modules/http_server/bin/http_server
2. RunProtractor:
./node_modules/protractor/bin/protractorchromeOnlyConf.js
3. You’llgetanerror,namelyExpected0tobe1..4. Theerroristhattheexpectationhasfailed.Itistimetoaddthecontrollerand
repeatertotherecentlyvieweditemslisttoshowtheitems:
<divng-controller="RecentlyViewedController">
<divng-repeat="iteminrecent">
{{item}}
</div>
</div>
5. Rerunthetest6. Theerroristhesameasbefore.Thistime,Protractorerrorsdon’tgiveanycluesto
whattheissueis.ThenextstepistoopenupabrowserandseewhatthewebbrowserJavaScriptconsoleissaying.Pointyourbrowsertohttp://localhost:8080/#/recentlyViewed.Immediately,oneerrorwillbevisible,namely[ng:areq]Argument'RecentlyViewedController'isnotafunction,gotundefined.Torectifythis,performthefollowingsteps:
1. Nowthatthereisanactualerrortofix,progresscanbemade.Theerrorindicatesthatthecontrollerwasnotavailable.Asthecontrollerhasnotbeenadded,itistimetoaddthecontrollertothepage.Openuptheindex.htmlpage
www.it-ebooks.info
![Page 200: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/200.jpg)
andaddthecontrollerreference:
<scriptsrc="app/recentlyViewedController.js"></script>
2. Rerunthetest.
7. Nowthetestwillbesuccessful.
Makingrecentlyvieweditemsbetter
Therecentlyviewedcontrollerisnowcomplete.Itwouldbenicetobetterorganizetheview,howeverthiscanhappenlater.Thepointofthisexercisewastoestablishcommunicationbetweenseparateviewsandcreateausablefunction.Thishasbeenachieved,andnowyoucanmovetothenextstepofthewalk-through.
www.it-ebooks.info
![Page 201: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/201.jpg)
CreatingaproductcartAnotherimportantaspectoftheapplicationistheabilitytoaddproductstoacart.Apublishingandsubscriptionmodelwillbeusedtopublishwhenanitemhasbeensavedtoacart.Asubscriptiontotheeventwillthenkeeptrackofitemsinthecartsotheusercaneasilyseewhensaveditemsgetupdatedinrealtime.Hereisthespecificationgiventheproductdetailsofaparticularproduct:
IftheproductissavedtoacartProductwillbedisplayedintheproductcartview
Nowthenecessarythingsareinordertogetdowntothe3A’s.
PublishertestfirstThepublisherwillcomefromsearchDetailController.Thetestwillneedtoensurethatwhenanitemissaved,aneventispublished.
AssemblingsearchDetailController
ThesearchDetailControlleralreadyhassomeunittestswritten.Theexistingtestcanbeleveragedtoconfirmthepublishingfeature.Herearethestepstocreateasubtesttohandlethesavingofacart:
1. Startwithaninnerstub:
describe('',function(){
beforeEach(function(){
});
it('',function(){
});
})
2. Inordertotestthataneventhasbeenemitted,aspywillbeneededon$rootScope.Bringin$rootScopeandaddaspytoit:
//...
varsavedToCartEventSpy=jasmine.createSpy();
beforeEach(function(){
inject(function($rootScope){
$rootScope.$on('SAVEDTOCART',savedToCartEventSpy);
});
});
3. AddafterEachtoresetthespy:
afterEach(function(){
savedToCartEventSpy.calls.reset();
});
Invokingthesavingofaproduct
InthebeforeEachsection,selectthemethodandmakethefollowingchanges:
www.it-ebooks.info
![Page 202: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/202.jpg)
beforeEach(function(){
//...
varfakeProduct={productId:1};
searchDetailScope.saveProduct(fakeProduct);
})
Confirmingthesaveevent
Theexpectationisthatthespyhasbeencalled:
it('',function(){
expect(savedToCartEventSpy).toHaveBeenCalled();
})
MakingthesaveProducttestpassNowweneedtomakethetestpass.HerearethestepstomakethesaveProducttestpass:
1. StartKarma:
$karmastart
2. ThefirsterrorwillbeTypeError:'undefined'isnotafunction(evaluating'searchDetailScope.saveProduct(fakeProduct)').Ifyougetthiserror,thenfollowthesesteps:
1. Thefunctiondoesn’texistonthescope.Additusingthefollowingcode:
$scope.saveProduct=function(product){};
2. Rerunthetest.
3. NowtheerrorhashittheexpectationandsaysExpectedspyunknowntohavebeencalled.Inthiscase,followthegivensteps:
1. Thesmallestthingwecanaddtothetestistheabilitytoemittheeventfromthemethod.Firstadd$rootScopetothecontroller:
.controller('SearchDetailController',
['$scope','$routeParams','productService','$rootScope',function($sc
ope,$routeParams,productService,$rootScope){
2. ThenaddtheSbroadcast()eventtoit:
$rootScope.$broadcast('SAVEDTOCART',product);
3. Rerunthetest.
4. Thetestissuccessful.
TestforthesubscriberfirstThesubscriberunittestwillconfirmthatwhenaSAVEDTOCARTeventisemitted,thentheproductwillbeaddedtothecartobject.ThespecificationisasaSAVEDTOCARTeventis
www.it-ebooks.info
![Page 203: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/203.jpg)
given,thefollowingactionwillbeperformed:
Itwilladdtheproducttothecart
Assemblingtheproductcarttest
Herearethestepstoassembletheproductcarttest:
1. Createanewfile,spec/unit/cart.js.2. Startwiththebasestub:
describe('',function(){
beforeEach(function(){
});
it('',function(){
});
});
3. Initializethemodule:
module('product');
4. Initializethescopesothatexpectationscanbemade:
varscope={};
beforeEach(function(){
//...
inject(function($controller){
$controller('CartController',{$scope:scope});
});
});
5. Initialize$rootScopesosubscriptionscanbemade:
inject(function($controller,$rootScope){
scope=$rootScope.$new();
$controller('CartController',{$scope:scope,$rootScope:$rootScope});
});
6. Thelastthingtoconfirmisthatthecartisempty.Addthefollowingexpectationtoensurethetestissetupproperly:
expect(scope.cart.length).toBe(0);
Invokingasavedcartevent
ThistestisaroundthefactthatwhentheSAVEDTOCARTeventispublished,theCartControllerpropertywillperformaspecificaction.AddthepublishingoftheeventtothebeforeEachmethod:
beforeEach(function(){
//...
varfakeProduct={productId:1};
$rootScope.$broadcast('SAVEDTOCART',fakeProduct);
});
Confirmingthesavedcart
www.it-ebooks.info
![Page 204: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/204.jpg)
Nowthatthetesthasbeensetupandtheactperformed,youcanassert.Assertthatthenumberofcartitemsisequalto1byaddingthefollowingcode:
it('',function(){
expect(scope.cart.length).toBe(1);
});
MakingthecartcontrollertestrunNowit’stimetowalkthetestthroughthecyclebyfollowingthegivenstepsuntilwegetagreentest:
1. StartKarma:
$karmastart
2. ThefirsterrorisError:[ng:areq]Argument'CartController'isnotafunction,gotundefined.Asseenpreviously,thecontrollerhasn’tbeencreated.Createanewfileandsetupastubcontroller(/app/cart.js):
angular.module('product')
.controller('CartController',['$scope',function($scope){
}]);
3. ThenexterrorwillbeTypeError:'undefined'isnotanobject(evaluating'scope.cart.length').Thisindicatesthatnoobjectwasfoundonthescopenamedcart.Goaheadandcreateitnowinapp/cart.js:
$scope.cart=[];
4. Then,you’llgetanexpectationerror,namelyExpected0tobe1.Error:Expected0tobe1.Torectifythis,performthefollowingsteps:
1. Atthispoint,thecontrollerisnotdoinganythingwiththeeventbeingemitted.Add$rootScopeasadependencytotheapplication:
.controller('CartController',
['$scope','$rootScope',function($scope,$rootScope){
2. Addthehandlinglogictocapturetheeventandaddtheproducttothecart:
$rootScope.$on('SAVEDTOCART',function(productEvent){
$scope.cart.push(productEvent);
});
5. Success!Allthetestshavepassed.
End-to-endtestingTheunittestsarenowcomplete,anditisnowtimetoperformend-to-endtestingforthecart.
Assemblingthecart’send-to-endtest
www.it-ebooks.info
![Page 205: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/205.jpg)
ThetestcomesfromtheperspectiveofbeingonaproductdetailviewandselectingaSavetoCartbutton.Oncetheitemhasbeensaved,itshouldbeavailableinthecartview.Herearethestepstoassemblethecart’send-to-endtest:
1. Createanewfilenamedspec/e2e/cartScenario.js.2. Startwiththebasetemplatetest:
describe('',function(){
beforeEach(function(){
});
it('',function(){
});
});
3. Thenextthingweneedtodoisnavigatetoaproductpage:
browser.get("#/product/1");
4. Selectthebuttonthatwillsavethecart:
varsaveToCartButton=element(by.buttonText('SavetoCart'));
Invokingasavetocartaction
TheactionistoclickontheSavebuttonusingthefollowingcode:
saveToCartButton.click();
Confirmingproductshavebeensaved
Theassertistoconfirmthatthecartviewnowhasatleastoneproduct:
it('',function(){
varproductsInCart=element.all(by.repeater('productincart'));
expect(productsInCart.count()).toBe(1);
})
Makingthecart’send-to-endtestpassHereisthewalk-throughoftheprocessofmakingtheapplicationrun:
1. Startthesite:
$./node_modules/http-server/bin/http-server.
2. RunProtractor:
$./node_modules/protractor/bin/protractorchromeOnlyConf.js
3. ThefirsterrorisNoSuchElementError:Noelementfoundusinglocator:by.buttonText("SavetoCart").Torectifythis,performthefollowingsteps:
1. Goaheadandcreatethebuttonwithintheproductdetail’sapp/searchDetail.htmlpartialview:
<button>SavetoCart</button>
www.it-ebooks.info
![Page 206: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/206.jpg)
2. Rerunthetest.
4. ThenexterrorisExpected0tobe1.Torectifythis,performthefollowingsteps:
1. Thiserrormeansthatthecountis0forproductsinthecart.Byreviewingtheindexpage,youcanseethatthecartdoesn’tevenexistinthepage.First,addareferencetothecartcontroller:
<scriptsrc="app/cart.js"></script>
2. Next,theitemsinthecartneedtobeaddedtothepage.First,addatagwiththecontroller:
<divng-controller="CartController"></div>
3. Finally,addarepeatertodisplaytheproductinthecart:
<ul>
<ling-repeat="productincart">{{product}}</li>
</ul>
4. Rerunthetest.
5. Thesameerroroccurs,Expected0tobe1.Torectifythis,performthefollowingsteps:
1. Eventhoughtheproductdatahasbeenadded,thetestisstillfailing.Thenextquestioniswhetheranythingisbeingaddedtothecart.Inthiscase,no.Thebuttonisbeingselectedbutnoactionhasbeenassociatedwithit.Updatethebuttoninapp/searchDetail.htmltousethesearchDetailControllerclass’ssaveProductmethod:
<buttonng-click="saveProduct()">SavetoCart</button>
2. Rerunthetest.
6. Allthetestspass.
www.it-ebooks.info
![Page 207: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/207.jpg)
Self-testquestionsThefollowingaresomequestionstocheckyourunderstanding:
Q1.Whenbroadcastingamessage,itpropagatesupthescope’shierarchy.
1. True2. False
Q2.ThefollowingcreatesaspyinJasmine:
1. varspy=jasmine.createSpy();2. varspy=jasmine.$new();3. varspy=jasmine.createFake();
Q3.The$rootScopescopeisthehighestlevelscopeinAngularJS.
1. True2. False
Additionally,ifyouwantmorepractice,addtheabilitytoaddlikestothepage.
www.it-ebooks.info
![Page 208: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/208.jpg)
SummaryThischapterhasexploredeventswithinAngularJS.YousawtwotypesofAngularJSeventemitters:$broadcast()and$emit().YoualsosawsomeexamplesofapplyingTDDtoeventsandhoweventsgiveaseparationofcontrollersandcode.Inaddition,youexpandedthetypesoftestingtechniquestoincludeservicesandreiteratedthetestingofcontrollersandmodels.YoualsoexploredfurtherconfigurationofKarmatouseitsfeatures.Inthenextchapter,youwilllookattheintegrationandtestingofdataandAPIsintoanAngularJSapplication.
www.it-ebooks.info
![Page 209: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/209.jpg)
Chapter7.GiveMeSomeDataApplicationsneedawaytoconsumetheever-expansiveworldofdata.Mostapplicationswrittentodayconsumedata.LuckilyforAngularJSdevelopers,consumingdataisquiteeasy.Testingdataconsumptionisalsoacorecomponentoftheframework.Inthischapter,wewillcoverthefollowingtopics:
IntegratingaREST-basedserviceCreatingandmockingAngularJS’s$httpHandlingexceptionsImplementingafakeAPIbuilderpattern
www.it-ebooks.info
![Page 210: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/210.jpg)
REST–thelanguageoftheWebRepresentationalStateTransfer(REST)defineshowtheWebshouldcommunicate.FromanAngularJSapplicationstandpoint,themainconcerniswiththeHTTPmethods.ForHTTPmethods,RESTcanbethoughtofastheverbsoractionsthatanHTTPrequestcanmake.Specifically,anHTTPrequestcanmaketheserequesttypes:GET,POST,PUT,andDELETE.FromanAPIstandpoint,theHTTPmethodscanbeusedtodeterminehowlogicshouldhandlethespecificHTTPrequesttype.HereisafurtherlookatthecommonHTTPmethods:
HTTPMethod Description Example
GET Retrievesdatafromanendpoint curl--requestGET'http://<SOMEURL>'
POST Postsanewdataelementtotheendpoint curl–requestPOST'http://<SOMEURL>'–data'anydata'
PUT Insertsorupdatestheencloseddataelementtotheendpoint curl–requestPOST'http://<SOMEURL>'–data'anydata'
DELETE Deletesarequesttotheendpoint curl--requestDELETE'http://<SOMEURL>'
NoteThecurltoolisacommand-linetoolthatcanbeusedtomakerequests.OnUnixmachines,itisavailableinthecommandlinebysimplytypingcurl.ForWindowsmachines,itisbesttoinstallGitbashandaccessitthroughtheGitbashcommandline.InstallationinstructionsforGitandGitbashcanbefoundathttp://git-scm.com/downloads.
Ascanbeseenfromtheprecedingexplanation,theRESTfulcomponentsofHTTPcandefinethebasicsformostAPIs.TheprecedingRESTapproachisdifferentfromotherwebservicetechniquesorprotocolsandcanbeusedbypracticallyanything.Fortheirsimplicity,REST-basedwebservicesarethebestoptions.Inthischapter,thefocuswillonlybeonhowtouseAngularJSwithaREST-basedAPI.
www.it-ebooks.info
![Page 211: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/211.jpg)
GettingstartedwithRESTBeforejumpingintohowAngularJScommunicateswithaRESTlayer,itisimportanttoseehowtocommunicateusingstandardtoolswithinabrowser.Asyousawfromthepreviousdefinition,curlcanbeusedtocommunicatetoaRESTAPI.AlthoughmakingamanualHTTPrequestoutsideofabrowserisuseful,youalsoneedtounderstandthebasicsofhowabrowsermakesanAPIrequestwithoutaframework.Inabrowser,requestscanbemadetoRESTlayersthroughasynchronouscalls.Thisallowsrequeststhatwon’taffecttheotherpartsoftheapplicationtobemade;thatis,thepagewon’tfreezeandbecomeunusable.Thewebpageremainsuseablewhiletherequestismade.
BrowsersprovideamechanismtomakeasynchronousRESTcallsusinganXMLHttpRequestmethod.AnXMLHttpRequestmethodcanbeusedtomakeanHTTPGET,POST,PUT,orDELETErequest.HereisanexampleofhowtomakeaGETrequest:
varrequest=newXMLHttpRequest();
request.open('GET','/any/rest/endpoint');
request.send();
Theprecedingexamplecreatesanewrequest,specifiestherequesttypeandlocation,andfinally,sendstherequest.Themissingpieceisthehandlingoftheresponse.Addthefollowingcodejustbeforethesendmethod:
request.onreadstatechange=function(){
if(request.readyState===4){
console.log('receivedresponsewithstatus:'+request.status);
}
};
Theprecedingcodehandleswhentherequesthasreceivedaresponsefromtheserverandiscomplete(readystate===4).Withintheconditiongiveninthecode,youcanhandletheparsingoftheresponse,thedeterminingstatusoftherequest,andsoon.
What’sgreatabouttheprecedingcodeisthatitdoesn’trequireaframework.Theproblemisthatthecodecangrowinsizeandbecomerepetitiveforeveryrequest.AngularJShasabstractedtherequestforyou.
www.it-ebooks.info
![Page 212: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/212.jpg)
TestingasynchronouscallsNowthatyouunderstandhowtomakeHTTPrequeststhroughthebrowser,weneedtounderstandhowtotestthesecalls.Theprecedingrequestsareasynchronous.Asynchronousmeansthereisnoguaranteeofwhenthefunctionwillcomplete.Foryourreference,hereisanexampleofsynchronoussequentiallogic:
varsynchronousFunc=function(){
console.log('InsynchronousFunc');
};
synchronousFunc();
console.log('AftercalltosynchronousFunc');
Whentheprecedingcodeisrun,theoutputisasfollows:
InsynchronousFunc
AftercalltosynchronousFunc
Eachfunctioncalloccursintheorderofthecall.Withanasynchronousrequest,theorderisnotguaranteed.Acallbackfunctionispassedintoafunctiontoinformyouwhenamethodiscomplete.
TipCallbackfunctionshavetwomainconventions.ThefirstisthejQuery-basedmethod.ThesecondistheNode.jsmethod.ThejQueryconventionusestwocallbacksasthelastargumentstoamethod.Thefirstcallbackisforsuccess,andthesecondisforanerror.TheNode.jsconventionistouseasinglecallbackasthelastargument.Thecallbackhastwoparameters,thefirstbeinganerrorandthesecondbeingthesuccessfulresult.
Itisuptoyoutodecidewhichconventiontousebasedonwhatyou’redevelopingfor.Don’tcreateyourownnewconvention;useoneoftheprecedingconventionssothatotherdeveloperscaneasilyunderstandandreadyourcode.
Hereisanexampleoftheoutputofanasynchronousmethod:
varasynchronousFunc=function(callback){
setTimeout(callback,0);
};
varcallback=function(){
console.log('InasynchronousFunc');
};
asynchronousFunc(callback);
console.log('AftercalltoasynchronousFunc');
Whentheprecedingcodeisrun,theoutputisasfollows:
AftercalltoasynchronousFunc
InasynchronousFunc
ThenextsectionswilllookathowtesttoasynchronousfunctionsinKarmaandProtractor.
www.it-ebooks.info
![Page 213: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/213.jpg)
CreatingasynchronouscallsinKarmaFromtheprecedingasynchronousexample,itshouldbeclearthatthewayinwhichyoutestneedstobemodifiedtoaccountforasynchronousbehavior.Luckily,thisisfairlystraightforwardwhentestingwithKarma.
HerearethestepstotesttheprecedingasynchronousmethodusingKarma:
1. Createthestubtestusingthefollowingcode:
describe('',function(){
beforeEach(function(){
});
it('',function(){
});
});
2. Createaspytotestwhentheasynchronousmethodgetscalled:
varspy=jasmine.createSpy();
3. CalltheasynchronousmethodinthebeforeEachfunction:
beforeEach(function(){
varasynchronousFunc=function(callback){
setTimeout(callback,0);
};
varcallback=function(){
spy();
};
asynchronousFunc(callback);
});
4. AddacallbacktotheparametersofthebeforeEachfunction.Bydoingthis,youhavemadethefunctionasynchronous:
beforeEach(function(done){
…
});
5. CallthedonemethodintheasynchronousFunccallback:
varcallback=function(){
spy();
done();
};
6. Addtheassertionfunction:
it('',function(){
expect(spy).toHaveBeenCalled();
});
ThekeytotheprecedingcodeisthatacallbackwaspassedintothebeforeEachfunction.Youcantrytorunthistestwithoutthecallbackandseewhetherthetestwillfail.A
www.it-ebooks.info
![Page 214: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/214.jpg)
callbackcanbepassedintothebeforeEach,afterEach,describe,anditmethods.
Youwillbeleveragingthisexamplethroughtherestofthechapter,sobesurethatyouunderstandthemainconcepts.NowthatyouhavetestedinKarma,thenextsectionwillshowyouwhatProtractoroffersfromanasynchronousstandpoint.
www.it-ebooks.info
![Page 215: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/215.jpg)
CreatingasynchronouscallsinProtractorProtractorisdifferentinthewayithandlesasynchronousactions.Ithasbeenoptimizedtohandleasynchronousactions,specifically,promises.Asanexample,whenatestnavigatestoapage,ProtractorwillwaituntilAngularJShasbeenloadeduntilitstartsrunningthetests.JulieRalph,themaincontributorandcreatorofProtractor,sumsitupinthisGitHubissue(https://github.com/angular/protractor/issues/716):
ProtractorpatchesJasminesothatitisautomaticallyasynchronous,andatestcasefinisheswhentheWebDriverqueueofcommandsisfinished.
Whatthismeansisthatyoudon’thavetothinkabouthowthecallsarebeingrenderedandwhenthepromisesarecomplete.Itevenwaitsfor$httprequeststocomplete.HereisanexampleofusingProtractor:
describe('WhenItypeinasearchquery',function(){
varsearchResult=element.all(by.repeater("resultinresults"));
beforeEach(function(){
browser.get("/index.html");
$('input').sendKeys('anyvalue');
element(by.buttonText('search')).searchButton.click();
});
it('Shouldthenaddtheresult',function(){
expect(searchResult.count()).toBe(1);
});
});
TheprecedingcodesnippetistakenfromChapter6,TelltheWorld.IthighlightshowProtractorexecuteseachoneofthecommandsandtakescareoftheasynchronousbehaviorsforyou.Inthenextsection,youwillseehowtomakeRESTrequestsusingAngularJS.
www.it-ebooks.info
![Page 216: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/216.jpg)
MakingRESTrequestsusingAngularJSNowthatwehavelookedatwhatRESTrequestsareandseenhowtotestasynchronouslyinKarmaandProtractor,itistimetoseehowtomakearequestinAngularJS.Atthelowestlevel,AngularJSprovidesthe$httpmodule.ThemoduleallowsyoutomakeHTTPrequests.Byvisitingthedocumentation(https://docs.angularjs.org/api/ng/service/$http),wecanseethatitsaysthefollowing:
The$httpserviceisacoreAngularservicethatfacilitatescommunicationwiththeremoteHTTPserversviathebrowser’sXMLHttpRequestobject.
AsyouhavealreadyseenhowtomakeanXMLHttpRequest,youshouldfeelateasethatyouknowwhatisgoingonunderthehood.Hereisasimpleexampleofhowtomakean$http.getrequestinAngularJS:
$http.get('/any/rest/endpoint')
.success(function(data,status,header,config){
});
.error(function(data,status,header,config){
});
Thesuccess/errorfunctioniscalledasynchronouslyoncetherequestiscomplete.
Using$httpisnottheonlywaytomakearequest.IfanAPIiscompletelyREST-based,AngularJSprovidesthe$resourcemodule.Aresourcegetsdefinedandusedasshowninthefollowingsteps:
1. Definearesourceforaspecificendpoint:
varthing=$resource('/any/rest/endpoint/:id',{id:'@id'});
2. MaketheHTTPGETrequest:
thing.get({id:1},function(aThing){
…
});
TheprecedingexampledefinesaresourcethatretrievesaThingbasedonanID.ItthenretrievesthatdatawithaGETrequest.
BothoftheprecedingexamplesshowyouhowtocreaterequestsinAngularJS.Youwillbelookingatthe$httpmethodintheremainingexamples,butitisgoodtounderstandthedifferentwaysinwhichrequestscanbecreatedinAngularJS.
www.it-ebooks.info
![Page 217: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/217.jpg)
TestingwithAngularJSRESTNowthatyouhaveseenhowtomakerequestsinAngularJSandhowtotestasynchronously,youwillneedtolookathowtoputittogether.ThefollowingexamplelooksataspecificserviceandthendiscusseshowtotestusingKarma.
TestingtheproductserviceTheservicethatneedstobetestedisasfollows:
angular.module('anyModule')
.service('productService',['$http',function($http){
return{
search:function(query){
return$http.get('/product/search');
}
};
});
TheprecedingproductServiceparameterprovidesanobjectsearchthattakesinaqueryandreturnsa$httppromise.Theproductservicecanbeusedinacontrollerasfollows:
productService.search(query)
.success(function(data){
$scope.result=data;
})
.error(function(data){
$scope.error=data;
});
angular.module('anyModule')
.controller('productController',['$scope','productService',
function($scope,productService){
$scope.search=function(query){
productService.search(query)
.success(function(data){
$scope.result=data;
})
.error(function(data){
$scope.error=data;
});
}]);
TheprecedinguseoftheproductServiceshowsyouthatbecausean$httppromiseisreturned,youcanusethesuccessanderrorfunctionstodefinewhatneedstooccurafter.Nowthatthereisacontrollerandaservice,thenextsectionwillshowyouhowtotestthecomponents.
Testing$httpwithKarmaTheKarmatestwilllooktoconfirmthebehaviorofproductServiceifthe$httpcallissuccessfulandisonetolookatifanerroroccurs.Themaindifferencebetweenthistestandothersthathavebeenlookedatsofaristhatyouarecreatingarequesttosomething
www.it-ebooks.info
![Page 218: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/218.jpg)
outsideofAngularJS.Thisisaperfectcaseofusemocking.Youcansetupafakeobjectaround$httptotestthesuccessanderrorpathsoftherequest.AngularJSprovidesamockobjectthatcanbeused,whichisAngularmock’s$httpBackend.
Herearethestepstocreateapositivetest—whentherequestissuccessful:
1. Startwiththeteststub:
describe('',function(){
beforeEach(function(){
});
it('',function(){
});
});
2. Initializethemodule:
beforeEach(function(){
module('anyModule');
});
3. Inject$httpBackendandproductServiceinthebeforeEachfunction:
var$httpBackend=null;
varproductService=null;
beforeEach(function(){
module('anyModule');
inject(function(_$httpBackend_,_productService_){
$httpBackend=_$httpBackend_;
productService=_productService_;
});
});
4. MocktheGETsuccessfulrequestwithanHTTPstatuscodeof200asfollows:
it('',function(){
$httpBackend.when('GET','/product/search').respond(200,'');
});
5. Settheexpectationasfollows:
it('',function(){
…
$httpBackend.expectGET('/product/search');
});
6. MakethecalltoproductServiceusingthefollowingcode:
productService.search('any');
7. Flushtherequestusingthefollowingcode:
$httpBackend.flush();
Asyoucansee,$httpBackendallowsexpectationsandmockresponsestobecontrolled.Totieuplooseends,herearetheadditionalexpectationsforafailedrequest.Followthestepstoaddexpectationsforafailedrequest:
www.it-ebooks.info
![Page 219: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/219.jpg)
1. Addtheexpectationstubtoanasynchronousparameter:
it('',function(done){
});
2. MocktheGETunsuccessfulrequestwithanHTTPstatuscodeof500:
$httpBackend.when('GET','/product/search').respond(500,'');
3. CallproductService.Search:
productService.search('any');
4. Confirmthattheerrorfunctiongetscalled:
productService.search('any').error(function(){
expect(true).toBe(true);
done();
});
5. Flushtherequest:
$httpBackend.flush();
Wehavenotaddedanyotherlayerstotheapplicationandareabletoconfirmhowitwillworkduringasuccessfulandunsuccessfulrequest.Inthenextsection,youwillseehowtotestHTTPrequestsinProtractor.
www.it-ebooks.info
![Page 220: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/220.jpg)
MockingrequestswithProtractorNowthatunittestsforthebackendarecomplete,youcanmovetothefrontendandtestanHTTPrequestthroughProtractor.Youmightnotalwayswanttodothis.Protractorissupposedtotestyoursitefromanend-to-endperspective.Thismeansthatalllayersoftheapplicationwillbetouched.Onebenefitofthefollowingexampleisthatitwillhelpincaseswhereyouhaven’tsetupthebackendrestservice.Youcanbeginbylayingoutthepageandinteractionsbeforethebackendiscomplete.Thiscanhelpwhenyou’rejustputtingyoursitetogether.
InordertomockthebackendHTTPlayerforProtractor,wewilluse$httpBackend,whichispartofthengMockE2EmoduleandisusedtomockthebackendHTTPlayerforProtractor.The$httpBackendpropertyusedforProtractorisdifferentfromtheoneusedinthepreviousKarmatest.Touseend-to-end$httpBackendyouwillneedtoinjectngMockE2Easadependencyintotheapplication.Forthisreason,itisnotaviablesolutiontohaveinaproductionsite.
Herearethestepsthataretobemockedusing$httpBackendinProtractor:
1. AddAngularJSandAngularmockstothewebpage:
<scriptsrc="bower_components/angular/angular.js"></script>
<scriptsrc="bower_components/angular-mocks/angular-mocks.js"></script>
2. CreateamoduleandrequirengMockE2E:
angular.module('anyModule',['ngMockE2E'])
3. Addarunfunctionthatuses$httpBackend:
.run(['$httpBackend',function($httpBackend){
4. Createthemockdata:
.run(['$httpBackend',function($httpBackend){
varproducts=[{id:'id1',name:'product1'},{id:
'id2',name:'product2'}];
}]);
5. Setthemockdatarequest:
.run(['$httpBackend',function($httpBackend){
varproducts=[{id:'id1',name:'product1'},{id:
'id2',name:'product2'}];
$httpBackend.whenGET('/product/search').respond(products);
}]);
Nowtherequestto/product/searchwillrespondwiththeproductsdefinedinthemock.Thismeansthattheapplicationwillworkwithouttheneedforabackendserviceandwillbeabletobetestedasanapplicationwithabackendservice.Acompleteexampleusingamockedbackendwillbeshowninthewalk-through.
www.it-ebooks.info
![Page 221: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/221.jpg)
DisplayingproductswithRESTAllthecorecomponentsofREST,asynchronoustesting,andmockingHTTPrequestshavebeendiscussed.Now,thefollowingwalk-throughwillprovideafullexamplethatwilllookatdisplayingproductsthatareretrievedthroughanexternalservice.Theexamplewillignorethecreationofanexternalserviceandfocusonthedataitprovides:alistofproductsinaJSONformat.Thewalk-throughwilltakeabottom-upapproachsothatthecoredatalayerisworkedoutbeforeaddingtheUIelements.
www.it-ebooks.info
![Page 222: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/222.jpg)
UnittestingproductrequestsTheapproachfromtheunitlevelistocreateaservicetomanagetheHTTPrequestsforproducts.Thecontrollerwillthenbebuiltupthesameway.
SettinguptheprojectBeforewritingtests,theprojectneedstohaveastructure.Hereiswhattheinitialprojectstructurelookslike:
KarmaconfigurationNowthattheprojecttemplatehasbeensetup,acoupleofadjustmentsneedtobemade.TheKarmaconfigurationneedstouseaheadlessbrowserandsetupthetestfilestothecorrectlocation.Openupkarma.conf.jsandmakethefollowingchanges:
1. UpdatethebrowserssectiontoPhantomJSforheadlessbrowsertesting:
browsers:['PhantomJS'],
2. Updatethefilessectiontoincludetheunittestfolders:
files:[
'bower_components/angular/angular.js',
'bower_components/angular-mocks/angular-mocks.js',
'app/**/*.js',
'spec/unit/**/*.js'
],
Karmahasbeenconfiguredandtheprojecttemplatehasbeencreated.ThenextstepistosetupanAPIbuilderfortheproductdata.Thiswillallowforaconsistentinterfacetobeusedinatestwheremockingdataisrequired.
UsinganAPIbuilderpatternAbuilderisanobjectthatisusedtocreateanotherobject;itwillbeusedtocreatetestdata.AnAPIbuildercanreduceduplicationandthetimetakentocreatetests.Itprovidesacentralwaytohandlemethodsandcreatedata.Ifabuilderisnotused,theneverytestwrittenwillhavetohaveaseparatedistinctwayofcreatingdata.Thisisanespeciallybad
www.it-ebooks.info
![Page 223: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/223.jpg)
designwhentheAPIbeingusedchanges!
TheproductdataAPIisdefinedbyasingleroute/products.Theexpectedresponseisalistofproducts.HerearethestepstocreateabuilderfortheproductAPI:
1. CreateanewfileinthespecfoldernamedproductDataBuilder.js:
$touchproductDataBuilder.js
2. CreateanewfunctionnamedproductDataBuilder:
module.exports=functionproductDataBuilder(){};
3. ReturnanobjectwithmethodstosetIDs,names,andtoactuallybuildanobject:
module.exports=functionproductDataBuilder(){
return{
withId:function(id){
},
withName:function(name){
},
build:function(){
}
};
};
4. Initializeabasicproduct:
module.exports=functionproductDataBuilder(){
return{
_mockProduct:{id:1,name:'productName'},
withId:function(id){
},
withName:function(name){
},
build:function(){
}
};
};
5. Havethesettercommandsupdatethemockproduct:
return{
...
withId:function(id){
this._mockProduct.id=id;
returnthis;
},
withName:function(name){
this._mockProduct.name=name;
returnthis;
},
};
6. Havethebuildmethodreturnthemockdata:
return{
build:function(){
www.it-ebooks.info
![Page 224: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/224.jpg)
returnthis._mockProduct;
}
};
Thebuilderallowsyoutouseafluentinterfacetocreateproducts.Thesimplestuseisasfollows:
varproductDataBuilder=require('../productDataBuilder');
varsomeProduct=productDataBuilder.build();
AmorecomplicatedusewillbetosettheIDandnametosomethingsuchasthefollowing:
varproductDataBuilder=require('../productDataBuilder');
varsomeProduct=productDataBuilder.withId(9999)
.withName('Product9999');
TheprecedingproductDataBuilderobjectwillbeusedintheKarmatest.
www.it-ebooks.info
![Page 225: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/225.jpg)
TheproductdataserviceIt’stimetogettotheactualtest.ThesameTDDlifecyclethathasbeenusedthroughoutthebookwillbeused;testfirst,makeitrun,andmakeitbetter.AsthecreationandtestingofaservicethatusesHTTPhasalreadybeendiscussed,thiswalk-throughwillbeskipped.Forreference,thetestsareinthecoderepositoryandtheserviceisdefinedasfollows:
angular.module('product')
.service('productService',['$http',function($http){
return{
getAll:function(){
return$http.get('/products')
}
};
}]);
Withtheservicecomplete,thenextstepistolookatthecontrollerandhowtoactuallymakeuseoftheHTTPdata.
www.it-ebooks.info
![Page 226: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/226.jpg)
TheproductdatacontrollerThenextcomponentneededisacontrollersothattheUIcanuseproductService.Thecontrollerneedstohaveonemethodtomaketherequestforproducts.Inthemethod,itneedstoset$resultwhentherequestissuccessfuland$errorwhentherequestisunsuccessful.
AssemblingtheproductcontrollertestHerearethestepstoassembletheproductcontroller:
1. Createanewtestfilefortheproductcontrollerspec/productController.js:
$touchspec/productController.js
2. Usethestandardteststub:
describe('',function(){
beforeEach(function(){
});
it(function(){
});
});
3. Createvariablesforscopeand$httpBackend:
varscope={};
var$httpBackend=null;
4. Initializetheproductmodule:
beforeEach(function(){
module('product');
});
5. Getthe$controllerand$httpBackend:
beforeEach(function(){
inject(function($controller,_$htttpBackend_){
});
});
6. Set$httpBackendtotheinjectedvariable:
inject(function($controller,_$httpBackend_){
$httpBackend=_$httpBackend_;
7. Initializethecontrollerscope:
inject(function($controller,_$httpBackend_){
$httpBackend=_$httpBackend_;
$controller('ProductController',{$scope:scope});
Gettingproducts
www.it-ebooks.info
![Page 227: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/227.jpg)
Theobjectundertestisthecontroller’sscopegetAllmethod.HerearethestepstocallthemethodforasuccessfulHTTPresponse:
1. ForasuccessfulHTTPresponse,usethebuildertobuildatestproduct:
it('',function(){
vartestProduct=productDataBuilder().build();
});
2. MocktheHTTPrequestresponsetoreturntestProduct:
$httpBackend.when('GET','/products').respond(200,[testProduct]);
3. Calltheobjectundertest:
scope.getAll()
Now,theunsuccessfulHTTPresponserequiresanerrorresponse.HerearethestepsfortheunsuccessfulHTTPrequest:
1. MocktheHTTPrequestresponsetoreturntestProduct:
it('',function(){
$httpBackend.when('GET','/products').respond(200,[testProduct]);
});
2. Calltheobjectundertest:
scope.getAll()
TheHTTPresponsehasbeencovered,andthenextstepwillasserttheexpectation.
AssertingproductdataresultsAnassertioncanbeusedtorequirethatanHTTPrequestreceivesaresponse.Themocked$httpBackendpropertycancalltheflush()methodtoexecutetheHTTPresponsesynchronously,soyoudon’thavetoworryaboutasynchronousissues.HerearethestepsforthesuccessfulHTTPresponseexpectation:
1. Flushtherequest:
$httpBackend.flush();
2. ExpecttheresultvariableonthescopeobjecttohavetestProductData:
expect(scope.results[0]).toEqual(testProductData);
HerearetheassertstepsfortheunsuccessfulHTTPresponseexpectation:
1. FlushtheHTTPrequestusingthefollowingcode:
$httpBackend.flush()
2. Confirmthatthescopes’errorvaluehasbeenset:
www.it-ebooks.info
![Page 228: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/228.jpg)
expect(scope.error).toEqual('error');
Nowthatthetestshavebeenassembled,thenextstepistomakethemrun.
www.it-ebooks.info
![Page 229: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/229.jpg)
MakingtheproductdatatestsrunHerearethestepstogetthecontrollertestrunning:
1. RunKarma:
$karmastart
2. ThefirsterrorisError:[ng:areq]Argument'ProductController'isnotafunction,gotundefined.Torectifythis,performthefollowingsteps:
1. ThiserrormeansthatProductControllerdoesn’texist.Createacontrollerstubinapp/productController.js:
angular.module('product')
.controller('ProductController',['$scope',function($scope){
}]);
2. Rerunthetest.
3. ThisnexterrorisTypeError:'undefined'isnotafunction(evaluating'scope.getAll()').Torectifythis,performthefollowingsteps:
1. ThiserrormeansthatthereisnofunctioncalledgetAllinthecontroller.Addthefunctionnow:
.controller('ProductController',['$scope',function($scope){
$scope.getAll()=function(){
};
}]);
2. Rerunthetest.
4. ThenexterrorisError:Nopendingrequesttoflush!.Torectifythiserror,performthefollowingsteps:
1. ThiserroroccursbecausethetestisexpectinganHTTPrequesttobeflushedbutthereisnorequest.AddproductServicetocontrollersothattherequestwillgetmade.AddproductServiceasadependency:
.controller('ProductController',
['$scope','productService',function($scope,productService){
2. AddproductServicetothegetAllfunction:
scope.getAll=function(){
productService.getAll();
};
3. Rerunthetest.
5. ThenexterrorisExpectedundefinedtoequal{id:1,name:'productName'}.Torectifythiserror,performthefollowingsteps:
www.it-ebooks.info
![Page 230: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/230.jpg)
1. Thiserroroccursbecausescope.resultshasnotbeensetwhentheproductservicewassuccessful.AddasuccessfulcallbacktoproductServiceandsetthescope’sresultsvariable:
productService.getAll()
.success(function(data){
$scope.results=data;
});
6. Nowwe’redowntoonefailure,whichisExpectedundefinedtoequal.Torectifythis,performthefollowingstep:
1. Thiserroroccursbecausewehaven’thandledtheerrorconditionoftheHTTPrequest.AddtheerrorconditionofproductServicesothatitsetsthescope’serror:
productService.getAll()
.success(function(data){
$scope.results=data;
})
.error(function(error){
$scope.error=error;
})
7. Confirmthatallthetestspassnow.
Theunittestsfortheproductcontrollerhavebeencompletedusingamockedbackendtotestbothpositiveandnegativescenarios.Thenextstepcanbeskipped,astherewerenocalloutsduringdevelopment.
Thenextsectionwilllookathowtotestfromanend-to-endperspective.
www.it-ebooks.info
![Page 231: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/231.jpg)
Testingmiddle-to-endNowthattheunitleveltestingoftheapplicationiscomplete,theuserfacingtestscanbeworkedon.OneofthebenefitsofAngularmocksisthatitprovides$httpBackend,whichcanbeusedtomockdataforend-to-endtests.Asdataisbeingmocked,itisreallyamiddle-to-endtest.ThisisbecauseonlytheUIinteractionsarebeingtested,astherestofthebehaviorhasbeenmocked.ThiswillallowustocreatescaffoldingfortheUIlayer.Oncethedevelopmentiscomplete,thescaffoldingcanberemovedandafullend-to-endtestcanbeputinplace.
HerearetheinitialsetupstepstocreatetheapplicationUIusingamockedbackendwithProtractor:
1. InstallProtractor:
$npminstallprotractor
2. UpdateWebDriver:
$./node_modules/protractor/bin/webdriver-managerupdate
3. Copytheexample’sChrome-onlyconfiguration:
$cp./node_modules/protractor/example/chromeOnlyConf.js.
4. OpenupthechromOnlyConf.jsandupdatethedrivertopointtothenode_modulesdirectory:
chromeDriver:'./node_modules/protractor/selenium/chromedriver',
5. UpdatethebaseURLvariable:
baseUrl:'http://localhost:8080/',
6. Updatethetestdirectory:
specs:['spec/e2e/**/*.js'],
7. AddngMockE2easadependencytotheproductmoduleintheapporproduct.jsfile:
angular.module('product',['ngMockE2e'])
8. Setupthemockrequest:
.run(['$httpBackend',function($httpBackend){
vartestProduct=productDataBuilder().build();
varproducts=[testProduct];
$httpBackend.whenGET('/products').respond(products);
}]);
9. Createtheindex.htmlpageusinganHTMLstub:
<!DOCTYPEhtml>
<html>
<head>
www.it-ebooks.info
![Page 232: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/232.jpg)
<title></title>
</head>
<body>
</body>
</html>
10. AddtheAngularJSreferences:
<scriptsrc="bower_components/angular/angular.js"></script>
</body>
11. Addtheproductmodule,controller,andservice:
<scriptsrc="app/product.js"></script>
<scriptsrc="app/productService.js"></script>
<scriptsrc="app/productController.js"></script>
12. Formockingpurposes,addAngularmocksandtheproductdatabuilder:
<scriptsrc="bower_components/angular-mocks/angular-mocks.js"></script>
<scriptsrc="spec/productDataBuilder.js"></script>
Theinitial’sindexpageandmockhasbeensetup.ThenextstepwillwalkthroughtheTDDlifecycleandgettheapplicationrocking.
www.it-ebooks.info
![Page 233: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/233.jpg)
TestfirstThefirststepinthelifecycleistocreatethetestsusingthe3A’s.Thetestconfirmsthattheproductdatawillbevisibleonthepageonceauserpushesabuttontogettheproductdata.
AssemblingtheproducttestHerearethestepstoassembletheProtractortest:
1. Createanewfileforthetestcalledspec/e2e/productScenario.js:
$touchproductScenario.js
2. Createtheteststub:
describe('',function(){
beforeEach(function(){
});
it('',function(){
});
});
3. Browsetheapplication:
beforeEach(function(){
browser.get('/index.html');
});
4. Findthebuttonthatwewillbeselecting:
beforeEach(function(){
varproductButton=element(by.buttonText('GetProducts'));
});
Nowthatthetesthasbeenassembled,wecanhittheobjectundertest.
GettingproductsTheactionofthistestistoselecttheproductbutton.AswehavealreadyretrievedthebuttonintheAssemblesection,wecannowclickonit:
beforeEach(function(){
varproductButton=element(by.buttonText('GetProducts'));
productButton.click();
});
Finally,itistimetocreatetheassertionsandexpectations.
ExpectingproductdataresultsTheassertionforthistestistoensurethattheproductdataisnowdisplayed.Herearethesteps:
1. Findtheresults:
www.it-ebooks.info
![Page 234: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/234.jpg)
varresults=element.all(by.repeater('resultinresults'));
2. Assertthatthecountisgreaterthan0:
expect(results.count()).toBeGreaterThan(0);
Thetestsetupiscomplete.Thenextstepistomakeitrun.
www.it-ebooks.info
![Page 235: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/235.jpg)
MakingtheproductdatarunAshasbeendonewiththeotherProtractortests,oneprocesswillberunningtheHTTPpageandtheotherwillberunningtheprotractortest:
1. Installhttp-serversothatwecanrunthewebsite:
$npminstallhttp-server
2. Startthewebsite:
$./node_modules/http-server/bin/http-server.
3. Inanothercommandwindow,runtheprotractortests:
$./node_modules/protractor/bin/protractorchromeOnlyConf.js
4. ThefirsterrorisError:Angularcouldnotbefoundonthepagehttp://localhost:8080/index.html:angularneverprovided
resumeBootstrap.Torectifythis,performthefollowingsteps:
1. Theprecedingerrorisduetothefactthatwehaven’treferencedtheapplicationmoduleinthewebpage.Addtheproductmoduletothebodyoftheapplication:
<bodyng-app='product'>
2. Rerunthetests.
5. ThenexterrorisNoSuchElementError:Noelementfoundusinglocator:by.buttonText("GetProducts").Torectifythis,performthefollowingstep:
1. Addthebutton:
<button>GetProducts</button>
6. ThenexterrorhashittheexpectationandstatesExpected0tobegreaterthan0.Tofixthis,weneedtofirstaddproductControllertothepage:
<divng-controller='ProductController'>
<button>GetProducts</button>
</div>
7. Thenextstepistoassociatethebutton-clickwiththeProductControllerclassesscopetogetallproducts:
<buttonng-click='getAll()'>GetProducts</button>
8. Thefinalstepistodisplayallresults:
<divng-repeat="resultinresults">
{{result}}
</div>
Thetestnowshowsasuccessfulresult.
www.it-ebooks.info
![Page 236: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/236.jpg)
Themakeitbetterstepwillbeskippedasthereisnothingimmediatethatneedstoberefactored.Atthispoint,theapplicationistestedandoperatedusingthemockeddata.Youshouldbeabletoseehowpowerfulthistechniquecanbeasyou’rebuildingupanapplication.Thenextsectionwilllookatremovingthescaffoldingandusinganactualbackend.
www.it-ebooks.info
![Page 237: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/237.jpg)
Testingend-to-endRemovetheAngularmocksscaffoldingandsetupthetesttoactuallyconnecttotherealserverandsetup.
ThebackendofAngularmocksallowedustocreatetheapplicationwithouttheneedtoactuallyreturndata.Nowthattheapplicationhasbeensetup,wecanremovethescaffoldingandcreatearealHTTPrequestforthedata.Herearethesteps:
1. RemovengMockE2eandthemockresponsefromtheproductsmoduleinapp/product.js:
angular.module('product',[]);
RemoveAngularmocksandproductDataBuilderfromtheindex.htmlpage
2. ReruntheProtractortest.3. Theerrorstatesthefailedexpectation.
NowthatthemockHTTPresponsehasbeenremoved,weneedtoaddanactualrequest.Luckilyforus,wedon’thavetouseanyothertoolorframeworkandcanusethehttp-servermodulethatwehavebeenusingthewholetime.Inareal-worldexample,theproductroutewouldliveinaseparateservice,butthisexamplewilluseasimplerapproachforbrevity.
www.it-ebooks.info
![Page 238: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/238.jpg)
GettingtheproductdataThehttp-servermodule,whichisusedtoservestaticcontent,canbeextendedtoservestaticcontentaswell.Thisallowsustosetupastaticfilethatmirrorsarequestroute.Inthiscase,asingleJSONfileofproductswillbeused.Theproductsfilewillhaveanarrayofproductdata.Herearethesteps:
1. Createanewfilenamedproductsintherootoftheproject:
$touchproducts
2. Openthefileandaddthefollowingcontent:
[{
"id":1,
"name":"productName"
}]
Now,the/productsrouteisavailableandwillreturnanarrayofproducts.ReruntheProtractortest,andconfirmthatitispassing.Withthesesimpletests,wehavetestedtheapplicationend-to-endandsuccessfullyremovedthemockscaffolding.
Thisconcludesthewalk-throughofusingTDDtocreateanAngularJSRESTlayer.
www.it-ebooks.info
![Page 239: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/239.jpg)
Self-testquestionsQ1.Acallbackfunctionreferstoafunctionthatiscalledafteranasynchronousfunctioncompletes.
1. True2. False
Q2.AnXMLHttpRequestcannotsendorreceiveJSON.
1. True2. False
Q3.RESTstandsfor:
1. RepresentationalStateTransfer2. Nothing3. RepeatableEndpointStateTransfer
Q4.Asynchronousfunctionsalwayscompleteintheorderinwhichtheywerecalled.
1. True2. False
Q5.Therearetwodifferentimplementationsof$httpBackend:oneforunitandoneforend-to-endtesting.
1. True2. False
www.it-ebooks.info
![Page 240: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/240.jpg)
SummaryThischapterexplainedthedetailsbehindRESTrequests,asynchronoustesting,andthemockingofAngularHTTPrequestsinKarmaandProtractor.Ithasbroughttogethermanyofthetechniquesandtoolsusedthroughoutthebook.Specifically,ithasshowedushowtoapplytheTDDlifecycle(testfirst,makeitrun,andmakeitbetter)toincrementallybuildyourapplicationstoaspecificationandhowtousethe3A’s(Assemble,Act,andAssert)toconstructatest.
Asyoucompletethisbookandgoaboutapplyingthetechniquesintherealworld,rememberthatknowingwhattotestisjustasimportantasknowinghowtotest.Thisbookhasshownyouhow;itisuptoyoutopracticeandcontinuetoimproveyourdevelopmentskillsthroughTDD.
www.it-ebooks.info
![Page 241: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/241.jpg)
AppendixA.IntegratingSeleniumServerwithProtractorThroughoutthisbook,weusedSeleniumChromeDrivertotestwithProtractor.WhatthismeantwasthatinordertorunaProtractortest,wesimplyhadtohavethewebsiterunningandthenkickoffProtractor.InChapter3,End-to-endTestingwithProtractor,ChromeDriverwasinstalledandusedtorunthetests.FromtheperspectiveofthebookandTDD,thiswasacceptable.Ourtestsweresmallandcontainedanddidnothavealotofmovingparts.
TheproblemwithonlyusingChromeDriveristhatwecan’ttestonotherbrowsers.Asyourapplicationgrowsandyouwanttosupportmorebrowsers,youneedtothinkaboutrunningastandaloneSeleniumServer.Thissectionofthebookprovidesawalk-throughofhowtogetastandaloneSeleniumServerrunningandintegratedwithProtractor.
www.it-ebooks.info
![Page 242: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/242.jpg)
InstallationThegoodthingaboutinstallationisthatwehavealreadydoneitbefore.EverytimeweinstalledChromeDriver,thefirstthingwedidwasinstallSelenium.Herearethestandardsteps:
1. InstalltheProtractornpmmodule:
$npminstallprotractor
2. InstallSeleniumWebDriver:
$./node_modules/protractor/bin/webdriver-managerupdate
That’sit.Seleniumisnowinstalledandisreadytobeused.Inthenextsection,wewillseehowtoupdatetheProtractorconfigurationtousetheSeleniumstandaloneserver.
www.it-ebooks.info
![Page 243: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/243.jpg)
ProtractorconfigurationLuckilyforus,wedon’thavetorememberallthebasicconfigurationsforProtractor.Withinnpm_modules,thereareexamplesthatwecanuse.HerearethestepstocopytheSeleniumstandaloneconfiguration:
1. OpenuptheexampleProtractorconfigurationfilethatislocatedinthefollowingdirectory:
./node_modules/protractor/example/conf.js
2. Copythefiletoyourlocaltestfolder:
$cp./node_modules/protractor/example/conf.js
TheconfigurationshouldlookverysimilartothechromeOnlyconfiguration.Hereisasnippetoftheimportantconfigurationitems:
exports.config={
seleniumAddress:'http://localhost:4444/wd/hub',
capabilities:{
'browserName':'chrome'
},
…
};
ThefirstimportantitemistheseleniumAddressobject.Theaddressisthehostname,port,andlocationwheretheSeleniumServerisrunning.Thenextimportantitemisthecapabilitiesobject.Browser-specificcapabilitiesgiveyoutheabilitytodefinewhichbrowserswillbetestedagainst.AswearenotusingtheChromeOnlyconfiguration,youcannowchooseInternetExplorer(IE),Firefox,andsoon.Formoreinformationonmultiplebrowsersupportandcapabilities,refertotheProtractordocumentationathttps://github.com/angular/protractor/blob/master/docs/browser-setup.md
Inthenextsection,wewilllookathowtorunSelenium.
TipTheseleniumAddressobjectismeanttobeconfigurablesothatyoucanhaveaseparateinstanceinacompletelydifferentlocationthanyourdevelopmentmachine.VisittheSeleniumsiteformoreinformationathttp://www.seleniumhq.org/.
www.it-ebooks.info
![Page 244: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/244.jpg)
RunningSeleniumSeleniumisquitestraightforwardtostart.Oncerun,itcanjustsitinthebackgroundwhilethetestsarerunning:
1. StarttheSeleniumstandaloneservice:
$./node_modules/protractor/bin/webdriver-managerstart
2. Theconsolewindowwilldisplayseveralinformationmessages.Ensurethefollowingmessagesaredisplayed:
3. Youshouldensurethatthedefaultportused,ascanbeseenintheRemoteWebDrivermessageintheprecedingmessages,isthesameastheonethatisconfiguredintheProtractorconfiguration:
seleniumAddress:'http://localhost:4444/wd/hub',
…
www.it-ebooks.info
![Page 245: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/245.jpg)
LetitrunSeleniumisnowrunningonthe4444localhostport.InordertoensurethatProtractorcancommunicatewithSelenium,let’srunasimpletesttoensureeverythingisworking.Aswehavedonethroughoutthebook,wewillfollowtheTDDstepseventhoughthiswillbeanextremelyshortandsimpletest.AsProtractorisinstalled,theonlyotherprerequisiteistoinstallanHTTPserver.Installhttp-serverusingthefollowingcommand:
$npminstallhttp-server
Onceitisinstalled,starttheserver:
$./node_modules/http-server/bin/http-server
www.it-ebooks.info
![Page 246: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/246.jpg)
TestfirstThetestwillcheckwhetherthetitleofthepageisequaltoseleniumTestTitle.CreateanewProtractortestfilenamedscenario.js.
AssembleTosetupthetest,weneedtonavigatethebrowsertotherootofthewebapplication:
beforeEach(function(){
browser.get("/");
});
ThereisnoActsectionaswewillsimplybecheckingthattheloadedindexpagehasthetitleweneed.
AssertTheassertneedsgetthetitleandcompareitwiththeexpectedvalue:
it('',function(){
expect(browser.getTitle()).toBe('seleniumTestTitle');
});
www.it-ebooks.info
![Page 247: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/247.jpg)
MakeitrunNowthatthetestisprepared,wecanstartrunningtheProtractortestthroughthestandaloneSeleniumServer.HerearethestepstoruntheProtractortest:
1. AddthetestfiletotheProtractorconfiguration:
specs:['scenario.js'],
2. CreateanemptyHTMLpagethatwillbeusedtomakethetestrun:
<!DOCTYPEhtml>
<html>
<head>
<title></title>
</head>
<body>
</body>
</html>
3. AddtheindexpagetotheProtractorconfiguration:
specs:['scenario.js','index.html'],
4. Runthetest:
$./node-modules/protractor/bin/protractorconf.js
5. ThefirsterrorisAngularcouldnotbefoundonthepagehttp://localhost:8080/index.html:retrieslookingforangularexceeded.Torectifythis,performthefollowingsteps:
1. AngularJShasnotbeenaddedtothepage.Installangularthroughbower:
$bowerinstallangular
2. AddtheAngularJSreferencetotheindex.htmlpage:
<scripttype="text/javascript"
src="bower_components/angular/angular.js"></script>
3. Rerunthetest.
6. ThenexterrorisAngularcouldnotbefoundonthepagehttp://localhost:8080/index.html:angularneverprovidedresumeBootstrap.ThiserrormeansthatAngularJScouldn’tloadthemainmoduleofyourapplication.Torectifythis,performthefollowingsteps:
1. Addasimplemoduleintothebodytag:
<bodyng-app='test'>
2. Initializethemoduleinthelasttag:
www.it-ebooks.info
![Page 248: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/248.jpg)
<scripttype="text/javascript"
src="bower_components/angular/angular.js"></script>
<scripttype="text/javascript">
angular.module('test',[]);
</script>
3. Rerunthetest.
7. Thenexterrorhashittheexpectation:Expected‘http://localhost:8080/index.html’tobe‘seleniumTestTitle’.Herearethestepstorectifythiserror:
1. Setthetitleofthewebpagetotheexpectation:
<title>seleniumTestTitle</title>
2. Rerunthetest.
8. TheProtractoroutputnowreports1test,1assertion,0failures.Withthesuccessofthetest,wehavenowsuccessfullyshownyouhowtousetheSeleniumstandaloneserver.
www.it-ebooks.info
![Page 249: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/249.jpg)
SummaryThisappendixhasshownyouhowtosetupandusetheSeleniumstandaloneserver.Therearemanyoptionsandadvantagesofusingthestandaloneserver.TheadvantagesaregearedmoreforadvancedtestingwhenyouwanttouseadedicatedSeleniumServeroraPaaS(PlatformasaService)orifyouwanttotestafunctionalityondifferentbrowsersandasthevolumeofyourProtractortestsgrow.Formoreinformation,visittheSeleniumhomepageathttp://www.seleniumhq.org/.
www.it-ebooks.info
![Page 250: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/250.jpg)
AppendixB.AutomatingKarmaUnitTestingonCommitRunningtestslocallyisonething,buthowdoyouknowwhethertheywillworkonsomeoneelse’scomputer.Settingupcontinuoustestingandintegrationshouldbepartofeveryapplicationyouwrite.Oneofthebestthingsisthatthetoolstosetuparefree,easytouse,andbestofall,theygettoshowcaseyourtests!ThefollowingsectionwillexplorehowtosetupcontinuousintegrationusingGitHubforsourcecontrolandTravisforcontinuousintegration.
www.it-ebooks.info
![Page 251: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/251.jpg)
GitHubGitHubisasourcecontrol,collaboration,andall-aroundawesometool.Foropensourceprojects,itisfree.Onceyousignup,youcangetstartedandcreateanewrepositoryforyourproject.GitHubprovidesaGitURLforeveryproject;theURLcanthenbesetuptopushchangeslikeanyotherGitrepository.OneofthebenefitsofusingGitHubisthatitautomaticallyprovideshooksintootherapplicationsandservices.WhensettingupcontinuousintegrationandtestingthroughTravisCI,youwillleveragetheTravisCIGitHubhook.
www.it-ebooks.info
![Page 252: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/252.jpg)
TestsetupInordertorunKarmaproperly,wewillneedtoaddthefollowingdevelopmentdependencies:
karma:ThebaseKarmainstallationkarma-jasmine:Thetestrunnerkarma-phantomjs-launcher:ThePhantomJSheadlessbrowserpluginwediscussedandsetupinChapter5,FlipFlop
InstallthefollowingKarmadevdependencies:
$npminstallkarma--save-dev
$npminstallkarma-jasmine--save-dev
$npminstallkarma-phantomjs-launcher--save-dev
www.it-ebooks.info
![Page 253: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/253.jpg)
TestscriptsWhenusingTravisCI,ascripttorunthetestsneedstobedefined.Thebestplacetodefineascriptisinthepackage.jsonfile.Thepackage.jsonfileisusedinseveralwaysbynode.js.Herearethestepstorunthetest:
1. Thetestscriptcanthenberunwhenyoutypethefollowingcommandinthecommandprompt:
$npmtest
2. Updatethepackage.jsonscriptssectionasshowninthefollowingcodesnippet:
"scripts":{
"start":"nodeapp.js",
"test":"karmastart--single-run--browsersPhantomJS"
}
3. Confirmthatthetestscriptworks:
$npmtest
PhantomJSallowsteststorunontheTravisCIserverswithouttheneedforaUI.Thefollowingisasampleoutput:
Theapplicationsetupisnowconfiguredtorununittestsviathenpmtestcommand.ThiswillbeusedbyTravisCItorunthetests.
www.it-ebooks.info
![Page 254: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/254.jpg)
SettingthehookGitHubprovidesseveralhooksintootherapplications.Ahookallowsyoutochainactionswhenacommitoccurs.Ahookisanextremelyusefulfeaturefromacontinuousintegrationstandpointbecausewecansetupthecodetobetestedoneverycommit.TravisCIhasaGitHubhookthatcanbeeasilysetuponanyGitHubrepository.Thefollowingisawalk-throughonhowtocreateaTravisCIhookonyouropensourcerepository.
www.it-ebooks.info
![Page 255: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/255.jpg)
CreatingthehookHerearethestepstocreatethehook:
1. CreateaTravisCIaccountbygoingtotheTravisCIpageathttps://travis-ci.organdclickonSigninwithGitHub.Confirmthequestionsitasksandcontinue.
2. ActivateaGitHubWebhooktoTravisCI.YoucansetuptheWebhookinTravisCIthroughyourprofileURLathttps://travis-ci.org/profile
3. Turntheswitchon.Intheprofile,youshouldseeyourrepository.
HereisabeforeviewofWebhook(Switchoff):
HereisaviewoftheWebhookafteritisenabled(Switchon):
www.it-ebooks.info
![Page 256: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/256.jpg)
AddingaTravisconfigurationfileTravisrequiresaconfigurationfiletobeattherootofyourrepositorynamed.travis.yml.Theconfigurationfilecontainsthesourcecodelanguage,languageversioning,metadata,andotherinformation.Thetemplateconfigurationwilllookasfollows:
language:node_js
node_js:
-"0.10"
Besidesthebasicconfigurationintheprecedingcode,additionalsetupisneededtorunKarmatests.Thebefore_scriptconfigurationwillbeusedtoinstallKarmaandBowerpriortorunninganytests.HereiswhattheconfigurationneedstolooklikeinordertoinstallKarmaandBowerbeforeanytestsrun:
language:node_js
node_js:
-"0.10"
before_script:
-npminstall-gkarma-cli
-npminstall-gbower
-bowerinstall
Nowthetestsarereadytoberun.Addtheprecedingcontentstoanewfilenamedtravis.yml.Bydefault,theNode.jsprojectwillexecutethenpmtestcommandinTravis.Thisiswhyyoudon’tneedtospecifytheactualcommandtotestyourapplication.
NotePleasenotethatTravisCIiscasesensitive.
Thefollowingscreenshotisanexampleofwhattheprecedingcodelookslike:
www.it-ebooks.info
![Page 257: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/257.jpg)
Ifyouhaveanyissues,gototheTravisCIGettingstartedguideathttp://docs.travis-ci.com/user/getting-started/.
www.it-ebooks.info
![Page 258: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/258.jpg)
ReferencesThefollowingaresomereferencesthatmayhelpyouwiththeconcepts:
ThisformofuserspecificationiswrittenusingtheGerkinsyntax.TheGerkinsyntaxallowsyoutowritethespecificationsinawell-formattedmanner.Seethefollowinglinkformoredetails:http://en.wikipedia.org/wiki/Behavior-driven_development.TheJavaScriptJabberhomepagecanbefoundathttp://javascriptjabber.com/106-jsj-protractor-with-julie-ralph/TheGitHubpageforhttp-servercanbefoundathttps://github.com/nodeapps/http-server
www.it-ebooks.info
![Page 260: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/260.jpg)
Chapter1,IntroductiontoTest-drivenDevelopmentQ1 2
Q2 1
Q3 1
Q4 1
Q5 2
www.it-ebooks.info
![Page 262: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/262.jpg)
Chapter3,End-to-endTestingwithProtractorQ1 1
Q2 1
Q3 1
www.it-ebooks.info
![Page 267: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/267.jpg)
IndexA
3A’sreferencelink/Testingtechniques
3A’sassemble/Assemble,Act,andAssert(3A’s)act/Assemble,Act,andAssert(3A’s),Assemble,Act,Assert(3A’s)assert/Assemble,Act,andAssert(3A’s),Assemble,Act,Assert(3A’s)assemble/Assemble,Act,Assert(3A’s)
3A’s,applicationtoentercommentsassemble/Assembleact/Actassert/Assert
3A’s,commentaddingspecificationassemble/Assembleact/Actassert/Assert
3A’s,commentlikingspecificationassemble/Assembleact/Actassert/Assert
AngularJSinstalling/InstallingAngularJS
AngularJScomponentsattributes/Servicesdirectives/Servicescontrollers/Servicesservices/Services
AngularJSREST,testingwithabout/TestingwithAngularJSRESTproductservice,testing/Testingtheproductservice$http,testingwithKarma/Testing$httpwithKarma
AngularJSroutesabout/Walk-throughofAngularroutessettingup/SettingupAngularJSroutesdirections,defining/Definingdirectionsflipfloptest,assembling/Assemblingtheflipfloptest
AngularJSservicesabout/Services
AngularMocksinstalling/InstallingAngularmocksURL/InstallingAngularmocks
www.it-ebooks.info
![Page 268: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/268.jpg)
applicationtoentercommentsspecification,preparing/Preparingtheapplication’sspecificationsettingup/Settinguptheprojectdirectory,settingup/SettingupthedirectoryProtractor,installing/SettingupProtractorProtractor,settingup/SettingupProtractorKarma,settingup/SettingupKarmahttp-serversetup/Settinguphttp-serverKarmaconfiguration/ConfiguringKarma
applicationtoentercomments,TDDlifecycleabout/Bringonthecommentstestfirst/Testfirst3A’s/Testfirsttest,running/Makeitrunmodule,adding/Addingthemoduleinput,adding/Addingtheinputcontroller/Controllertest,passing/Makeitpasstest,improving/Makeitbetter
asynchronouscallstesting/Testingasynchronouscallscreating,inKarma/CreatingasynchronouscallsinKarmacreating,inProtractor/CreatingasynchronouscallsinProtractor
asyncmagiccomponents,Protractorabout/Asyncmagicpage,loadingbeforetestexecution/Loadingapagebeforetestexecutionassertiononelements/Assertiononelementsthatgetloadedinpromises
www.it-ebooks.info
![Page 269: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/269.jpg)
BbeforeEachparameter
about/Testfirst,Testfirstbottom-upapproach
about/Top-downorbottom-upapproachusing/Usingabottom-upapproach
Bowerabout/Bowerinstalling/Bowerinstallation
broadcasttesting/Testingbroadcast,Testingbroadcast
builderobjectabout/Buildingwithabuilder
builderpatternabout/Buildingwithabuilder
www.it-ebooks.info
![Page 270: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/270.jpg)
C$controllervariable
about/Assemble,Act,andAssert(3A’s)Chrome
about/InstallationprerequisitesURL/Installationprerequisites
commentlikingspecificationabout/Onwardsandupwardstesting,withProtractortesttemplate/Testfirst3A’s/Testfirsttest,running/Makeitrununittests,fixing/Fixingtheunitteststest,improving/Makeitbettertest,coupling/Couplingofthetest
controllertesting/Testingacontrollersimplecontrollertestsetup/Asimplecontrollertestsetupscope,initializing/Initializingthescope
curltoolabout/REST–thelanguageoftheWeb
www.it-ebooks.info
![Page 271: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/271.jpg)
Ddescribeparameter
about/Testfirst,TestfirstDescribeproperty,Karmatest/TestingwithKarmadirections,AngularJSroutes
ngRoute,configuring/ConfiguringngRouteroutecontrollers,defining/Definingtheroutecontrollersrouteviews,defining/Definingtherouteviews
documentation,TDDabout/FundamentalsofTDD
DocumentObjectModel(DOM)/TDDwithProtractor
www.it-ebooks.info
![Page 272: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/272.jpg)
Eemit
about/Emittingtesting/Testingemit
end-to-endtestingabout/Gettingdowntobusiness,Testingend-to-endspecification,reviewing/Specificationdevelopmentto-dolist/Thedevelopmentto-dolistTDDprocess/Testfirstproductdata,obtaining/Gettingtheproductdata
end-to-endtesting,productcartend-to-endtest,assembling/Assemblingthecart’send-to-endtestsavetocartaction,invoking/Invokingasavetocartactionsavedproducts,confirming/Confirmingproductshavebeensavedend-to-endtest,passing/Makingthecart’send-to-endtestpass
end-to-endtesting,recentlyvieweditemsabout/End-to-endtestingtestfirst/Testfirstrecentlyviewedend-to-endtest,assembling/Assemblingtherecentlyviewedend-to-endtestsearchresult,selecting/Selectingasearchresultrecentlyvieweditems,confirming/ConfirmingrecentlyvieweditemsrecentlyViewedItemstest,passing/MakingtherecentlyViewedItemstestpassrecentlyViewedItemstest,improving/Makingrecentlyvieweditemsbetter
end-to-endtests,Protractortestwebserver,installing/Installingthetestwebserver
events,insearchapplicationimplementing/Harnessingthepowerofeventsplan/Theplanrebranding/Rebrandingrecentlyvieweditems,viewing/Seeingrecentlyvieweditemsproductcart,creating/Creatingaproductcart
Expectproperty,Karmatest/TestingwithKarma
www.it-ebooks.info
![Page 273: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/273.jpg)
Fflipfloptest,AngularJSroutes
viewsflip,creating/Makingtheviewsflipflip,asserting/Assertingafliprunning/Makingflipfloprunimproving/Makingflipflopbetter
FunctionUnderTest/Testingtechniquesfundamentals,searchapplication
Protractorlocators/Protractorlocators
www.it-ebooks.info
![Page 275: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/275.jpg)
H$httpBackendproperty/Testing$httpwithKarmaheadlessbrowsertesting,forKarma
settingup/SettingupheadlessbrowsertestingforKarmapreconfiguration/Preconfigurationconfiguration/Configuration
http-servermodule/Gettingtheproductdataabout/Gettingtheproductdata
HTTPmethodsabout/REST–thelanguageoftheWebGET/REST–thelanguageoftheWebPOST/REST–thelanguageoftheWebPUT/REST–thelanguageoftheWebDELETE/REST–thelanguageoftheWeb
www.it-ebooks.info
![Page 276: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/276.jpg)
Iinjectvariable
about/Assemble,Act,andAssert(3A’s)installation
Karma/InstallingKarmaProtractor/Protractorinstallation
itparameterabout/Testfirst,Testfirst
Itproperty,Karmatest/TestingwithKarma
www.it-ebooks.info
![Page 277: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/277.jpg)
JJasmine
about/Jasminepros/Jasminecons/Jasmine
Jasminespyused,forcreatingtestdouble/TestingdoubleswithJasminespies
JavaScripttestingframeworksabout/JavaScripttestingframeworksJasmine/JasmineSelenium/SeleniumMocha/Mocha
JavaScripttestingtoolsabout/JavaScripttestingtoolsKarma/KarmaProtractor/Protractor
www.it-ebooks.info
![Page 278: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/278.jpg)
KKarma
about/Karmapros/Karmacons/Karmabirth/BirthofKarmafeatures/TheKarmadifferencecombining,withAngularJS/ImportanceofcombiningKarmawithAngularJSinstalling/InstallingKarmaURL/InstallingKarmaprerequisites,forinstallation/Installationprerequisitesconfiguring/ConfiguringKarmaconfiguration,customizing/CustomizingKarma’sconfigurationinstallation,confirming/ConfirmingKarma’sinstallationandconfiguration,ConfirmingtheKarmainstallationconfiguration,confirming/ConfirmingKarma’sinstallationandconfigurationcommoninstallation/configurationissues/Commoninstallation/configurationissuestesting,with/TestingwithKarmainitializing/InitializingKarma
Karma,usingwithAngularJSabout/UsingKarmawithAngularJSAngularJS,obtaining/GettingAngularJStesting,with/TestingwithAngularJSandKarmadevelopmentto-dolist/Adevelopmentto-dolistlistofitems,testing/TestingalistofitemsTDDprocess/Testingalistofitemsfunction,addingtocontroller/Addingafunctiontothecontroller
karma.conffile/InitializingKarmaKarmaconfiguration
about/Karmaconfigurationfilewatching/Filewatching
Karmaconfiguration,applicationtoentercommentstesting/Testfirst3A’s/Testfirsttest,running/Makeitruntest,improving/Makeitbettertestchain,backingup/Backupthetestchaininput,binding/Bindtheinput
Karmadevdependencieskarma/Testsetupkarma-jasmine/Testsetupkarma-phantomjs-launcher/Testsetup
www.it-ebooks.info
![Page 279: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/279.jpg)
installing/TestsetupKarmaunittesting
testsetup/Testsetuptestscripts/Testscriptshook,setting/Settingthehookhook,creating/CreatingthehookTravisconfigurationfile,adding/AddingaTravisconfigurationfile
www.it-ebooks.info
![Page 280: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/280.jpg)
Mmessages
publishing/Publishingandsubscribingmessagessubscribing/Publishingandsubscribingmessages
middle-to-endtestingabout/Testingmiddle-to-endtestfirst/Testfirstproducttest,assembling/Assemblingtheproducttestproducts,obtaining/Gettingproductsproductdataresults,expecting/Expectingproductdataresultsproductdata,running/Makingtheproductdatarun
Mochaabout/Mochapros/Mochacons/Mocha
www.it-ebooks.info
![Page 281: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/281.jpg)
NNode.js
URL/Installationprerequisites,Installationprerequisitesabout/Installationprerequisites
NodePackageManager(npm)modules/Mocha
www.it-ebooks.info
![Page 282: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/282.jpg)
PPhantomJS
URL/SettingupheadlessbrowsertestingforKarmaPhantomJSbrowserplugin
URL/Preconfigurationprerequisites,Protractorinstallation
Node.js/InstallationprerequisitesChrome/InstallationprerequisitesSeleniumWebDriverforChrome/Installationprerequisites
productcartcreating/Creatingaproductcartpublishertestfirst/PublishertestfirstsearchDetailController,assembling/AssemblingsearchDetailControllerproductsaving,invoking/Invokingthesavingofaproductsaveevent,confirming/ConfirmingthesaveeventsaveProducttest,passing/MakingthesaveProducttestpasssubscriberunittest/Testforthesubscriberfirsttest,assembling/Assemblingtheproductcarttestsavedcartevent,invoking/Invokingasavedcarteventsavedcart,confirming/Confirmingthesavedcartcartcontrollertest,running/Makingthecartcontrollertestrunend-to-endtesting/End-to-endtesting
productdatacontrollerabout/Theproductdatacontrollerproductcontrollertest,assembling/Assemblingtheproductcontrollertestproducts,obtaining/Gettingproductsproductdataresults,asserting/Assertingproductdataresults
productdataserviceabout/Theproductdataservice
productrequests,unittestingabout/Unittestingproductrequestsproject,settingup/SettinguptheprojectKarmaconfiguration/KarmaconfigurationAPIbuilderpattern,using/UsinganAPIbuilderpattern
products,displayingwithRESTabout/DisplayingproductswithRESTproductrequests,unittesting/Unittestingproductrequestsproductdataservice/Theproductdataserviceproductdatacontroller/Theproductdatacontrollerproductdatatests,running/Makingtheproductdatatestsrun
Protractorabout/Protractor,AnoverviewofProtractorpros/Protractor
www.it-ebooks.info
![Page 283: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/283.jpg)
cons/Protractoroverview/AnoverviewofProtractororigins/OriginsofProtractorbirth/ThebirthofProtractorfeatures/LifewithoutProtractorURL/Commoninstallation/configurationissuesrealtest/HelloProtractorTDD,using/TDDend-to-endpre-setup/Thepre-setupsetup/Thesetupend-to-endtests/Testfirstconfiguring/ConfiguringProtractorgaps,cleaningup/Cleaningupthegapsasyncmagiccomponents/AsyncmagicTDD,implementingwith/TDDwithProtractor
Protractorinstallationabout/Protractorinstallationreferencelink,forguide/Protractorinstallationprerequisites/Installationprerequisitesperforming/InstallingProtractorWebDriver,installingforChrome/InstallingWebDriverforChromeconfiguration,customizing/Customizingconfigurationconfirming/Confirminginstallationandconfigurationconfiguration,confirming/Confirminginstallationandconfigurationcommonissues/Commoninstallation/configurationissues
Protractorlocatorsabout/ProtractorlocatorsCSSlocators/CSSlocatorsbuttontextlocator/Buttonandlinklocatorslinktextlocator/ButtonandlinklocatorsAngularlocators/AngularlocatorsURLlocationreferences/URLlocationreferences
publishingandsubscribingmessages/Publishingandsubscribingmessagesissues/Publishingandsubscribing–thegoodandbadscenarios/Thegoodcommunicating,throughevents/Communicatingthrougheventscoupling,reducing/Reducingcoupling
www.it-ebooks.info
![Page 284: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/284.jpg)
Rrecentlyvieweditems,viewing
about/Seeingrecentlyvieweditemstestfirst/Testfirstend-to-endtesting/End-to-endtesting
recentlyviewedtestwriting/TestfirstSearchController,assembling/AssemblingSearchControllerproduct,selecting/Selectingaproductevents,tobepublished/Expectingeventstobepublishedsearchcontrollerrun,creating/Makingthesearchcontrollerrununittest/Recentlyviewedunittest
recentlyviewedunittestabout/Recentlyviewedunittestwriting/TestfirstRecentlyViewedController,assembling/AssemblingRecentlyViewedControllerrecentlyvieweditem,invoking/InvokingarecentlyvieweditemRecentlyViewedController,confirming/ConfirmingRecentlyViewedControllerRecentlyViewedController,running/MakingRecentlyViewedControllerrun
refactoring,TDDabout/FundamentalsofTDD,Refactoring
RESTabout/REST–thelanguageoftheWebgettingstartedprocess/GettingstartedwithREST
RESTrequestscreating,AngularJSused/MakingRESTrequestsusingAngularJStesting,withAngularJSREST/TestingwithAngularJSRESTmocking,withProtractor/MockingrequestswithProtractor
www.it-ebooks.info
![Page 285: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/285.jpg)
SSaaS(SoftwareasaService)/LifewithoutProtractorSauceLabs
URL/LifewithoutProtractorScenarioRunner
about/Endoflifescopevariable
about/Assemble,Act,andAssert(3A’s)searchapplication
fundamentals/Fundamentalscreating/Creatinganewprojectheadlessbrowsertesting,settingupforKarma/SettingupheadlessbrowsertestingforKarma
searchapplication,TDDwayabout/SearchingtheTDDway,Thesearchapplicationapproach,decidingon/Decidingontheapproachsearchquery/Walk-throughofsearchquerysearchquerytest/ThesearchquerytestsearchqueryHTMLpage/ThesearchqueryHTMLpage
searchresults,searchapplicationabout/Showmesomeresults!searchresultroutes,creating/Creatingthesearchresultroutestesting/Testingthesearchresultssearchresulttest,assembling/Assemblingthesearchresulttestselecting/Selectingasearchresultconfirming/Confirmingasearchresultsearchresulttest,running/Makingthesearchresulttestruntesting,forlocation/Creatingalocation-awaretestimproving/MakingthesearchresultbetterrouteID,confirming/ConfirmingtherouteIDrouteIDunittest,settingup/SettinguptherouteIDunittestrouteIDunittest,confirming/ConfirmingtheIDrouteparameterstest,running/Makingtherouteparameter’stestrun
SeleniumURL/Seleniumabout/Seleniumpros/Seleniumcons/Seleniuminstalling/InstallationProtractorconfiguration/Protractorconfigurationrunning/RunningSelenium,Letitruntestfirst/Testfirst
SeleniumWebDriver,forChrome
www.it-ebooks.info
![Page 286: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/286.jpg)
about/Installationprerequisitesinstalling/InstallingWebDriverforChrome
success,measuringinTDDsteps,breakingdown/Breakingdownthestepstestfirstmethodology/Measuretwicecutonce
www.it-ebooks.info
![Page 287: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/287.jpg)
TTDD
about/AnoverviewofTDD,TDDend-to-endfundamentals/FundamentalsofTDDbenefits/FundamentalsofTDDsuccess,measuring/Measuringsuccesstestingtechniques/Testingtechniquesapplying/TDDend-to-end
TDDlifecycleabout/Divingintest,settingup/Settingupthetestdevelopmentto-dolist,creating/Creatingadevelopmentto-dolisttestfirst/Testfirsttest,running/Makingitruntest,improving/Makingitbetter
TDDprocess,end-to-endtestingtestfirst/Testfirst3A’s/Assemble,Act,Assert(3A’s)test,running/Makeitruntest,improving/Makeitbetter
TDDprocess,foraddingfunctiontocontrollerabout/Addingafunctiontothecontrollertestfirst/Testfirst3A’s/Assemble,Act,andAssert(3A’s)test,running/Makeitruntest,improving/Makeitbetter
TDDprocess,fortestinglistofitemstestfirst/Testfirst3A’s/Assemble,Act,andAssert(3A’s)test,running/Makeitruntest,improving/Makeitbetter
test,Seleniumassemble/Assembleassert/Assertrunning/Makeitrun
testdoubleabout/TestingdoubleswithJasminespiesusing/TestingdoubleswithJasminespiescreating,Jasminespyused/TestingdoubleswithJasminespiesreturnvalue,stubbing/Stubbingareturnvaluearguments,testing/Testingarguments
testingframeworkabout/Testingwithaframework
www.it-ebooks.info
![Page 288: 2.droppdf.com2.droppdf.com/files/6uXTX/angularjs-test-driven-development.pdf · Table of Contents AngularJS Test-driven Development Credits About the Author About the Reviewers Support](https://reader034.vdocuments.mx/reader034/viewer/2022042223/5ec9755e3194143a89736beb/html5/thumbnails/288.jpg)
testingtechniques,TDDabout/Testingtechniquestestingframework/Testingwithaframeworktestdouble/TestingdoubleswithJasminespiestestdouble,usingJasminespy/TestingdoubleswithJasminespiesrefactoring/Refactoringbuilding,withbuilder/Buildingwithabuilder
ToBeTruthyproperty,Karmatest/TestingwithKarmatop-downapproach
about/Top-downorbottom-upapproachTravisCI
configurationfile/AddingaTravisconfigurationfileURL/AddingaTravisconfigurationfile
TravisCIhookcreating/Creatingthehook
www.it-ebooks.info