Creating a Modern Firebase Powered Application with TDD
Use reactive programming and tests to build a professional app
[Sprint Three] Delete a Client
Delete an existing client
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
Feat: Ability to delete a client
Now we are going to implement the ability to delete a client.
User story: As a massage therapist, I want the ability to delete a client, so that I can remove clients entries mistakingly added or remove clients that I no longer provide services for
Project management
Remember to move the card for this task to the Test
column, and create a new task branch to work on.
Let's start with our E2E test again, we will add this one to clients.cy.ts
:
it('can delete a client', () => {
const clientToDelete = {
name: {
first: 'Josh',
last: 'Morony',
},
phone: '333',
email: '[email protected]',
notes: '',
};
cy.callFirestore('set', 'clients/abc123', clientToDelete);
getItemsInList().first().click();
getDeleteButton().click();
getConfirmButton().click();
getItemsInList().should('not.exist');
});
We have some extra utility methods to add here:
export const getDeleteButton = () => cy.get('[data-test="delete-button"]');
export const getConfirmButton = () => cy.get('#confirm-delete');
NOTE: We are using an id
to grab the confirm button because there isn't a way for us to set up data-test
attributes on an Ionic alert button.
An important difference about this test is that we not only click the "delete" button but we also click a "confirm" button after that. This is a destructive action and we don't want accidental taps to wipe out user data, so we are going to have a confirm dialog pop up to check if the massage therapist really wants to delete the client.
Let's run this test to check that it fails:
Timed out retrying after 4000ms: Expected to find element: [data-test="delete-button"], but never found it.
Great! Now we can add the delete button. We actually have a bit of an architectural decision to make here - do we add the button directly to the client-detail
page or do we add it to our client-detail-card
presentational component?
If we add it to the presentational component then we would have to add an @Output()
event for when the delete is triggered so the parent could handle it. In any case, the delete button is associated with the client we are viewing in general, not just the card displaying the clients details, so I think it makes sense to add the button directly to the client-detail
page for now:
<ion-content class="ion-padding">
<ng-container *ngIf="{ client: client$ | async } as vm">
<app-client-detail-card [client]="vm.client"> </app-client-detail-card>
<ion-button
data-test="delete-button"
color="danger"
fill="outline"
(click)="deleteClient(vm.client)"
>
Delete Client
</ion-button>
</ng-container>
</ion-content>
Notice that we have actually done a minor refactor here. Before we had the *ngIf
and async
pipe directly on <app-client-detail-card>
, but now we need to supply the client to deleteClient
as well. To handle this, we just add an <ng-container>
that handles setting up the vm
.
Since we are trying to access the ClientsService
let's make sure to add that as a provider to our test setup for client-detail
:
Thanks for checking out the preview of this lesson!
You do not have the appropriate membership to view the full lesson. If you would like full access to this module you can view membership options (or log in if you are already have an appropriate membership).