forked from Code-4-Community/scaffolding
-
Notifications
You must be signed in to change notification settings - Fork 0
[SSF-51] Food request backend tests #53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
a20d7e0
Setup initial test
dburkhart07 57e7c8a
Finished tests for controller and service
dburkhart07 c9bbc85
Removed endpoint from apiClient
dburkhart07 46c4d73
Updated comment per review
dburkhart07 b3550e4
Cleaned up tests
dburkhart07 e9dcc5c
Final commit:
dburkhart07 459fb3e
Final commit fr
dburkhart07 ce376a1
Final commit fr this time!
dburkhart07 858c54a
Resolved merge conflicts
dburkhart07 97fdb60
Final commit
dburkhart07 82158b3
Resolved comments
dburkhart07 c3df1a7
prettier
dburkhart07 02a8180
Resolved merge conflicts
dburkhart07 d5442da
prettier
dburkhart07 f7615e0
Fixed tests
dburkhart07 9cbb1ea
Resolved merge conflicts
dburkhart07 7c89f01
Fixed unit tests
dburkhart07 3be69ae
prettier
dburkhart07 8d9ce44
Fixed dependency issue for food requests
dburkhart07 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
322 changes: 322 additions & 0 deletions
322
apps/backend/src/foodRequests/request.controller.spec.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,322 @@ | ||
| import { RequestsService } from './request.service'; | ||
| import { RequestsController } from './request.controller'; | ||
| import { Test, TestingModule } from '@nestjs/testing'; | ||
| import { mock } from 'jest-mock-extended'; | ||
| import { AWSS3Service } from '../aws/aws-s3.service'; | ||
| import { OrdersService } from '../orders/order.service'; | ||
| import { Readable } from 'stream'; | ||
| import { FoodRequest } from './request.entity'; | ||
| import { RequestSize } from './types'; | ||
| import { OrderStatus } from '../orders/types'; | ||
|
|
||
| const mockRequestsService = mock<RequestsService>(); | ||
| const mockOrdersService = mock<OrdersService>(); | ||
| const mockAWSS3Service = mock<AWSS3Service>(); | ||
|
|
||
| const foodRequest: Partial<FoodRequest> = { | ||
| requestId: 1, | ||
| pantryId: 1, | ||
| }; | ||
|
|
||
| describe('RequestsController', () => { | ||
| let controller: RequestsController; | ||
|
|
||
| beforeEach(async () => { | ||
| mockRequestsService.findOne.mockReset(); | ||
| mockRequestsService.find.mockReset(); | ||
| mockRequestsService.create.mockReset(); | ||
| mockRequestsService.updateDeliveryDetails?.mockReset(); | ||
| mockAWSS3Service.upload.mockReset(); | ||
| mockOrdersService.updateStatus.mockReset(); | ||
|
|
||
| const module: TestingModule = await Test.createTestingModule({ | ||
| controllers: [RequestsController], | ||
| providers: [ | ||
| { | ||
| provide: RequestsService, | ||
| useValue: mockRequestsService, | ||
| }, | ||
| { | ||
| provide: OrdersService, | ||
| useValue: mockOrdersService, | ||
| }, | ||
| { | ||
| provide: AWSS3Service, | ||
| useValue: mockAWSS3Service, | ||
| }, | ||
| ], | ||
| }).compile(); | ||
|
|
||
| controller = module.get<RequestsController>(RequestsController); | ||
| }); | ||
|
|
||
| it('should be defined', () => { | ||
| expect(controller).toBeDefined(); | ||
| }); | ||
|
|
||
| describe('GET /:requestId', () => { | ||
| it('should call requestsService.findOne and return a specific food request', async () => { | ||
| const requestId = 1; | ||
|
|
||
| mockRequestsService.findOne.mockResolvedValueOnce( | ||
| foodRequest as FoodRequest, | ||
| ); | ||
|
|
||
| const result = await controller.getRequest(requestId); | ||
|
|
||
| expect(result).toEqual(foodRequest); | ||
| expect(mockRequestsService.findOne).toHaveBeenCalledWith(requestId); | ||
| }); | ||
| }); | ||
|
|
||
| describe('GET /get-all-requests/:pantryId', () => { | ||
| it('should call requestsService.find and return all food requests for a specific pantry', async () => { | ||
| const foodRequests: Partial<FoodRequest>[] = [ | ||
| foodRequest, | ||
| { | ||
| requestId: 2, | ||
| pantryId: 1, | ||
| }, | ||
| ]; | ||
| const pantryId = 1; | ||
|
|
||
| mockRequestsService.find.mockResolvedValueOnce( | ||
| foodRequests as FoodRequest[], | ||
| ); | ||
|
|
||
| const result = await controller.getAllPantryRequests(pantryId); | ||
|
|
||
| expect(result).toEqual(foodRequests); | ||
| expect(mockRequestsService.find).toHaveBeenCalledWith(pantryId); | ||
| }); | ||
| }); | ||
|
|
||
| describe('POST /create', () => { | ||
| it('should call requestsService.create and return the created food request', async () => { | ||
| const createBody: Partial<FoodRequest> = { | ||
| pantryId: 1, | ||
| requestedSize: RequestSize.MEDIUM, | ||
| requestedItems: ['Test item 1', 'Test item 2'], | ||
| additionalInformation: 'Test information.', | ||
| dateReceived: null, | ||
| feedback: null, | ||
| photos: null, | ||
| }; | ||
|
|
||
| const createdRequest: Partial<FoodRequest> = { | ||
| requestId: 1, | ||
| ...createBody, | ||
| requestedAt: new Date(), | ||
| order: null, | ||
| }; | ||
|
|
||
| mockRequestsService.create.mockResolvedValueOnce( | ||
| createdRequest as FoodRequest, | ||
| ); | ||
|
|
||
| const result = await controller.createRequest(createBody as FoodRequest); | ||
|
|
||
| expect(result).toEqual(createdRequest); | ||
| expect(mockRequestsService.create).toHaveBeenCalledWith( | ||
| createBody.pantryId, | ||
| createBody.requestedSize, | ||
| createBody.requestedItems, | ||
| createBody.additionalInformation, | ||
| createBody.dateReceived, | ||
| createBody.feedback, | ||
| createBody.photos, | ||
| ); | ||
| }); | ||
| }); | ||
|
|
||
| describe('POST /:requestId/confirm-delivery', () => { | ||
| it('should upload photos, update the order, then update the request', async () => { | ||
| const requestId = 1; | ||
|
|
||
| const body = { | ||
| dateReceived: new Date().toISOString(), | ||
| feedback: 'Nice delivery!', | ||
| }; | ||
|
|
||
| // Mock Photos | ||
| const mockStream = new Readable(); | ||
| mockStream._read = () => {}; | ||
|
|
||
| const photos: Express.Multer.File[] = [ | ||
| { | ||
| fieldname: 'photos', | ||
| originalname: 'photo1.jpg', | ||
| encoding: '7bit', | ||
| mimetype: 'image/jpeg', | ||
| buffer: Buffer.from('image1'), | ||
| size: 1000, | ||
| destination: '', | ||
| filename: '', | ||
| path: '', | ||
| stream: mockStream, | ||
| }, | ||
| { | ||
| fieldname: 'photos', | ||
| originalname: 'photo2.jpg', | ||
| encoding: '7bit', | ||
| mimetype: 'image/jpeg', | ||
| buffer: Buffer.from('image2'), | ||
| size: 2000, | ||
| destination: '', | ||
| filename: '', | ||
| path: '', | ||
| stream: mockStream, | ||
| }, | ||
| ]; | ||
|
|
||
| const uploadedUrls = [ | ||
| 'https://fake-s3/photo1.jpg', | ||
| 'https://fake-s3/photo2.jpg', | ||
| ]; | ||
|
|
||
| // Mock AWS upload | ||
| mockAWSS3Service.upload.mockResolvedValue(uploadedUrls); | ||
|
|
||
| // Mock RequestsService.findOne | ||
| mockRequestsService.findOne.mockResolvedValue({ | ||
| requestId, | ||
| pantryId: 1, | ||
| order: { orderId: 99 }, | ||
| } as FoodRequest); | ||
|
|
||
| mockOrdersService.updateStatus.mockResolvedValue(); | ||
|
|
||
| const updatedRequest: Partial<FoodRequest> = { | ||
| requestId, | ||
| pantryId: 1, | ||
| dateReceived: new Date(body.dateReceived), | ||
| feedback: body.feedback, | ||
| photos: uploadedUrls, | ||
| }; | ||
|
|
||
| mockRequestsService.updateDeliveryDetails.mockResolvedValue( | ||
| updatedRequest as FoodRequest, | ||
| ); | ||
|
|
||
| const result = await controller.confirmDelivery(requestId, body, photos); | ||
|
|
||
| expect(mockAWSS3Service.upload).toHaveBeenCalledWith(photos); | ||
|
|
||
| expect(mockRequestsService.findOne).toHaveBeenCalledWith(requestId); | ||
|
|
||
| expect(mockOrdersService.updateStatus).toHaveBeenCalledWith( | ||
| 99, | ||
| OrderStatus.DELIVERED, | ||
| ); | ||
|
|
||
| expect(mockRequestsService.updateDeliveryDetails).toHaveBeenCalledWith( | ||
| requestId, | ||
| new Date(body.dateReceived), | ||
| body.feedback, | ||
| uploadedUrls, | ||
| ); | ||
|
|
||
| expect(result).toEqual(updatedRequest); | ||
| }); | ||
|
|
||
| it('should handle no photos being uploaded', async () => { | ||
| const requestId = 1; | ||
|
|
||
| const body = { | ||
| dateReceived: new Date().toISOString(), | ||
| feedback: 'No photos delivery!', | ||
| }; | ||
|
|
||
| mockRequestsService.findOne.mockResolvedValue({ | ||
| requestId, | ||
| pantryId: 1, | ||
| order: { orderId: 100 }, | ||
| } as FoodRequest); | ||
|
|
||
| mockOrdersService.updateStatus.mockResolvedValue(); | ||
|
|
||
| const updatedRequest: Partial<FoodRequest> = { | ||
| requestId, | ||
| pantryId: 1, | ||
| dateReceived: new Date(body.dateReceived), | ||
| feedback: body.feedback, | ||
| photos: [], | ||
| }; | ||
|
|
||
| mockRequestsService.updateDeliveryDetails.mockResolvedValue( | ||
| updatedRequest as FoodRequest, | ||
| ); | ||
|
|
||
| const result = await controller.confirmDelivery(requestId, body); | ||
|
|
||
| expect(mockAWSS3Service.upload).not.toHaveBeenCalled(); | ||
| expect(mockRequestsService.findOne).toHaveBeenCalledWith(requestId); | ||
| expect(mockOrdersService.updateStatus).toHaveBeenCalledWith( | ||
| 100, | ||
| OrderStatus.DELIVERED, | ||
| ); | ||
| expect(mockRequestsService.updateDeliveryDetails).toHaveBeenCalledWith( | ||
| requestId, | ||
| new Date(body.dateReceived), | ||
| body.feedback, | ||
| [], | ||
| ); | ||
| expect(result).toEqual(updatedRequest); | ||
| }); | ||
|
|
||
| it('should handle empty photos array', async () => { | ||
| const requestId = 1; | ||
|
|
||
| const body = { | ||
| dateReceived: new Date().toISOString(), | ||
| feedback: 'Empty photos array delivery!', | ||
| }; | ||
|
|
||
| mockRequestsService.findOne.mockResolvedValue({ | ||
| requestId, | ||
| pantryId: 1, | ||
| order: { orderId: 101 }, | ||
| } as FoodRequest); | ||
|
|
||
| mockOrdersService.updateStatus.mockResolvedValue(); | ||
|
|
||
| const updatedRequest: Partial<FoodRequest> = { | ||
| requestId, | ||
| pantryId: 1, | ||
| dateReceived: new Date(body.dateReceived), | ||
| feedback: body.feedback, | ||
| photos: [], | ||
| }; | ||
|
|
||
| mockRequestsService.updateDeliveryDetails.mockResolvedValue( | ||
| updatedRequest as FoodRequest, | ||
| ); | ||
|
|
||
| const result = await controller.confirmDelivery(requestId, body, []); | ||
|
|
||
| expect(mockAWSS3Service.upload).not.toHaveBeenCalled(); | ||
| expect(mockRequestsService.findOne).toHaveBeenCalledWith(requestId); | ||
| expect(mockOrdersService.updateStatus).toHaveBeenCalledWith( | ||
| 101, | ||
| OrderStatus.DELIVERED, | ||
| ); | ||
| expect(mockRequestsService.updateDeliveryDetails).toHaveBeenCalledWith( | ||
| requestId, | ||
| new Date(body.dateReceived), | ||
| body.feedback, | ||
| [], | ||
| ); | ||
| expect(result).toEqual(updatedRequest); | ||
| }); | ||
|
|
||
| it('should throw an error for invalid date', async () => { | ||
| await expect( | ||
| controller.confirmDelivery( | ||
| 1, | ||
| { dateReceived: 'bad-date', feedback: '' }, | ||
| [], | ||
| ), | ||
| ).rejects.toThrow('Invalid date format for deliveryDate'); | ||
| }); | ||
| }); | ||
| }); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.