From bccfe5a042086c6130edd80763af3c76187df5aa Mon Sep 17 00:00:00 2001 From: RafaPolit Date: Tue, 24 Sep 2024 13:10:57 -0500 Subject: [PATCH 1/3] Added EntityCreatedEvent --- app/api/entities/entities.js | 11 +++++- app/api/entities/events/EntityCreatedEvent.ts | 11 ++++++ app/api/entities/specs/entities.spec.js | 39 +++++++++++++++++-- 3 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 app/api/entities/events/EntityCreatedEvent.ts diff --git a/app/api/entities/entities.js b/app/api/entities/entities.js index 73099ce7b4..7ed0148d5f 100644 --- a/app/api/entities/entities.js +++ b/app/api/entities/entities.js @@ -17,6 +17,7 @@ import ID from 'shared/uniqueID'; import { denormalizeMetadata, denormalizeRelated } from './denormalize'; import model from './entitiesModel'; +import { EntityCreatedEvent } from './events/EntityCreatedEvent'; import { EntityUpdatedEvent } from './events/EntityUpdatedEvent'; import { EntityDeletedEvent } from './events/EntityDeletedEvent'; import { saveSelections } from './metadataExtraction/saveSelections'; @@ -149,7 +150,7 @@ async function updateEntity(entity, _template, unrestricted = false) { await applicationEventsBus.emit( new EntityUpdatedEvent({ before: docLanguages, - after: result, + after: await model.get({ sharedId: entity.sharedId }), targetLanguageKey: entity.language, }) ); @@ -203,6 +204,14 @@ async function createEntity(doc, languages, sharedId, docTemplate) { await updateNewRelationships(v2RelationshipsUpdates); await Promise.all(result.map(r => denormalizeAfterEntityCreation(r))); + + await applicationEventsBus.emit( + new EntityCreatedEvent({ + entities: await model.get({ sharedId }), + targetLanguageKey: languages[0].key, + }) + ); + return result; } diff --git a/app/api/entities/events/EntityCreatedEvent.ts b/app/api/entities/events/EntityCreatedEvent.ts new file mode 100644 index 0000000000..12d561a6ec --- /dev/null +++ b/app/api/entities/events/EntityCreatedEvent.ts @@ -0,0 +1,11 @@ +import { AbstractEvent } from 'api/eventsbus'; +import { EntitySchema } from 'shared/types/entityType'; + +interface EntityCreatedData { + entities: EntitySchema[]; + targetLanguageKey: string; +} + +class EntityCreatedEvent extends AbstractEvent {} + +export { EntityCreatedEvent }; diff --git a/app/api/entities/specs/entities.spec.js b/app/api/entities/specs/entities.spec.js index 5ea4daa2fb..bc7a2c2310 100644 --- a/app/api/entities/specs/entities.spec.js +++ b/app/api/entities/specs/entities.spec.js @@ -2,6 +2,8 @@ /* eslint-disable max-nested-callbacks,max-statements */ import Ajv from 'ajv'; +// eslint-disable-next-line node/no-restricted-import +import fs from 'fs/promises'; import entitiesModel from 'api/entities/entitiesModel'; import { spyOnEmit } from 'api/eventsbus/eventTesting'; @@ -11,8 +13,6 @@ import { search } from 'api/search'; import date from 'api/utils/date.js'; import db from 'api/utils/testing_db'; import { UserInContextMockFactory } from 'api/utils/testingUserInContext'; -// eslint-disable-next-line node/no-restricted-import -import fs from 'fs/promises'; import { UserRole } from 'shared/types/userSchema'; import fixtures, { @@ -32,6 +32,7 @@ import fixtures, { import entities from '../entities.js'; import { EntityUpdatedEvent } from '../events/EntityUpdatedEvent'; import { EntityDeletedEvent } from '../events/EntityDeletedEvent'; +import { EntityCreatedEvent } from '../events/EntityCreatedEvent'; describe('entities', () => { const userFactory = new UserInContextMockFactory(); @@ -509,17 +510,47 @@ describe('entities', () => { }); describe('events', () => { + it('should emit an event when an entity is created', async () => { + const emitSpy = spyOnEmit(); + const newEntity = { + template: templateId, + title: 'New Super Hero', + metadata: { + text: [{ value: 'New Text' }], + property1: [{ value: 'value1' }], + property2: [{ value: 'value2' }], + description: [{ value: 'ew Description' }], + friends: [{ icon: null, label: 'shared2title', type: 'entity', value: 'shared2' }], + enemies: [{ icon: null, label: 'shared2title', type: 'entity', value: 'shared2' }], + select: [], + }, + }; + + const savedEntity = await entities.save(newEntity, { + user: { _id: adminId }, + language: 'en', + }); + + const afterAllLanguages = await entities.getAllLanguages(savedEntity.sharedId); + + emitSpy.expectToEmitEventWith(EntityCreatedEvent, { + entities: afterAllLanguages, + targetLanguageKey: 'es', + }); + emitSpy.restore(); + }); + it('should emit an event when an entity is updated', async () => { const emitSpy = spyOnEmit(); const before = fixtures.entities.find(e => e._id === batmanFinishesId); - const beforeAllLanguages = fixtures.entities.filter(e => e.sharedId === before.sharedId); + const beforeAllLanguages = await entities.getAllLanguages(before.sharedId); const after = { ...before, title: 'new title' }; await entities.save(after, { language: 'en' }); const afterAllLanguages = await entities.getAllLanguages(before.sharedId); - emitSpy.expectToEmitEvent(EntityUpdatedEvent, { + emitSpy.expectToEmitEventWith(EntityUpdatedEvent, { before: beforeAllLanguages, after: afterAllLanguages, targetLanguageKey: 'en', From efef3d916bcfcbf04c156c6b6d0ece84106a4563 Mon Sep 17 00:00:00 2001 From: RafaPolit Date: Wed, 25 Sep 2024 10:00:38 -0500 Subject: [PATCH 2/3] Replaced spies with simple spies. --- app/api/entities/specs/entities.spec.js | 36 ++++++++++++++++--------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/app/api/entities/specs/entities.spec.js b/app/api/entities/specs/entities.spec.js index bc7a2c2310..160f837d24 100644 --- a/app/api/entities/specs/entities.spec.js +++ b/app/api/entities/specs/entities.spec.js @@ -15,6 +15,7 @@ import db from 'api/utils/testing_db'; import { UserInContextMockFactory } from 'api/utils/testingUserInContext'; import { UserRole } from 'shared/types/userSchema'; +import { applicationEventsBus } from 'api/eventsbus'; import fixtures, { adminId, batmanFinishesId, @@ -511,7 +512,8 @@ describe('entities', () => { describe('events', () => { it('should emit an event when an entity is created', async () => { - const emitSpy = spyOnEmit(); + const emitSpy = jest.spyOn(applicationEventsBus, 'emit'); + const newEntity = { template: templateId, title: 'New Super Hero', @@ -533,15 +535,19 @@ describe('entities', () => { const afterAllLanguages = await entities.getAllLanguages(savedEntity.sharedId); - emitSpy.expectToEmitEventWith(EntityCreatedEvent, { - entities: afterAllLanguages, - targetLanguageKey: 'es', - }); - emitSpy.restore(); + expect(emitSpy.mock.calls[0][0]).toBeInstanceOf(EntityCreatedEvent); + expect(emitSpy).toHaveBeenCalledWith( + new EntityCreatedEvent({ + entities: afterAllLanguages, + targetLanguageKey: 'es', + }) + ); + + emitSpy.mockRestore(); }); it('should emit an event when an entity is updated', async () => { - const emitSpy = spyOnEmit(); + const emitSpy = jest.spyOn(applicationEventsBus, 'emit'); const before = fixtures.entities.find(e => e._id === batmanFinishesId); const beforeAllLanguages = await entities.getAllLanguages(before.sharedId); const after = { ...before, title: 'new title' }; @@ -550,12 +556,16 @@ describe('entities', () => { const afterAllLanguages = await entities.getAllLanguages(before.sharedId); - emitSpy.expectToEmitEventWith(EntityUpdatedEvent, { - before: beforeAllLanguages, - after: afterAllLanguages, - targetLanguageKey: 'en', - }); - emitSpy.restore(); + expect(emitSpy.mock.calls[0][0]).toBeInstanceOf(EntityUpdatedEvent); + expect(emitSpy).toHaveBeenCalledWith( + new EntityUpdatedEvent({ + before: beforeAllLanguages, + after: afterAllLanguages, + targetLanguageKey: 'en', + }) + ); + + emitSpy.mockRestore(); }); }); }); From e3905828769e442a9396168b775ee54c34f644ea Mon Sep 17 00:00:00 2001 From: RafaPolit Date: Wed, 25 Sep 2024 11:20:45 -0500 Subject: [PATCH 3/3] Propagated language to entity save. --- app/api/entities/entities.js | 11 ++++++++--- app/api/entities/specs/entities.spec.js | 16 ++++++++-------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/app/api/entities/entities.js b/app/api/entities/entities.js index 7ed0148d5f..fd3f35e94d 100644 --- a/app/api/entities/entities.js +++ b/app/api/entities/entities.js @@ -158,7 +158,7 @@ async function updateEntity(entity, _template, unrestricted = false) { return result; } -async function createEntity(doc, languages, sharedId, docTemplate) { +async function createEntity(doc, [currentLanguage, languages], sharedId, docTemplate) { if (!docTemplate) docTemplate = await templates.getById(doc.template); const thesauriByKey = await templates.getRelatedThesauri(docTemplate); @@ -208,7 +208,7 @@ async function createEntity(doc, languages, sharedId, docTemplate) { await applicationEventsBus.emit( new EntityCreatedEvent({ entities: await model.get({ sharedId }), - targetLanguageKey: languages[0].key, + targetLanguageKey: currentLanguage, }) ); @@ -419,7 +419,12 @@ export default { docTemplate = defaultTemplate; } doc.metadata = doc.metadata || {}; - await this.createEntity(this.sanitize(doc, docTemplate), languages, sharedId, docTemplate); + await this.createEntity( + this.sanitize(doc, docTemplate), + [language, languages], + sharedId, + docTemplate + ); } const [entity] = includeDocuments diff --git a/app/api/entities/specs/entities.spec.js b/app/api/entities/specs/entities.spec.js index 160f837d24..6e28939018 100644 --- a/app/api/entities/specs/entities.spec.js +++ b/app/api/entities/specs/entities.spec.js @@ -511,9 +511,14 @@ describe('entities', () => { }); describe('events', () => { - it('should emit an event when an entity is created', async () => { - const emitSpy = jest.spyOn(applicationEventsBus, 'emit'); + let emitSpy; + + beforeEach(() => { + emitSpy = jest.spyOn(applicationEventsBus, 'emit'); + emitSpy.mockClear(); + }); + it('should emit an event when an entity is created', async () => { const newEntity = { template: templateId, title: 'New Super Hero', @@ -539,15 +544,12 @@ describe('entities', () => { expect(emitSpy).toHaveBeenCalledWith( new EntityCreatedEvent({ entities: afterAllLanguages, - targetLanguageKey: 'es', + targetLanguageKey: 'en', }) ); - - emitSpy.mockRestore(); }); it('should emit an event when an entity is updated', async () => { - const emitSpy = jest.spyOn(applicationEventsBus, 'emit'); const before = fixtures.entities.find(e => e._id === batmanFinishesId); const beforeAllLanguages = await entities.getAllLanguages(before.sharedId); const after = { ...before, title: 'new title' }; @@ -564,8 +566,6 @@ describe('entities', () => { targetLanguageKey: 'en', }) ); - - emitSpy.mockRestore(); }); }); });