Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/backend/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { ConfigModule, ConfigService } from '@nestjs/config';
import { MulterModule } from '@nestjs/platform-express';
import typeorm from './config/typeorm';
import { OrdersModule } from './orders/order.module';
import { ManufacturerModule } from './foodManufacturers/manufacturer.module';
import { ManufacturerModule } from './foodManufacturers/manufacturers.module';
import { DonationModule } from './donations/donations.module';
import { DonationItemsModule } from './donationItems/donationItems.module';
import { AllocationModule } from './allocations/allocations.module';
Expand Down
2 changes: 2 additions & 0 deletions apps/backend/src/config/typeorm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { RemoveMultipleVolunteerTypes1764811878152 } from '../migrations/1764811
import { RemoveUnusedStatuses1764816885341 } from '../migrations/1764816885341-RemoveUnusedStatuses';
import { UpdatePantryFields1763762628431 } from '../migrations/1763762628431-UpdatePantryFields';
import { PopulateDummyData1768501812134 } from '../migrations/1768501812134-populateDummyData';
import { UpdateManufacturerEntity1768680807820 } from '../migrations/1768680807820-UpdateManufacturerEntity';

const config = {
type: 'postgres',
Expand Down Expand Up @@ -67,6 +68,7 @@ const config = {
RemoveMultipleVolunteerTypes1764811878152,
RemoveUnusedStatuses1764816885341,
PopulateDummyData1768501812134,
UpdateManufacturerEntity1768680807820,
],
};

Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/donations/donations.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
JoinColumn,
ManyToOne,
} from 'typeorm';
import { FoodManufacturer } from '../foodManufacturers/manufacturer.entity';
import { FoodManufacturer } from '../foodManufacturers/manufacturers.entity';
import { DonationStatus } from './types';

@Entity('donations')
Expand Down
4 changes: 2 additions & 2 deletions apps/backend/src/donations/donations.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { AuthService } from '../auth/auth.service';
import { Donation } from './donations.entity';
import { DonationService } from './donations.service';
import { DonationsController } from './donations.controller';
import { ManufacturerModule } from '../foodManufacturers/manufacturer.module';
import { FoodManufacturer } from '../foodManufacturers/manufacturer.entity';
import { ManufacturerModule } from '../foodManufacturers/manufacturers.module';
import { FoodManufacturer } from '../foodManufacturers/manufacturers.entity';

@Module({
imports: [
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/donations/donations.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Repository } from 'typeorm';
import { Donation } from './donations.entity';
import { DonationService } from './donations.service';
import { mock } from 'jest-mock-extended';
import { FoodManufacturer } from '../foodManufacturers/manufacturer.entity';
import { FoodManufacturer } from '../foodManufacturers/manufacturers.entity';

const mockDonationRepository = mock<Repository<Donation>>();
const mockFoodManufacturerRepository = mock<Repository<FoodManufacturer>>();
Expand Down
2 changes: 1 addition & 1 deletion apps/backend/src/donations/donations.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Donation } from './donations.entity';
import { validateId } from '../utils/validation.utils';
import { FoodManufacturer } from '../foodManufacturers/manufacturer.entity';
import { FoodManufacturer } from '../foodManufacturers/manufacturers.entity';
import { DonationStatus } from './types';

@Injectable()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import {
ArrayNotEmpty,
IsBoolean,
IsEmail,
IsEnum,
IsNotEmpty,
IsOptional,
IsPhoneNumber,
IsString,
Length,
MaxLength,
} from 'class-validator';
import { Allergen, DonateWastedFood, ManufacturerAttribute } from '../types';

export class FoodManufacturerApplicationDto {
@IsString()
@IsNotEmpty()
@Length(1, 255)
foodManufacturerName: string;

@IsString()
@IsNotEmpty()
@Length(1, 255)
foodManufacturerWebsite: string;

@IsString()
@IsNotEmpty()
@Length(1, 255)
contactFirstName: string;

@IsString()
@IsNotEmpty()
@Length(1, 255)
contactLastName: string;

@IsEmail()
@Length(1, 255)
contactEmail: string;

@IsString()
@IsNotEmpty()
@IsPhoneNumber('US', {
message:
'contactPhone must be a valid phone number (make sure all the digits are correct)',
})
contactPhone: string;

@IsOptional()
@IsString()
@IsNotEmpty()
@MaxLength(255)
secondaryContactFirstName?: string;

@IsOptional()
@IsString()
@IsNotEmpty()
@MaxLength(255)
secondaryContactLastName?: string;

@IsOptional()
@IsEmail()
@IsNotEmpty()
@MaxLength(255)
secondaryContactEmail?: string;

@IsOptional()
@IsString()
@IsPhoneNumber('US', {
message:
'secondaryContactPhone must be a valid phone number (make sure all the digits are correct)',
})
@IsNotEmpty()
secondaryContactPhone?: string;

@ArrayNotEmpty()
@IsEnum(Allergen, { each: true })
unlistedProductAllergens: Allergen[];

@ArrayNotEmpty()
@IsEnum(Allergen, { each: true })
facilityFreeAllergens: Allergen[];

@IsBoolean()
productsGlutenFree: boolean;

@IsBoolean()
productsContainSulfites: boolean;

@IsString()
@IsNotEmpty()
@Length(1, 255)
productsSustainableExplanation: string;

@IsBoolean()
inKindDonations: boolean;

@IsEnum(DonateWastedFood)
donateWastedFood: DonateWastedFood;

@IsOptional()
@IsEnum(ManufacturerAttribute)
manufacturerAttribute?: ManufacturerAttribute;

@IsOptional()
@IsString()
@IsNotEmpty()
@MaxLength(255)
additionalComments?: string;

@IsOptional()
@IsBoolean()
newsletterSubscription?: boolean;
}
29 changes: 0 additions & 29 deletions apps/backend/src/foodManufacturers/manufacturer.entity.ts

This file was deleted.

8 changes: 0 additions & 8 deletions apps/backend/src/foodManufacturers/manufacturer.module.ts

This file was deleted.

131 changes: 131 additions & 0 deletions apps/backend/src/foodManufacturers/manufacturers.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import { mock } from 'jest-mock-extended';
import { FoodManufacturersService } from './manufacturers.service';
import { FoodManufacturersController } from './manufacturers.controller';
import { Test, TestingModule } from '@nestjs/testing';
import { FoodManufacturer } from './manufacturers.entity';
import { Allergen, DonateWastedFood, ManufacturerStatus } from './types';
import { FoodManufacturerApplicationDto } from './dtos/manufacturer-application.dto';

const mockManufacturersService = mock<FoodManufacturersService>();

const mockManufacturer1: Partial<FoodManufacturer> = {
foodManufacturerId: 1,
foodManufacturerName: 'Good Foods Inc',
status: ManufacturerStatus.PENDING,
};

const mockManufacturer2: Partial<FoodManufacturer> = {
foodManufacturerId: 2,
foodManufacturerName: 'Healthy Eats LLC',
status: ManufacturerStatus.PENDING,
};

describe('FoodManufacturersController', () => {
let controller: FoodManufacturersController;

beforeEach(async () => {
jest.clearAllMocks();

const module: TestingModule = await Test.createTestingModule({
controllers: [FoodManufacturersController],
providers: [
{
provide: FoodManufacturersService,
useValue: mockManufacturersService,
},
],
}).compile();

controller = module.get<FoodManufacturersController>(
FoodManufacturersController,
);
});

it('should be defined', () => {
expect(controller).toBeDefined();
});

describe('GET /pending', () => {
it('should return pending food manufacturers', async () => {
const mockManufacturers: Partial<FoodManufacturer>[] = [
mockManufacturer1,
mockManufacturer2,
];

mockManufacturersService.getPendingManufacturers.mockResolvedValue(
mockManufacturers as FoodManufacturer[],
);

const result = await controller.getPendingManufacturers();

expect(result).toEqual(mockManufacturers);
expect(result).toHaveLength(2);
expect(result[0].foodManufacturerId).toBe(1);
expect(result[1].foodManufacturerId).toBe(2);
expect(
mockManufacturersService.getPendingManufacturers,
).toHaveBeenCalled();
});
});

describe('GET /:id', () => {
it('should return a food manufacturer by id', async () => {
mockManufacturersService.findOne.mockResolvedValue(
mockManufacturer1 as FoodManufacturer,
);

const result = await controller.getFoodManufacturer(1);

expect(result).toEqual(mockManufacturer1);
expect(mockManufacturersService.findOne).toHaveBeenCalledWith(1);
});
});

describe('POST /api/manufacturers', () => {
it('should submit a food manufacturer application', async () => {
const mockApplicationData: FoodManufacturerApplicationDto = {
foodManufacturerName: 'Good Foods Inc',
foodManufacturerWebsite: 'https://goodfoods.example.com',
contactFirstName: 'Alice',
contactLastName: 'Johnson',
contactEmail: 'alice.johnson@goodfoods.example.com',
contactPhone: '555-123-4567',
unlistedProductAllergens: [Allergen.EGG],
facilityFreeAllergens: [Allergen.EGG],
productsGlutenFree: true,
productsContainSulfites: false,
productsSustainableExplanation: 'We use eco-friendly packaging.',
inKindDonations: true,
donateWastedFood: DonateWastedFood.SOMETIMES,
};

mockManufacturersService.addFoodManufacturer.mockResolvedValue();

await controller.submitFoodManufacturerApplication(mockApplicationData);

expect(mockManufacturersService.addFoodManufacturer).toHaveBeenCalledWith(
mockApplicationData,
);
});
});

describe('POST /approve/:id', () => {
it('should approve a food manufacturer', async () => {
mockManufacturersService.approve.mockResolvedValue();

await controller.approveManufacturer(1);

expect(mockManufacturersService.approve).toHaveBeenCalledWith(1);
});
});

describe('POST /deny/:id', () => {
it('should deny a food manufacturer', async () => {
mockManufacturersService.deny.mockResolvedValue();

await controller.denyManufacturer(1);

expect(mockManufacturersService.deny).toHaveBeenCalledWith(1);
});
});
});
Loading
Loading