Lesson 17

[Sprint Three] Delete a Client

Delete an existing client

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:

PRO

Thanks for checking out the preview of this lesson!

The full version of this lesson is only available to pro members. If you would like full access to this module and all of the other pro modules on Elite Ionic you can become a pro member (or log in if you are already a member).