Creating a Modern Firebase Powered Application with TDD
Use reactive programming and tests to build a professional app
The Structure of this Module
An overview of the project plan
PROModule Outline
- Source Code & Resources PRO
- Lesson 1: Introduction PUBLIC
- Lesson 2: The Structure of this Module PUBLIC
- Lesson 3: [Sprint One] Setting up Firebase PUBLIC
- Lesson 4: [Sprint One] Creating Security Rules with TDD PRO
- Lesson 5: [Sprint One] Testing Authentication PRO
- Lesson 6: [Sprint One] Component Store PRO
- Lesson 7: [Sprint One] Circumventing Firebase Authentication for E2E Tests PRO
- Lesson 8: [Sprint Two] Displaying Client List from Firestore PRO
- Lesson 9: [Sprint Two] - Adding Clients PRO
- Lesson 10: [Sprint Two] - Editing Clients PRO
- Lesson 11: [Sprint Two] - Client Details PRO
- Lesson 12: Preparing for Delivery PRO
- Lesson 13: Configuring for Production PRO
- Lesson 14: [Sprint Three] - Refactoring PRO
- Lesson 15: [Sprint Three] Setting up PWA PRO
- Lesson 16: [Sprint Three] Logout PRO
- Lesson 17: [Sprint Three] Delete a Client PRO
- Lesson 18: [Sprint Three] - Feedback Mechanism PRO
- Lesson 19: [Sprint Three] View Feedback PRO
- Lesson 20: More Styling PRO
- Lesson 21: [Sprint Four] - Refactoring Feedback PRO
- Lesson 22: [Sprint Four] - Feedback Dates PRO
- Lesson 23: [Sprint Four] - Client Survey PRO
- Lesson 24: [Sprint Four] - View Survey PRO
- Lesson 25: Final Touches PRO
- Lesson 26: Conclusion PRO
Lesson Outline
The Structure of this Module
As I mentioned in the introduction video, this module is an extension of the project management module - however, you don't need to do project management module if you do not want to. If you are reading this lesson, then you should be at one of these two stages:
- You have completed Lesson 14 of the project management module and want to follow through with the details of how the application is actually built
- You have just come directly to this module to learn about building a modern Firestore powered application using Test Driven Development.
For those of you who fall into the second category I will give you a little more context in this lesson. If you fall into the first category then you can either read this lesson for a quick recap of or just skip straight to the next lesson.
If you fall into the second category, but would like to complete the project management module as well, click the link below and continue through the module until you end up back at this lesson again:
Switch modules: Proceed to Lesson 2 of the Project Management for Professional Ionic Applications module
The key difference in philosophy between this module and more typical modules/courses/books I create is that it isn't a completed/self-contained example. Most examples I create build an entire application from start to finish. This module however was created as a result of me actually building a real life application for a real client. This means that the application build is not as neat/simplified as a normal tutorial would be - it is larger, more complex, it takes longer, and it changes along the way. However, it does give, I think, a much more realistic look at what it is like to use TDD to build a real world application.
The way this is structured is that we will be following along with the first four sprints of this application build. I documented absolutely everything I did during these first four sprints so that I could write up this module (if you are unfamiliar with the term sprint it is basically just a chunk of work done on the project over a specified time frame like 1 week or 2 weeks). In a typical tutorial I would smooth out any mistakes and present the nice and clean final product to you in a nice and logical order, but with this module any mistakes I make along the way you will be making with me (and we will undo those mistakes later when we discover them).
We end up somewhere with a lot of the core functionality implemented, but the application will be left far from entirely completed. I don't think there would be much value including the entire project in this module because eventually we are just doing the same thing over and over again, and this module is already ridiculously large (I think this is likely the largest "example" content I have ever created). I had to draw the line somewhere, so I did it where I thought made the most sense!
As the module progresses, I will be linking back to additional lessons in the project management module where it is relevant. If you are completing both modules then you can just follow the links back and forth between the two modules, and eventually you will complete both together. If you are just interested in this module, then you can ignore the links back to the project management module. You may also see sections within lessons in this module that are marked with a Project Management label - again, you can either complete or ignore these as you please.
What is the point of this module?
Although this module is associated with the project management module, this module has a different focus. It isn't just about facilitating the building of the application for the project management process, this module has independent goals. Specifically, what we will focusing on learning in this module is:
- How to build an application that uses Firestore for data storage
- How to use AngularFire to integrate Firebase with an Angular application
- How to use local Firebase emulators to help with development
- How to build a general real-world application using modern/best-practice techniques
- How to do all of this using a Test Driven Development methodology
If you have no experience with automated testing and specifically Cypress/Jest then this module will likely be quite hard to follow along with. We do everything step-by-step so you can probably still get through it, but you might not get a whole lot out of it because I won't be explaining basic testing concepts in this module. If that is the case for you, I would highly recommend completin the Test Driven Develpoment with Cypress/Jest module first.
What are we actually building?
Again, if you're coming here from the project management module then you already have some context, but if not then you won't know what we are building yet.
We will be building an application for a massage therapist who is running a business providing relaxation and remedial massage. The key idea is that this application will provide the owner of the business the ability to manage clients, schedule appointments, provide forms, take notes, and other features that will help manage the day-to-day running of the business. This is the initial set of user stories that was decided on to provide the functionality:
EPIC: As a massage therapist, I want to be able to manage client data
As a massage therapist, I want to be able to record a client's details so that I don't need to ask them for the same information on their next visit
As a massage therapist, I want to be able to see a list of all clients, so that I can have a birds eye view of my entire client base
As a massage therapist, I want to be able to edit a clients details, so that I can manually make updates if necessary
As a massage therapist, I want to be able to search for a specific client, so that I can quickly find details for that client
As a massage therapist, I want to be able to access the full details of a specific client, so that I can access all of the information that is required to complete my services
As a massage therapist, I want to record custom notes for specific clients, so that I can easily find relevant information for that client
As a massage therapist, I want to be able to view the notes I recorded for a client in the same place as the rest of their details, so that I will see the additional notes for a client before beginning my service
As a massage therapist, I want to be able to edit notes associated with a client, so that I can update information relevant to the client over time
As a massage therapist, I want to be able to add a client's future appointments to a calendar, so that I can keep track of when I have clients coming in
As a massage therapist, I want to be able to view a clients future appointments in the same place as the rest of their details, so that this information will be available to me when performing my services allowing me to prompt them to book future appointments if necessary
As a massage therapist, I want to be able to see all of my appointments from all clients in one place, so that I don't need to check individual clients
As a massage therapist, I want to be able to edit a clients future appointments, so that I can accommodate changes in circumstances for the client
As a massage therapist, I want to be able to present clients with a questionnaire, so that I am able to gather the information I need to perform a massage.
As a massage therapist, I want to be able to send a client a link to the questionnaire that they can complete online, so that the client doesn't need to spend time filling out the questionnaire once they arrive
As a massage therapist, I want the results of the users questionnaire to be visible to me, so that I have the information required for the massage and so that I can get them to verify the information in person
As a massage therapist, I don't want clients to be able to exit the survey that I present to them in person, so that they can't view other parts of the application that might contain sensitive client data
As a massage therapist, I want to provide a mechanism for clients to supply feedback anonymously, so that clients are comfortable to be honest which will allow me to improve my service
As a massage therapist, I want the ability to view feedback that has been submitted anonymously, so that I can use that information to improve my services
As a massage therapist, I want to be able to send out a notice about COVID requirements before a client comes in, so that they know to reschedule their appointment if they are sick or meet any other requirement related to COVID that would prevent them from being able to receive my services
As a massage therapist, I want to have reminders sent out to my clients for upcoming appointments, so that my clients don't miss appointments
As a massage therapist, I want to be able to log in to the application using my Google account from any device, so that only I can access private information in the application and I can do it from any device
EPIC: As a massage therapist, I want to be able to record notes relevant to my work
As a massage therapist, I want to be able to create and edit general notes, so that any information relevant to my services will be easily available to me
As a massage therapist, I want to have to be able to view a list of all of the notes I have created, so that I can review the list for any important notes that I might need to look at
As a massage therapist, I want to have to be able to view the details of a specific note, so that I can record and review larger amounts of information
Keep in mind that these user stories may be changed or removed throughout the life of the project, and that won't really be discussed in this module. This is just to give you a general sense of what the application is about, but we will discuss the specific features that we are implementing at the beginning of each section.
We will also look at some additional documentation that was creating in the project management module as it becomes relevant, but to give you a quick high level overview of the structure of the project, this is what our plan is at the moment:
Broadly, we have split this application up into a bunch of different feature modules, and we have one shared folder for stuff that will be shared between multiple modules. However, instead of creating a shared module to bundle together shared components we will be using the SCAM (Single Component Angular Module) approach. What this means basically is that each individual component/directive/pipe will declare and export itself in its own module, so we can just import things individually rather than having to pull in the entire shared module.
This is a common pattern for Angular applications, but more specifically we are using a structure that is typical to use within an Nx workspace. We are not going to be using Nx in this module, but I like this structure regardless of whether I am using Nx or not.
The key idea is that we typically break everything up into four folders for each feature module:
- feature - contains the smart/routed component(s) for the feature module
- ui - contains the dumb/presentational component(s) used by the feature(s)
- data-access - contains anything related to accessing data e.g. services, state management
- utils - contains any utility/helper functions
Keep in mind that it is fine to break this structure with other types of folders where it makes sense, but this is typically what we try to stick to.
Let's talk a little bit more about how exactly I came to the folder structure we just saw.
An important aspect of keeping an Angular application well organised, testable, and maintainable is to create separation between your smart and dumb components. This is a big focus of the Nx structure.
A "dumb" or "presentational" component is primarily used for displaying things to the user and having them interact with it. It is not smart in the sense that it doesn't have any idea what the rest of the application is doing, it primarily just displays things based on the @Input
it receives, and it communicates primarily through its @Output
. It generally does not deal with observables, or injecting services, or any complex business logic. These are the sort of components you will find in the ui folders.
A "smart" component on the other hand does all those things that the "dumb" component doesn't. It does deal with observables, it does have injected dependencies, it does deal with complex logic, and it generally has the role of orchestrating how all of its child "dumb" components work together.
Fortunately, it is generally easy to identify what is what in an Angular application. All of your "routed" components - in an Ionic application specifically this basically just means your page components that are routed to - are your smart components. Everything inside of those smart components is generally a dumb component. This is why it is important to break up the contents of your routed components into smaller "dumb" components that are composed together. Otherwise you just end up with one mega smart component that does everything. This will make the application harder to understand, harder to test, and harder to maintain.
In determining this structure, the wireframes are a good reference to have. Just look at each individual page - those are your feature/smart components. Then look at every individual thing within that page, you will make each of those their own component and they will be your dumb/presentational components.
Typically you would only have one feature/smart component per feature module in your application, but for instances where you have child routes you might have multiple. You can see we heavily make use of this in our example structure because many of the features have child views.
Again, keep in mind that none of this is final. I did not spend a great deal of time planning this out, maybe 30 minutes thinking about it, we just need a plan that makes sense to get us started - we can adapt as we go. That's another good thing about separating concerns and keeping things nice and organised/modular - it becomes much easier to refactor. If we build all of the functionality into super components that do everything, modifying/refactoring to adapt to changing requirements becomes a lot harder.
Let's get started!
Ok, that's enough context for now. If you would like more context you can of course always go back and check out the project management module. Anything more you need to know for completing this module I will include as we go.