From 7872fcf6d8515a7d2cce21e3771fc9114fa4e1b7 Mon Sep 17 00:00:00 2001 From: Anna Hughes Date: Mon, 9 Dec 2024 14:13:50 +0000 Subject: [PATCH] fix: resource models fixes (#715) --- .../resource-feedback.service.spec.ts | 66 +++++++++++++++++++ src/webhooks/webhooks.service.spec.ts | 17 +++-- src/webhooks/webhooks.service.ts | 23 ++++--- test/utils/mockData.ts | 18 ++++- 4 files changed, 107 insertions(+), 17 deletions(-) create mode 100644 src/resource-feedback/resource-feedback.service.spec.ts diff --git a/src/resource-feedback/resource-feedback.service.spec.ts b/src/resource-feedback/resource-feedback.service.spec.ts new file mode 100644 index 00000000..4808198e --- /dev/null +++ b/src/resource-feedback/resource-feedback.service.spec.ts @@ -0,0 +1,66 @@ +import { createMock, DeepMocked } from '@golevelup/ts-jest'; +import { HttpException, HttpStatus } from '@nestjs/common'; +import { Test, TestingModule } from '@nestjs/testing'; +import { getRepositoryToken } from '@nestjs/typeorm'; +import { ResourceService } from 'src/resource/resource.service'; +import { FEEDBACK_TAGS_ENUM } from 'src/utils/constants'; +import { mockResource } from 'test/utils/mockData'; +import { Repository } from 'typeorm'; +import { ResourceFeedbackEntity } from '../entities/resource-feedback.entity'; +import { ResourceFeedbackService } from './resource-feedback.service'; + +describe('ResourceFeedbackService', () => { + let service: ResourceFeedbackService; + let mockResourceFeedbackRepository: DeepMocked>; + let mockResourceService: DeepMocked; + + const resourceFeedbackDto = { + resourceId: mockResource.id, + feedbackTags: FEEDBACK_TAGS_ENUM.RELATABLE, + feedbackDescription: 'feedback comments', + } as ResourceFeedbackEntity; + + beforeEach(async () => { + mockResourceFeedbackRepository = createMock>(); + mockResourceService = createMock(); + + const module: TestingModule = await Test.createTestingModule({ + providers: [ + ResourceFeedbackService, + { + provide: getRepositoryToken(ResourceFeedbackEntity), + useValue: mockResourceFeedbackRepository, + }, + { + provide: ResourceService, + useValue: mockResourceService, + }, + ], + }).compile(); + + service = module.get(ResourceFeedbackService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); + + describe('create', () => { + it('should create a resource feedback when resource exists', async () => { + jest.spyOn(mockResourceService, 'findOne').mockResolvedValueOnce(mockResource); + jest.spyOn(mockResourceFeedbackRepository, 'save').mockResolvedValueOnce(resourceFeedbackDto); + + const result = await service.create(resourceFeedbackDto); + expect(result).toEqual(resourceFeedbackDto); + expect(mockResourceFeedbackRepository.save).toHaveBeenCalledWith(resourceFeedbackDto); + }); + + it('should throw an HttpException when resource does not exist', async () => { + jest.spyOn(mockResourceService, 'findOne').mockResolvedValueOnce(null); + + await expect(service.create(resourceFeedbackDto)).rejects.toThrow( + new HttpException('RESOURCE NOT FOUND', HttpStatus.NOT_FOUND), + ); + }); + }); +}); diff --git a/src/webhooks/webhooks.service.spec.ts b/src/webhooks/webhooks.service.spec.ts index 30ef7ab5..4bb90413 100644 --- a/src/webhooks/webhooks.service.spec.ts +++ b/src/webhooks/webhooks.service.spec.ts @@ -28,6 +28,7 @@ import { mockCourseStoryblokResult, mockPartnerAccessEntity, mockResource, + mockResource2, mockResourceStoryblokResult, mockSession, mockSessionStoryblokResult, @@ -43,6 +44,7 @@ import { mockPartnerAccessRepositoryMethods, mockPartnerAdminRepositoryMethods, mockPartnerRepositoryMethods, + mockResourceRepositoryMethods, mockSessionRepositoryMethods, mockSlackMessageClientMethods, mockTherapySessionRepositoryMethods, @@ -85,7 +87,9 @@ describe('WebhooksService', () => { const mockedCoursePartnerService = createMock( mockCoursePartnerServiceMethods, ); - const mockedResourceRepository = createMock>(); + const mockedResourceRepository = createMock>( + mockResourceRepositoryMethods, + ); const mockedUserRepository = createMock>(mockUserRepositoryMethods); const mockedTherapySessionRepository = createMock>( mockTherapySessionRepositoryMethods, @@ -480,7 +484,7 @@ describe('WebhooksService', () => { expect(deletedResource.status).toBe(STORYBLOK_STORY_STATUS_ENUM.DELETED); }); - it.skip('should handle a new resource', async () => { + it('should handle a new resource', async () => { const resourceSaveRepoSpy = jest.spyOn(mockedResourceRepository, 'save'); const resourceFindOneRepoSpy = jest .spyOn(mockedResourceRepository, 'findOneBy') @@ -516,18 +520,18 @@ describe('WebhooksService', () => { expect(resource).toEqual(expectedResponse); expect(resourceSaveRepoSpy).toHaveBeenCalledWith(expectedResponse); expect(resourceFindOneRepoSpy).toHaveBeenCalledWith({ - storyblokUuid: mockResourceStoryblokResult.data.story.id, + storyblokUuid: mockResourceStoryblokResult.data.story.uuid, }); resourceSaveRepoSpy.mockClear(); resourceFindOneRepoSpy.mockClear(); }); - it.skip('should handle updating an existing resource', async () => { + it('should handle updating an existing resource', async () => { const resourceSaveRepoSpy = jest.spyOn(mockedResourceRepository, 'save'); const resourceFindOneRepoSpy = jest .spyOn(mockedResourceRepository, 'findOneBy') - .mockImplementationOnce(async () => mockResource); + .mockImplementationOnce(async () => mockResource2); const updatedMockResourceStoryblokResult = { ...mockResourceStoryblokResult }; const newName = 'New resource name'; @@ -552,6 +556,7 @@ describe('WebhooksService', () => { }; const expectedResponse = { + ...mockResource2, storyblokId: mockResourceStoryblokResult.data.story.id, storyblokUuid: mockResourceStoryblokResult.data.story.uuid, status: STORYBLOK_STORY_STATUS_ENUM.PUBLISHED, @@ -565,7 +570,7 @@ describe('WebhooksService', () => { expect(updatedResource).toEqual(expectedResponse); expect(resourceSaveRepoSpy).toHaveBeenCalled(); expect(resourceFindOneRepoSpy).toHaveBeenCalledWith({ - storyblokUuid: mockResourceStoryblokResult.data.story.id, + storyblokUuid: mockResourceStoryblokResult.data.story.uuid, }); resourceSaveRepoSpy.mockClear(); diff --git a/src/webhooks/webhooks.service.ts b/src/webhooks/webhooks.service.ts index a48de2b6..2463bc59 100644 --- a/src/webhooks/webhooks.service.ts +++ b/src/webhooks/webhooks.service.ts @@ -263,7 +263,10 @@ export class WebhooksService { } } - private async updateOrCreateStory(storyData: ISbStoryData, status: STORYBLOK_STORY_STATUS_ENUM) { + private async updateOrCreateStoryData( + storyData: ISbStoryData, + status: STORYBLOK_STORY_STATUS_ENUM, + ) { const storyPageComponent = storyData.content.component as STORYBLOK_PAGE_COMPONENTS; const updatedStoryData = { @@ -349,9 +352,7 @@ export class WebhooksService { } } - async updateDeletedStory(story_id: number) { - const status = STORYBLOK_STORY_STATUS_ENUM.DELETED; - + async updateInactiveStoryStatus(story_id: number, status: STORYBLOK_STORY_STATUS_ENUM) { // Story is deleted so cant be fetched from storyblok to get story type // Try to find course with matching story_id first let course = await this.courseRepository.findOneBy({ @@ -394,12 +395,16 @@ export class WebhooksService { this.logger.log(`Storyblok story ${status} request - ${story_id}`); - if (status === STORYBLOK_STORY_STATUS_ENUM.DELETED) { - return this.updateDeletedStory(story_id); + if ( + status === STORYBLOK_STORY_STATUS_ENUM.UNPUBLISHED || + status === STORYBLOK_STORY_STATUS_ENUM.DELETED + ) { + // Story can't be retrieved from storyblok so we just update the status of existing records + return this.updateInactiveStoryStatus(story_id, status); } - // Story was either published, unpublished, or moved - // First get story data from storyblok + // Story was either published or moved + // Retrieve the story data from storyblok before handling the update/create let story: ISbStoryData; const Storyblok = new StoryblokClient({ @@ -422,6 +427,6 @@ export class WebhooksService { } // Create or update the resource/course/session record in our database - return this.updateOrCreateStory(story, status); + return this.updateOrCreateStoryData(story, status); } } diff --git a/test/utils/mockData.ts b/test/utils/mockData.ts index 7027e906..d6710e1f 100644 --- a/test/utils/mockData.ts +++ b/test/utils/mockData.ts @@ -90,7 +90,7 @@ export const mockResourceStoryblokResult = { created_at: '2022-05-05T11:29:10.888Z', published_at: '2022-05-19T16:32:44.502Z', id: 98765, - uuid: 'resourceUuid', + uuid: 'resourceUuid2', content: { _uid: '23456', name: 'Resource name 2', @@ -138,7 +138,7 @@ export const mockResource: ResourceEntity = { resourceUser: [], id: 'resourceId1', storyblokId: 123456, - storyblokUuid: 'resourceStoryblokUuid1', + storyblokUuid: 'resourceUuid1', slug: 'resources/shorts/resource-name', status: STORYBLOK_STORY_STATUS_ENUM.PUBLISHED, name: 'Resource name', @@ -148,6 +148,20 @@ export const mockResource: ResourceEntity = { resourceFeedback: [], }; +export const mockResource2: ResourceEntity = { + id: 'resourceId2', + storyblokId: 98765, + storyblokUuid: 'resourceUuid2', + slug: 'resources/shorts/resource-name', + status: STORYBLOK_STORY_STATUS_ENUM.PUBLISHED, + name: 'Resource name 2', + category: RESOURCE_CATEGORIES.SHORT_VIDEO, + createdAt: new Date(100), + updatedAt: new Date(100), + resourceUser: [], + resourceFeedback: [], +}; + export const mockIFirebaseUser: IFirebaseUser = { iss: '', aud: '',