AngularJS Test-driven Development -...
Transcript of AngularJS Test-driven Development -...
![Page 3: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/13.jpg)
Chapter3,End-to-endTestingwithProtractor
Chapter4,TheFirstStep
Chapter5,FlipFlop
Chapter6,TellingtheWorld
Chapter7,GiveMeSomeData
Index
www.it-ebooks.info
![Page 15: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/22.jpg)
Whysubscribe?FullysearchableacrosseverybookpublishedbyPacktCopyandpaste,print,andbookmarkcontentOndemandandaccessibleviaawebbrowser
www.it-ebooks.info
![Page 23: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/23.jpg)
FreeaccessforPacktaccountholdersIfyouhaveanaccountwithPacktatwww.PacktPub.com,youcanusethistoaccessPacktLibtodayandview9entirelyfreebooks.Simplyuseyourlogincredentialsforimmediateaccess.
www.it-ebooks.info
![Page 24: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/26.jpg)
WhothisbookisforThisbookisforthedeveloperwhowantstogobeyondthebasictutorials,andwantstotaketheplungeintoAngularJSdevelopment.ThisbookisforthedeveloperwhohasexperiencewithAngularJSandhaswalkedthroughthebasictutorialsbutwantstounderstandthewidercontextofwhen,why,andhowtoapplytestingtechniquesandbestpracticestocreatequality-cleancode.Togetthemostoutofthisbook,itispreferredthatthereaderhasbasicunderstandingofHTML,JavaScript,andAngularJS.
www.it-ebooks.info
![Page 27: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/29.jpg)
CustomersupportNowthatyouaretheproudownerofaPacktbook,wehaveanumberofthingstohelpyoutogetthemostfromyourpurchase.
www.it-ebooks.info
![Page 30: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/30.jpg)
DownloadingtheexamplecodeYoucandownloadtheexamplecodefilesfromyouraccountathttp://www.packtpub.comforallthePacktPublishingbooksyouhavepurchased.Ifyoupurchasedthisbookelsewhere,youcanvisithttp://www.packtpub.com/supportandregistertohavethefilese-maileddirectlytoyou.
www.it-ebooks.info
![Page 31: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/32.jpg)
PiracyPiracyofcopyrightmaterialontheInternetisanongoingproblemacrossallmedia.AtPackt,wetaketheprotectionofourcopyrightandlicensesveryseriously.Ifyoucomeacrossanyillegalcopiesofourworks,inanyform,ontheInternet,pleaseprovideuswiththelocationaddressorwebsitenameimmediatelysothatwecanpursuearemedy.
Pleasecontactusat<[email protected]>withalinktothesuspectedpiratedmaterial.
Weappreciateyourhelpinprotectingourauthors,andourabilitytobringyouvaluablecontent.
www.it-ebooks.info
![Page 33: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/33.jpg)
QuestionsYoucancontactusat<[email protected]>ifyouarehavingaproblemwithanyaspectofthebook,andwewilldoourbesttoaddressit.
www.it-ebooks.info
![Page 34: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/35.jpg)
AnoverviewofTDDTDDisnotusedonlytodevelopsoftware.Thefundamentalprinciplescanbeseeninmanyindustries.ThissectionwillexplorethefundamentalsofTDDandhowtheyareappliedbyatailor.
www.it-ebooks.info
![Page 36: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/51.jpg)
};
TipDownloadingtheexamplecode
Youcandownloadtheexamplecodefilesfromyouraccountathttp://www.packtpub.comforallthePacktPublishingbooksyouhavepurchased.Ifyoupurchasedthisbookelsewhere,youcanvisithttp://www.packtpub.com/supportandregistertohavethefilese-maileddirectlytoyou.
www.it-ebooks.info
![Page 52: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/53.jpg)
SummaryThischapterprovidedanintroductiontoTDD.ItdiscussedtheTDDlifecycle(testfirst,makeitrun,makeitbetter)andshowedhowthesamestepsareusedbyatailor.Finally,itlookedoversomeofthetestingtechniquesthatwillbediscussedthroughoutthisbookincluding:
TestdoublesRefactoringBuildingpatterns
AlthoughTDDisahugetopic,thisbookissolelyfocusedontheTDDprinciplesandpracticestobeusedwithAngularJS.Inthenextchapter,youwillstartthejourneyandseehowtosetuptheKarmatestrunner.
www.it-ebooks.info
![Page 54: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/54.jpg)
Chapter2.TheKarmaWayJavaScripttestinghashitthemainstream,thankstoKarma.KarmamakesitseamlesstotestJavaScript.AngularJSwascreatedaroundtesting.ThischapterexplorestheoriginsofKarmaandwhyithastobeusedinanyAngularJSproject.Bytheendofthischapter,youwillnotonlyunderstandtheproblemthatKarmasolves,butalsowalkthroughacompleteexampleusingit.
www.it-ebooks.info
![Page 55: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/55.jpg)
JavaScripttestingtoolsKnowingwhatthedifferenttestingtoolsareishalfthebattle.Inthissection,youwilllearnaboutthetwoprimarytoolsthatwillbediscussedandusedthroughoutthebook.Theyare:
Karma:ThisisatestrunnerProtractor:Thisisanend-to-endtestingframework
www.it-ebooks.info
![Page 56: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/57.jpg)
ProtractorProtractorisanend-to-endtestingtool.Itallowsdeveloperstomimicuserinteractions.Itautomatesthetestingoffunctionalityandfeaturesthroughtheinteractionofawebbrowser.ProtractorhasspecificmethodstoassistwithtestingAngularJS,buttheyarenotexclusivetoAngularJS.SomeoftheprosandconsofusingProtractorareasfollows:
Pros Cons
Configurabletotestmultipleenvironments Documentationandexamplesarelimited
EasyintegrationwithAngularJS
Syntaxandtestingcanbesimilartothetestingframeworkchosenforunittesting
www.it-ebooks.info
![Page 58: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/58.jpg)
JavaScripttestingframeworksInthissection,youwilllearnaboutthetestingframeworksthatwillsupportyouinyourTDDpractices.Theseinclude:
JasmineSeleniumMocha
www.it-ebooks.info
![Page 59: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/62.jpg)
BirthofKarmaWhenpickingupanewtool,itisimportanttounderstandwhereitcamefromandwhyitwasbuilt.ThissectiongivesyousomebackgroundoftheoriginsofKarma.
www.it-ebooks.info
![Page 63: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/65.jpg)
InstallingKarmaTimetostartusingKarma.Installationsandapplicationsareconstantlychanging.ThefollowingguideisintendedtobebriefinthehopethatyouwillgototheKarmawebsite,http://karma-runner.github.io/,andfindthelatestinstructions.
Themainfocusofthissectionwillbeonthespecificconfigurationusedinthisbookandnotanin-depthinstallationguide.
www.it-ebooks.info
![Page 66: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/69.jpg)
$./node_modules/karma/bin/karma--version
NowthatKarmaisinstalledandrunning,it’stimetoputittouse.
www.it-ebooks.info
![Page 70: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/72.jpg)
UsingKarmawithAngularJSHere,youwillwalkthroughaTDDapproachtoanAngularJScomponent.Bytheendofthischapter,youshouldbeableto:
FeelconfidentaboutusingKarmaanditsconfigurationUnderstandthebasiccomponentsofaJasminetestStarttounderstandhowtointegrateaTDDapproachinanAngularJSapplication
www.it-ebooks.info
![Page 73: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/75.jpg)
$Chrome35.0.1916(Windows7):Executed0of0ERROR(0.01secs/0secs)
Thatisit.KarmaisnowrunningforthefirstAngularJSapplication.
www.it-ebooks.info
![Page 76: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/76.jpg)
TestingwithAngularJSandKarmaThepurposeofthisfirsttestusingKarmaistocreateadynamicto-dolist.ThiswalkthroughwillfollowtheTDDstepswediscussedinChapter1,IntroductiontoTest-drivenDevelopment:testfirst,makeitrun,andmakeitbetter.ThiswillallowyoutogainmoreexperienceinusingTDDwithAngularJS.
www.it-ebooks.info
![Page 77: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/82.jpg)
Nextupistherequirementtoaddanewitemtothelist.TheTDDrhythmwillbefollowedagain:testfirst,makeitrun,andmakeitbetter.
www.it-ebooks.info
![Page 83: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/87.jpg)
SummaryInthischapter,wereviewedJavaScripttestingframeworksandtoolsanddiscussedhowVojtechJínacreatedKarma.Wesawhowtoinstall,configure,andrunKarma.Finally,youhavewalkedthroughanexampleofusingKarmawithTDD.Inthenextchapter,youwilllearnaboutend-to-endtestingwithProtractor.
www.it-ebooks.info
![Page 88: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/91.jpg)
OriginsofProtractorProtractorisnotthefirstend-to-endtestingtoolthattheAngularJSteambuilt.ThefirsttoolwascalledScenarioRunner.InordertounderstandwhyProtractorwasbuilt,weneedtofirstlookatitspredecessor:ScenarioRunner.
www.it-ebooks.info
![Page 92: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/92.jpg)
EndoflifeScenarioRunnerisinmaintenancemodeandhasreacheditsendoflife.IthasbeendeprecatedinplaceofProtractor.Inthissection,wewilllookatwhatScenarioRunnerwasandwhatgapsthetoolhad.
www.it-ebooks.info
![Page 93: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/98.jpg)
Theinstallationisnowcomplete.BothProtractorandSeleniumWebDriverforChromehavebeeninstalled.Wecannowmoveontotheconfiguration.
www.it-ebooks.info
![Page 99: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/101.jpg)
HelloProtractorWiththeProtractorinstallationandconfigurationcomplete,youcanlookatwritingarealtest.ThissectionwillwalkyouthroughusingTDDwithProtractor.Attheendofthischapter,youshouldbeableto:
FeelconfidentinusingandconfiguringProtractorUnderstandthebasiccomponentsofaProtractortestStarttounderstandhowtointegrateaTDDapproachtoend-to-endtesting
www.it-ebooks.info
![Page 102: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/110.jpg)
CleaningupthegapsThereareacoupleofthingsthatwerediscussedinthischapterthatneedsomefurtherclarification.Thisincludesthefollowing:
Whereistheasynchronouslogic?HowtoreallyimplementTDDwithend-to-endtests.
www.it-ebooks.info
![Page 111: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/117.jpg)
SettinguptheprojectInpreviouschapters,wediscussedindetailhowaprojectshouldbesetup,explainedthedifferentcomponentsinvolved,andwalkedthroughtheentireprocessoftesting.Iwillskipthesedetailsandprovidealistinthefollowingsectionfortheinitialactionstogettheprojectsetup.
www.it-ebooks.info
![Page 118: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/123.jpg)
TestingacontrollerBeforegettingintothespecification,andthemind-setofthefeaturebeingdelivered,itisimportanttoseethefundamentalsoftestingacontroller.AnAngularJScontrollerisakeycomponentusedinmostapplications.
www.it-ebooks.info
![Page 124: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/126.jpg)
BringonthecommentsNowthatthesetupandapproachhavebeendecided,wecanstartourfirsttest.Fromatestingpointofview,aswewillbeusingatop-downapproach,wewillwriteourProtractortestsfirstandthenbuildtheapplication.WewillfollowthesameTDDlifecyclewehavealreadyreviewed,thatis,testfirst,makeitrun,andmakeitbetter.
www.it-ebooks.info
![Page 127: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/134.jpg)
MakeitbetterThetwocomponentsthatneedtobereworkedare:
AddingbehaviortotheSubmitbuttonRemovinghardcodedvalueofthecomments
www.it-ebooks.info
![Page 135: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/139.jpg)
OnwardsandupwardsNowthatwehavethefirstspecificationworkingend-to-endandunittested,wecanstartthenextspecification.Thenextspecificationstatesthattheuserswanttheabilitytolikeacomment.
Wewillusethesametop-downapproachandstartourtestfromaProtractortest.WewillcontinuetofollowtheTDDlifecycle,thatis,testfirst,makeitrun,makeitbetter.
www.it-ebooks.info
![Page 140: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/148.jpg)
Chapter5.FlipFlopAtthispoint,youshouldbefeelingconfidentintheinitialimplementationofanAngularJSapplicationusingTDD.Youshouldbefamiliarwithusingatest-firstapproach.Inthischapter,youwillcontinuetoexpandyourknowledgeofapplyingTDDwithAngularJSbylookingatthefollowing:
AngularJSroutesPartialviewsProtractorlocationreferenceswithCSS(CascadingStyleSheets)andHTMLelementsHeadlessbrowsertestingwithKarma
www.it-ebooks.info
![Page 149: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/149.jpg)
FundamentalsThischapterwillwalkyouthroughapplyingTDDtoroutesandpartialviewsforasearchapplication.Beforegettingintothewalk-through,youneedtobeawareofsomeofthetechniques,configurations,andfunctionsthatwillbeusedthroughoutthischapter,whichinclude:
ProtractorlocatorsHeadlessbrowsertesting
Afteryouhavereviewedtheseconcepts,youcanmoveontothewalk-through.
www.it-ebooks.info
![Page 150: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/159.jpg)
2. Rerunthetest.
5. TheProtractortestsnowpass.
MakingflipflopbetterForpractice,youshouldaddalinktoswitchbacktoviewAfromviewB.Thereisnothingthathasbeencalledoutthatneedstobechangedorrefactored.Themaintakeawayfromthiswalk-throughishowtouseProtractortotestroutes.Herearesomescreenshotsoftheapplication:
Theinitialindexpageisshowninthefollowingscreenshot:
Thefollowingiswhatyou’llseeaftertheviewhasbeenswitched:
www.it-ebooks.info
![Page 160: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/160.jpg)
SearchingtheTDDwayThiswalk-throughwillshowyouhowtobuildasimplesearchapplication.Thewalk-throughhastwocomponents.Thefirstdiscussesasearchquerycomponent.Thesecondusesroutestodisplaysearchresultdetails.
www.it-ebooks.info
![Page 161: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/161.jpg)
DecidingontheapproachThiswalk-throughusesthetop-downTDDapproach.Itstartswithwritingfailingtests,fromtheUIpointofviewusingProtractor,andthenworkingthroughtheapplicationwithacombinationofunitandend-to-endtests.
www.it-ebooks.info
![Page 162: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/166.jpg)
Showmesomeresults!NowthattheSearchbuttonissetwiththerequiredfeatures,theresultingdetailsneedtobedisplayedwhenasearchresultisselected.Hereistheuserspecification.Giventhefollowingsearchresults:
IselectanitemfromthesearchresultsIwillseethedetailsinthemainpagecomponent
Followingthetop-downapproach,thefirststepwillbetheProtractortestsfollowedbythenecessarystepstogettheapplicationfullyfunctional.
www.it-ebooks.info
![Page 167: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/176.jpg)
Afterasearchquery,theapplicationlookslikewhatisshowninthefollowingscreenshot:
Fordetailsoftheapplicationlooksasshowninthefollowingscreenshot(noticethattheURLcontainsthedetailroute):
www.it-ebooks.info
![Page 177: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/180.jpg)
BeforetheplungeBeforethewalk-through,thecoreconceptsofthechapterwillbereviewedfirst.Itisimportantthatyouunderstandtheseconceptsbeforeyoumoveontothewalk-through.
www.it-ebooks.info
![Page 181: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/183.jpg)
ServicesAngularJSservices,factories,andresourcesareallimportantcomponents.Servicesareusedtoabstractapplicationlogic.Theyareusedtoprovidesingleresponsibilityforaparticularaction.Singleresponsibilityallowscomponentstobeeasilytestedandchanged.Thisisbecausethefocusisononecomponentandnotalltheinnerdependencies.
HereisasummaryofsomeoftheotherAngularJScomponentsthathavebeenlookedatsofar:
Attributesanddirectives:ThesedriveactionsandflowfromtheUIControllers:ThisprovidesthegluebetweentheUIandlogicServices:Thisisolatesthelogic
www.it-ebooks.info
![Page 184: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/187.jpg)
events.Asyouprogressthroughtherestoftheeventtests,youwillfindthatthesetupandtechniquesusedherewillbeusedthroughouttherestofthechapter.
www.it-ebooks.info
![Page 188: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/191.jpg)
HarnessingthepowerofeventsPublishingandsubscribingeventscanleadtosomeuglyandhard-to-understandspaghetticode.Nowthatthefoundationsforthechapterhavebeenreviewed,youcandiveintoimplementingeventsintothesearchapplication.
www.it-ebooks.info
![Page 192: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/208.jpg)
SummaryThischapterhasexploredeventswithinAngularJS.YousawtwotypesofAngularJSeventemitters:$broadcast()and$emit().YoualsosawsomeexamplesofapplyingTDDtoeventsandhoweventsgiveaseparationofcontrollersandcode.Inaddition,youexpandedthetypesoftestingtechniquestoincludeservicesandreiteratedthetestingofcontrollersandmodels.YoualsoexploredfurtherconfigurationofKarmatouseitsfeatures.Inthenextchapter,youwilllookattheintegrationandtestingofdataandAPIsintoanAngularJSapplication.
www.it-ebooks.info
![Page 209: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/209.jpg)
Chapter7.GiveMeSomeDataApplicationsneedawaytoconsumetheever-expansiveworldofdata.Mostapplicationswrittentodayconsumedata.LuckilyforAngularJSdevelopers,consumingdataisquiteeasy.Testingdataconsumptionisalsoacorecomponentoftheframework.Inthischapter,wewillcoverthefollowingtopics:
IntegratingaREST-basedserviceCreatingandmockingAngularJS’s$httpHandlingexceptionsImplementingafakeAPIbuilderpattern
www.it-ebooks.info
![Page 210: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/214.jpg)
callbackcanbepassedintothebeforeEach,afterEach,describe,anditmethods.
Youwillbeleveragingthisexamplethroughtherestofthechapter,sobesurethatyouunderstandthemainconcepts.NowthatyouhavetestedinKarma,thenextsectionwillshowyouwhatProtractoroffersfromanasynchronousstandpoint.
www.it-ebooks.info
![Page 215: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/221.jpg)
DisplayingproductswithRESTAllthecorecomponentsofREST,asynchronoustesting,andmockingHTTPrequestshavebeendiscussed.Now,thefollowingwalk-throughwillprovideafullexamplethatwilllookatdisplayingproductsthatareretrievedthroughanexternalservice.Theexamplewillignorethecreationofanexternalserviceandfocusonthedataitprovides:alistofproductsinaJSONformat.Thewalk-throughwilltakeabottom-upapproachsothatthecoredatalayerisworkedoutbeforeaddingtheUIelements.
www.it-ebooks.info
![Page 222: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/228.jpg)
expect(scope.error).toEqual('error');
Nowthatthetestshavebeenassembled,thenextstepistomakethemrun.
www.it-ebooks.info
![Page 229: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/236.jpg)
Themakeitbetterstepwillbeskippedasthereisnothingimmediatethatneedstoberefactored.Atthispoint,theapplicationistestedandoperatedusingthemockeddata.Youshouldbeabletoseehowpowerfulthistechniquecanbeasyou’rebuildingupanapplication.Thenextsectionwilllookatremovingthescaffoldingandusinganactualbackend.
www.it-ebooks.info
![Page 237: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/249.jpg)
SummaryThisappendixhasshownyouhowtosetupandusetheSeleniumstandaloneserver.Therearemanyoptionsandadvantagesofusingthestandaloneserver.TheadvantagesaregearedmoreforadvancedtestingwhenyouwanttouseadedicatedSeleniumServeroraPaaS(PlatformasaService)orifyouwanttotestafunctionalityondifferentbrowsersandasthevolumeofyourProtractortestsgrow.Formoreinformation,visittheSeleniumhomepageathttp://www.seleniumhq.org/.
www.it-ebooks.info
![Page 250: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/250.jpg)
AppendixB.AutomatingKarmaUnitTestingonCommitRunningtestslocallyisonething,buthowdoyouknowwhethertheywillworkonsomeoneelse’scomputer.Settingupcontinuoustestingandintegrationshouldbepartofeveryapplicationyouwrite.Oneofthebestthingsisthatthetoolstosetuparefree,easytouse,andbestofall,theygettoshowcaseyourtests!ThefollowingsectionwillexplorehowtosetupcontinuousintegrationusingGitHubforsourcecontrolandTravisforcontinuousintegration.
www.it-ebooks.info
![Page 251: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/251.jpg)
GitHubGitHubisasourcecontrol,collaboration,andall-aroundawesometool.Foropensourceprojects,itisfree.Onceyousignup,youcangetstartedandcreateanewrepositoryforyourproject.GitHubprovidesaGitURLforeveryproject;theURLcanthenbesetuptopushchangeslikeanyotherGitrepository.OneofthebenefitsofusingGitHubisthatitautomaticallyprovideshooksintootherapplicationsandservices.WhensettingupcontinuousintegrationandtestingthroughTravisCI,youwillleveragetheTravisCIGitHubhook.
www.it-ebooks.info
![Page 252: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/254.jpg)
SettingthehookGitHubprovidesseveralhooksintootherapplications.Ahookallowsyoutochainactionswhenacommitoccurs.Ahookisanextremelyusefulfeaturefromacontinuousintegrationstandpointbecausewecansetupthecodetobetestedoneverycommit.TravisCIhasaGitHubhookthatcanbeeasilysetuponanyGitHubrepository.Thefollowingisawalk-throughonhowtocreateaTravisCIhookonyouropensourcerepository.
www.it-ebooks.info
![Page 255: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/257.jpg)
Ifyouhaveanyissues,gototheTravisCIGettingstartedguideathttp://docs.travis-ci.com/user/getting-started/.
www.it-ebooks.info
![Page 258: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/260.jpg)
Chapter1,IntroductiontoTest-drivenDevelopmentQ1 2
Q2 1
Q3 1
Q4 1
Q5 2
www.it-ebooks.info
![Page 262: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/262.jpg)
Chapter3,End-to-endTestingwithProtractorQ1 1
Q2 1
Q3 1
www.it-ebooks.info
![Page 267: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/273.jpg)
Fflipfloptest,AngularJSroutes
viewsflip,creating/Makingtheviewsflipflip,asserting/Assertingafliprunning/Makingflipfloprunimproving/Makingflipflopbetter
FunctionUnderTest/Testingtechniquesfundamentals,searchapplication
Protractorlocators/Protractorlocators
www.it-ebooks.info
![Page 275: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/279.jpg)
installing/TestsetupKarmaunittesting
testsetup/Testsetuptestscripts/Testscriptshook,setting/Settingthehookhook,creating/CreatingthehookTravisconfigurationfile,adding/AddingaTravisconfigurationfile
www.it-ebooks.info
![Page 280: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/281.jpg)
NNode.js
URL/Installationprerequisites,Installationprerequisitesabout/Installationprerequisites
NodePackageManager(npm)modules/Mocha
www.it-ebooks.info
![Page 282: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/html5/thumbnails/286.jpg)
about/Installationprerequisitesinstalling/InstallingWebDriverforChrome
success,measuringinTDDsteps,breakingdown/Breakingdownthestepstestfirstmethodology/Measuretwicecutonce
www.it-ebooks.info
![Page 287: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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: AngularJS Test-driven Development - DropPDF1.droppdf.com/files/BwnWc/angularjs-test-driven-development.pdfAngularJS Test-driven Development Credits About the Author About the Reviewers](https://reader033.fdocuments.net/reader033/viewer/2022042107/5e8631a399078346ab3d7fa7/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