From 4dd9c598386a08bc78f602854ce079faa5e769f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20Poizat?= Date: Wed, 3 Apr 2024 12:04:23 +0200 Subject: [PATCH] feat: Add a destroy method in ContactsCollection Depending if a contact has been imported by a konnector or not, there is logic to delete a contact. We need to delete a contact at least in : - cozy-contacts - cozy-keys-browser So let's centralize this logic. --- .../src/ContactsCollection.js | 22 ++++++ .../src/ContactsCollection.spec.js | 70 +++++++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/packages/cozy-stack-client/src/ContactsCollection.js b/packages/cozy-stack-client/src/ContactsCollection.js index 6efa53c93..39cf5f005 100644 --- a/packages/cozy-stack-client/src/ContactsCollection.js +++ b/packages/cozy-stack-client/src/ContactsCollection.js @@ -31,6 +31,28 @@ class ContactsCollection extends DocumentCollection { } return col } + + /** + * Destroys a contact + * + * If the contact is linked to accounts, it will be trashed instead of being + * destroyed. + * + * @param {object} contact - Contact to destroy. IT MUST BE THE FULL CONTACT OBJECT + * @returns {Promise} - Resolves when contact has been destroyed + */ + async destroy(contact) { + const syncData = contact?.cozyMetadata?.sync || {} + const isLinkedToAccounts = Object.keys(syncData).length > 0 + if (isLinkedToAccounts) { + return super.update({ + ...contact, + trashed: true + }) + } else { + return super.destroy(contact) + } + } } export const CONTACTS_DOCTYPE = 'io.cozy.contacts' diff --git a/packages/cozy-stack-client/src/ContactsCollection.spec.js b/packages/cozy-stack-client/src/ContactsCollection.spec.js index 774ec0d3d..c1e825d66 100644 --- a/packages/cozy-stack-client/src/ContactsCollection.spec.js +++ b/packages/cozy-stack-client/src/ContactsCollection.spec.js @@ -1,5 +1,6 @@ import CozyStackClient from './CozyStackClient' import ContactsCollection from './ContactsCollection' +import DocumentCollection from './DocumentCollection' const stackMyselfResponse = { data: { @@ -78,4 +79,73 @@ describe('ContactsCollection', () => { ) }) }) + + describe('destroy', () => { + const setup = () => { + const stackClient = new CozyStackClient({}) + const col = new ContactsCollection('io.cozy.contacts', stackClient) + return { col } + } + + beforeEach(() => { + jest.clearAllMocks() + }) + + it('should delete a contact with no sources', async () => { + const { col } = setup() + + const documentCollectionDestroySpy = jest + .spyOn(DocumentCollection.prototype, 'destroy') + .mockImplementation() + + const contact = { + _id: '123', + _rev: '1', + cozyMetadata: { + sync: {} + } + } + + await col.destroy(contact) + expect(documentCollectionDestroySpy).toHaveBeenCalledWith(contact) + + const contactWithoutMetadata = { + _id: '456', + _rev: '1' + } + await col.destroy(contactWithoutMetadata) + expect(documentCollectionDestroySpy).toHaveBeenCalledWith( + contactWithoutMetadata + ) + }) + + it('should flag a contact with sources as trashed', async () => { + const { col } = setup() + + const documentCollectionDestroySpy = jest + .spyOn(DocumentCollection.prototype, 'destroy') + .mockImplementation() + const documentCollectionUpdateSpy = jest + .spyOn(DocumentCollection.prototype, 'update') + .mockImplementation() + + const contact = { + _id: '123', + cozyMetadata: { + sync: { + 456: { + id: 'people/657623' + } + } + } + } + + await col.destroy(contact) + expect(documentCollectionDestroySpy).not.toHaveBeenCalled() + expect(documentCollectionUpdateSpy).toHaveBeenCalledWith({ + ...contact, + trashed: true + }) + }) + }) })