- Notifications
You must be signed in to change notification settings - Fork1
A largely BDD version of the "official" Angular "phone store" tutorial
License
UMM-CSci-3601/revised-angular-tutorial
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
This is a version ofthe "official" Angular "Phone Store" tutorial generated by @kklamberty and @NicMcPhee using a largely BDD (behavior-driven-development) approach. We're essentially starting with E2E (end-to-end) tests and using those to drive thedevelopment of components, services, features, etc.
Our reason for this is that most of the commonly used examples, such as the phone store tutorial andthe Tour of Heroes tutorial, have no testing. This (sort of) makes sense from the standpoint of the Angular developers their goal is to teach Angular, not cover Karma and Jasmine and Protractor, etc. It's frustrating when one of the selling points of Angular is that it's a readily testable framework, though, but none of the major examples actually include testing.
Thus we hope that by documenting an example of how one could build the phone store tutorial in a largely BDD style we can provide:
- An example of using BDD to document, test, and drive the implementation of complex functionality
- Reasonable examples of writing E2E tests
- Reasonable examples of writing unit tests
- Suggestions for where to use E2E tests, and where to use unit tests
We will not repeat all the tutorial material and explanations inthe phone store tutorial, so if you're new to Angular it would probably be useful to either go through that first, or at least be reading along through it while you're working through this tutorial. Based on our experience with students, however, there are some things (beyond testing) we will try to highlight or expand on, including:
- Observables and RxJS (& asynchrony in general)
- Parent/child component relationships
We might also provide a version of this that has all the E2E tests but none of the implementation code for those that would like to completely build the tutorial in a BDD fashion, but without having to write the tests first.
We will also not provide a complete tutorial on E2E tests with protractor or unit tests with karma, or on using jasmine to write tests. We will explain some of these ideas as we go, but you should hit up the Internet for a more complete introductions to those tools.
ng new phone-store- ❓ This creates a directory called
phone-storein the project. Do we want to change the name toclientto be more like our later structures? - At this point you can go into the
phone-storedirectory and runng serverand see our little project! 😄 It of course doesn't actuallydo anything interesting yet, but it does work.
- ❓ This creates a directory called
@floogulinc set up the GitHub Actions based on work done in S20.These are all laid out inthis pull request.
For reasons we don't fully understand, this requires installingsomewebdriver-manager binaries that didn't get installed ontheir own. Without them, we can't run thee2e tests.
Running:
node_modules/protractor/bin/webdriver-manager update
installed the necessary binaries and all the tests ran and passed.
The tutorial starts you off with two components:
top-bar, which has the app title and a checkout buttonproduct-list, which lists the products available at the store
and essentially no implemented "logic" except for the fact that the title links to the route'/'.
A question is what we can/should test about these components. Thetop-bar component, for example, has several properties that could be tested:
- It has a certain height.
- It has a certain background color (a blue).
- It contains an
h1element with the string "My Store". This text is white against the blue background. This is a link; clicking it takes you to the'/'route, which at the moment is just the same page. (So it doesn't really seem to do anything at the moment, but will clearly serve a purpose when there is a second page and beyond.) - It contains a checkout button containing both a shopping cart icon and the string "Checkout". The button is white, and the text and icon are blue.
Many of these are reallydisplay properties (e.g., colors, sizes, layout) and probably shouldn't be captured in tests. We probably don't want an E2E test that checks that the shade of blue in thetop-bar is "just so"; that would be really annoying if a design team came in and wanted to provided several possible color themes for consideration. It might also break the test if the user was using "dark mode" instead of "light mode", or the functionality was added later that let the user specify things like colors.
Things like the title (currently "My Store") are more complex. The fact that "My Store" is clearly not a good title is a sign that we might want to have tests that capture that exact text. Early in a project the team may not have settled on a title yet, and embedding it in the tests might prematurely "lock in" a title that no one is actually terribly fond of. So instead of testing for a specific title string, at the beginning maybe it would be sufficient to confirm that there is anapp-top-bar element, and that it contains anh1 element, without worrying about the text in that element.
We created an E2E spec that required (indirectly through the page objects) the existence of anapp-top-bar component. (ce1e3db) We then satisfied that spec by generating the component (35ff8b2):
ng generation component top-bar
and replacing the entire contents ofapp.component.html with the HTML from the tutorial, which includes adding:
<app-top-bar></app-top-bar>
at the top. (594c6d1)
We then added an E2E spec that required that there be a checkout button, and got that to pass by pasting in the button code from the tutorial. (9421cb8)
At this point the top bar is complete except for the fact that "My Store" should be a link to'/'. So we added an E2E spec that clicked on the titleand checked that we were on the "home page". (9f3046d) This is a slightly awkward testat the moment becauseeverything is on the home page; we should probablyextend it when there are additional pages to make sure the link brings usback home from those pages.
The tests all passed, but we realized that there was no styling, sowe copied over the CSS from the tutorial and pasted it into ourproject. We also needed to link to the Material Icons font inindex.html to bring in the shopping cart icon used in the checkoutbutton.
This completes the top bar for now.
We added a spec that required anapp-product-list element. This failed.
We then generated the component:
ng generate component product-list
As well as creating the component, we also need to route the default path to theproduct-list component. This requires adding this bit of code toapp.module.ts:
RouterModule.forRoot([{path:'',component:ProductListComponent},])
We just copied in theapp/products.ts file that has the list of phones,descriptions, and prices.
We added a spec that required anh2 header in theapp-product-list element,and added code toproduct-list-html so that would pass.
We specified that there should be threeh3 elements in theapp-product-list element. We got that to pass by adding theproductsfield to theProductListComponent and with an*ngFor in the productlist HTML.
We'd been focused entirely on the E2E tests so far, and it occurredto us that we should check on the unit tests. Running
ngtest --code-coverage --watch=falseran the unit tests for us. We had 100% coverage at this point, largelybecause we have pretty much zero logic. 😄 One test did fail,however,because we no longer display the default text
phone-store app is running!
We changed it to extract the title from the top bar and confirm thatit contains "store" (with upper or lower case 's') with:
expect(compiled.querySelector('app-top-bar h1').textContent).toMatch(".*[sS]tore.*");
This failed, though, because the test didn't know how to understandtheapp-top-bar HTML element from the top-bar component. AddingTopBarComponent to thedeclarations section inapp.component-spec.tsfixed that problem. Now the tests pass and our coverage is still at100% (because there's no meaningful logic).
WARN: 'Can't bind to 'routerLink' since it isn't a known property of 'a'.'
Nic spentway too long flailing around on that (searching theInternet wasn't a ton of help) until he finally thought to set--watch=true and look at the browser console. That pointed out thatthe problem was intop-bar.component.spec.ts, which wasn't where hehad been looking at all. Once he was looking in the right place, herealized that the problem wasthat we weren't importingRouterTestingModule; adding that fixedthe problem right away.
So far all the product list is is a list of product names. The firstsection of the tutorial expands that to display various pieces ofinformation (e.g., description) formatted in various ways.It also makes each product name a link, which will ultimately (in thesecond section of the tutorial) link to a separate, more detailed,page for that product.
The first thing the tutorial does is make each product name a link.These links have nohref so they don'tgo anywhere yet. Theydo,however, all have titles that have the form
"product.name + ' details'"i.e., the name of the product followed by the word "details".
We then added E2E tests that required that:
- Each product name is a link
- Each link has a
titleattribute that ends in' details'
Those tests failed, and we then added the code from the tutorialthat got them to pass.
We also refactored all thepage.navigateTo() calls up in thethebeforeEach section so we weren't repeating them a zilliontimes.
About
A largely BDD version of the "official" Angular "phone store" tutorial
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Releases
Packages0
Uh oh!
There was an error while loading.Please reload this page.
Contributors4
Uh oh!
There was an error while loading.Please reload this page.