From 60beb3cd5414612f12ba92dd2b9ad4d9923bb051 Mon Sep 17 00:00:00 2001 From: Dalton Burkhart Date: Sun, 9 Nov 2025 17:23:09 -0500 Subject: [PATCH 01/12] Initial changes --- apps/backend/src/config/typeorm.ts | 2 + .../src/config/typeormTestDataSource.ts | 52 +++ .../1759636753110-createDummyData.ts | 422 ++++++++++++++++++ apps/backend/src/orders/order.service.spec.ts | 205 ++++----- 4 files changed, 552 insertions(+), 129 deletions(-) create mode 100644 apps/backend/src/config/typeormTestDataSource.ts create mode 100644 apps/backend/src/migrations/1759636753110-createDummyData.ts diff --git a/apps/backend/src/config/typeorm.ts b/apps/backend/src/config/typeorm.ts index 9f66b3ca..d1e03ea5 100644 --- a/apps/backend/src/config/typeorm.ts +++ b/apps/backend/src/config/typeorm.ts @@ -17,6 +17,7 @@ import { UpdateRequestTable1741571847063 } from '../migrations/1741571847063-upd import { RemoveOrderIdFromRequests1744133526650 } from '../migrations/1744133526650-removeOrderIdFromRequests.ts'; import { AddOrders1739496585940 } from '../migrations/1739496585940-addOrders'; import { UpdatePantriesTable1742739750279 } from '../migrations/1742739750279-updatePantriesTable'; +import { CreateDummyData1759636753110 } from '../migrations/1759636753110-createDummyData'; const config = { type: 'postgres', @@ -47,6 +48,7 @@ const config = { UpdateFoodRequests1744051370129, RemoveOrderIdFromRequests1744133526650, UpdatePantriesTable1742739750279, + CreateDummyData1759636753110, ], }; diff --git a/apps/backend/src/config/typeormTestDataSource.ts b/apps/backend/src/config/typeormTestDataSource.ts new file mode 100644 index 00000000..dc2d98ec --- /dev/null +++ b/apps/backend/src/config/typeormTestDataSource.ts @@ -0,0 +1,52 @@ +import 'dotenv/config'; +import { DataSource, DataSourceOptions } from 'typeorm'; +import { PluralNamingStrategy } from '../strategies/plural-naming.strategy'; +import { User1725726359198 } from '../migrations/1725726359198-User'; +import { AddTables1726524792261 } from '../migrations/1726524792261-addTables'; +import { ReviseTables1737522923066 } from '../migrations/1737522923066-reviseTables'; +import { UpdateUserRole1737816745912 } from '../migrations/1737816745912-UpdateUserRole'; +import { UpdatePantriesTable1737906317154 } from '../migrations/1737906317154-updatePantriesTable'; +import { UpdateDonations1738697216020 } from '../migrations/1738697216020-updateDonations'; +import { UpdateDonationColTypes1741708808976 } from '../migrations/1741708808976-UpdateDonationColTypes'; +import { UpdatePantriesTable1738172265266 } from '../migrations/1738172265266-updatePantriesTable'; +import { UpdatePantriesTable1739056029076 } from '../migrations/1739056029076-updatePantriesTable'; +import { AssignmentsPantryIdNotUnique1758384669652 } from '../migrations/1758384669652-AssignmentsPantryIdNotUnique'; +import { AddOrders1739496585940 } from '../migrations/1739496585940-addOrders'; +import { UpdateOrdersTable1740367964915 } from '../migrations/1740367964915-updateOrdersTable'; +import { UpdateFoodRequests1744051370129 } from '../migrations/1744051370129-updateFoodRequests.ts'; +import { UpdateRequestTable1741571847063 } from '../migrations/1741571847063-updateRequestTable'; +import { RemoveOrderIdFromRequests1744133526650 } from '../migrations/1744133526650-removeOrderIdFromRequests.ts'; +import { UpdatePantriesTable1742739750279 } from '../migrations/1742739750279-updatePantriesTable'; +import { CreateDummyData1759636753110 } from '../migrations/1759636753110-createDummyData'; + +const testConfig: DataSourceOptions = { + type: 'postgres', + host: `${process.env.DATABASE_HOST}`, + port: parseInt(`${process.env.DATABASE_PORT}`, 10), + database: `${process.env.DATABASE_NAME_TEST}`, + username: `${process.env.DATABASE_USERNAME}`, + password: `${process.env.DATABASE_PASSWORD}`, + synchronize: false, + namingStrategy: new PluralNamingStrategy(), + migrations: [ + User1725726359198, + AddTables1726524792261, + ReviseTables1737522923066, + UpdateUserRole1737816745912, + UpdatePantriesTable1737906317154, + UpdateDonations1738697216020, + UpdateDonationColTypes1741708808976, + UpdatePantriesTable1738172265266, + UpdatePantriesTable1739056029076, + AssignmentsPantryIdNotUnique1758384669652, + AddOrders1739496585940, + UpdateOrdersTable1740367964915, + UpdateRequestTable1741571847063, + UpdateFoodRequests1744051370129, + RemoveOrderIdFromRequests1744133526650, + UpdatePantriesTable1742739750279, + CreateDummyData1759636753110, + ], +}; + +export const testDataSource = new DataSource(testConfig); diff --git a/apps/backend/src/migrations/1759636753110-createDummyData.ts b/apps/backend/src/migrations/1759636753110-createDummyData.ts new file mode 100644 index 00000000..20d5a12b --- /dev/null +++ b/apps/backend/src/migrations/1759636753110-createDummyData.ts @@ -0,0 +1,422 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class CreateDummyData1759636753110 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(` + INSERT INTO public.users (first_name, last_name, email, phone, role) VALUES + ('John', 'Smith', 'john.smith@ssf.org', '555-0101', 'SSF_REPRESENTATIVE'), + ('Sarah', 'Johnson', 'sarah.j@ssf.org', '555-0102', 'SSF_REPRESENTATIVE'), + ('Mike', 'Brown', 'mike.brown@pantry1.org', '555-0201', 'PANTRY_REPRESENTATIVE'), + ('Emily', 'Davis', 'emily.davis@pantry2.org', '555-0202', 'PANTRY_REPRESENTATIVE'), + ('Robert', 'Wilson', 'robert.w@pantry3.org', '555-0203', 'PANTRY_REPRESENTATIVE'), + ('Lisa', 'Martinez', 'lisa.m@foodcorp.com', '555-0301', 'MANUFACTURER_REPRESENTATIVE'), + ('David', 'Anderson', 'david.a@healthyfoods.com', '555-0302', 'MANUFACTURER_REPRESENTATIVE'), + ('Jennifer', 'Taylor', 'jennifer.t@organic.com', '555-0303', 'MANUFACTURER_REPRESENTATIVE'), + ('James', 'Thomas', 'james.t@volunteer.org', '555-0401', 'VOLUNTEER'), + ('Maria', 'Garcia', 'maria.g@volunteer.org', '555-0402', 'VOLUNTEER'), + ('William', 'Moore', 'william.m@volunteer.org', '555-0403', 'VOLUNTEER'), + ('Patricia', 'Jackson', 'patricia.j@volunteer.org', '555-0404', 'VOLUNTEER') + `); + + await queryRunner.query(` + INSERT INTO public.food_manufacturers (food_manufacturer_name, food_manufacturer_representative_id) VALUES + ('FoodCorp Industries', (SELECT user_id FROM public.users WHERE email = 'lisa.m@foodcorp.com')), + ('Healthy Foods Co', (SELECT user_id FROM public.users WHERE email = 'david.a@healthyfoods.com')), + ('Organic Suppliers LLC', (SELECT user_id FROM public.users WHERE email = 'jennifer.t@organic.com')) + `); + + await queryRunner.query(` + INSERT INTO public.pantries ( + pantry_name, address, allergen_clients, refrigerated_donation, + reserve_food_for_allergic, reservation_explanation, dedicated_allergy_friendly, + client_visit_frequency, identify_allergens_confidence, serve_allergic_children, + newsletter_subscription, restrictions, ssf_representative_id, pantry_representative_id, + activities, questions, items_in_stock, need_more_options, status + ) VALUES + ( + 'Community Food Pantry Downtown', + '123 Main St, Springfield, IL 62701', + 'yes', + 'yes', + true, + 'We have several clients with severe nut allergies and need to keep separate storage', + 'Dedicated shelf for allergen-free items', + 'weekly', + 'very_confident', + 'yes', + true, + ARRAY['peanuts', 'tree_nuts', 'shellfish'], + (SELECT user_id FROM public.users WHERE email = 'john.smith@ssf.org'), + (SELECT user_id FROM public.users WHERE email = 'mike.brown@pantry1.org'), + 'Food distribution, nutrition education, cooking classes', + 'How can we better serve clients with multiple allergies?', + 'Canned goods, pasta, rice, cereal', + 'More fresh produce and dairy alternatives', + 'active' + ), + ( + 'Westside Community Kitchen', + '456 Oak Ave, Springfield, IL 62702', + 'some', + 'no', + false, + 'Limited space for separate storage', + 'None currently', + 'monthly', + 'somewhat_confident', + 'no', + true, + ARRAY['gluten'], + (SELECT user_id FROM public.users WHERE email = 'sarah.j@ssf.org'), + (SELECT user_id FROM public.users WHERE email = 'emily.davis@pantry2.org'), + 'Weekly meal service, food boxes', + NULL, + 'Bread, canned vegetables, soup', + 'Gluten-free options', + 'active' + ), + ( + 'North End Food Bank', + '789 Pine Rd, Springfield, IL 62703', + 'no', + 'yes', + true, + 'Expanding allergen-friendly program', + 'Separate refrigerator for allergen-free items', + 'bi-weekly', + 'confident', + 'yes', + false, + ARRAY['dairy', 'eggs'], + (SELECT user_id FROM public.users WHERE email = 'john.smith@ssf.org'), + (SELECT user_id FROM public.users WHERE email = 'robert.w@pantry3.org'), + 'Emergency food assistance, senior programs', + 'Can we get more information about cross-contamination prevention?', + 'Proteins, grains, canned fruits', + 'Dairy-free and egg-free alternatives', + 'pending' + ) + `); + + await queryRunner.query(` + INSERT INTO public.donations ( + food_manufacturer_id, date_donated, status, total_items, total_oz, total_estimated_value + ) VALUES + ( + (SELECT food_manufacturer_id FROM public.food_manufacturers WHERE food_manufacturer_name = 'FoodCorp Industries'), + '2024-01-15 10:30:00', + 'available', + 150, + 2400.50, + 850.00 + ), + ( + (SELECT food_manufacturer_id FROM public.food_manufacturers WHERE food_manufacturer_name = 'Healthy Foods Co'), + '2024-01-20 14:00:00', + 'partially_allocated', + 200, + 3200.00, + 1200.00 + ), + ( + (SELECT food_manufacturer_id FROM public.food_manufacturers WHERE food_manufacturer_name = 'Organic Suppliers LLC'), + '2024-01-25 09:15:00', + 'available', + 100, + 1600.75, + 950.00 + ), + ( + (SELECT food_manufacturer_id FROM public.food_manufacturers WHERE food_manufacturer_name = 'FoodCorp Industries'), + '2024-02-01 11:00:00', + 'fully_allocated', + 75, + 1200.00, + 450.00 + ) + `); + + await queryRunner.query(` + INSERT INTO public.donation_items ( + donation_id, item_name, quantity, reserved_quantity, status, + oz_per_item, estimated_value, food_type + ) VALUES + ( + (SELECT donation_id FROM public.donations WHERE total_items = 150), + 'Peanut Butter (16oz)', + 50, + 10, + 'available', + 16.00, + 4.50, + 'protein' + ), + ( + (SELECT donation_id FROM public.donations WHERE total_items = 150), + 'Whole Wheat Bread', + 50, + 0, + 'available', + 24.00, + 3.00, + 'grain' + ), + ( + (SELECT donation_id FROM public.donations WHERE total_items = 150), + 'Canned Green Beans', + 50, + 5, + 'available', + 8.01, + 2.00, + 'vegetable' + ), + ( + (SELECT donation_id FROM public.donations WHERE total_items = 200), + 'Gluten-Free Pasta', + 75, + 30, + 'partially_reserved', + 16.00, + 5.00, + 'grain' + ), + ( + (SELECT donation_id FROM public.donations WHERE total_items = 200), + 'Almond Milk', + 75, + 20, + 'partially_reserved', + 32.00, + 4.50, + 'dairy_alternative' + ), + ( + (SELECT donation_id FROM public.donations WHERE total_items = 200), + 'Organic Apples', + 50, + 0, + 'available', + 5.00, + 3.50, + 'fruit' + ), + ( + (SELECT donation_id FROM public.donations WHERE total_items = 100), + 'Rice (5lb bag)', + 40, + 0, + 'available', + 80.00, + 12.00, + 'grain' + ), + ( + (SELECT donation_id FROM public.donations WHERE total_items = 100), + 'Canned Tomatoes', + 60, + 0, + 'available', + 10.75, + 2.50, + 'vegetable' + ), + ( + (SELECT donation_id FROM public.donations WHERE total_items = 75), + 'Cereal Boxes', + 75, + 75, + 'fully_reserved', + 16.00, + 6.00, + 'grain' + ) + `); + + await queryRunner.query(` + INSERT INTO public.food_requests ( + pantry_id, requested_size, requested_items, additional_information, + requested_at, date_received, feedback, photos + ) VALUES + ( + (SELECT pantry_id FROM public.pantries WHERE pantry_name = 'Community Food Pantry Downtown'), + 'large', + ARRAY['peanut_butter', 'bread', 'vegetables', 'dairy_alternatives'], + 'We have 150 families to serve this week. Need extra allergen-free options.', + '2024-01-16 08:00:00', + '2024-01-18 14:30:00', + 'Great selection, especially appreciated the allergen-free items', + ARRAY['delivery1.jpg', 'storage1.jpg'] + ), + ( + (SELECT pantry_id FROM public.pantries WHERE pantry_name = 'Westside Community Kitchen'), + 'medium', + ARRAY['gluten_free_pasta', 'vegetables', 'fruits'], + 'Preparing meals for 75 clients this month', + '2024-01-21 09:30:00', + '2024-01-23 10:00:00', + 'Good variety, could use more gluten-free options', + ARRAY['kitchen1.jpg'] + ), + ( + (SELECT pantry_id FROM public.pantries WHERE pantry_name = 'North End Food Bank'), + 'small', + ARRAY['rice', 'canned_goods', 'cereal'], + 'Regular monthly order', + '2024-02-02 10:00:00', + NULL, + NULL, + NULL + ), + ( + (SELECT pantry_id FROM public.pantries WHERE pantry_name = 'Community Food Pantry Downtown'), + 'medium', + ARRAY['cereal', 'milk_alternatives', 'fruits'], + 'Running low on breakfast items', + '2024-02-03 11:00:00', + NULL, + NULL, + NULL + ) + `); + + await queryRunner.query(` + INSERT INTO public.orders ( + request_id, pantry_id, shipped_by, status, created_at, + shipped_at, delivered_at, donation_id + ) VALUES + ( + (SELECT request_id FROM public.food_requests WHERE additional_information LIKE '%150 families%'), + (SELECT pantry_id FROM public.pantries WHERE pantry_name = 'Community Food Pantry Downtown'), + (SELECT food_manufacturer_id FROM public.food_manufacturers WHERE food_manufacturer_name = 'FoodCorp Industries'), + 'delivered', + '2024-01-16 09:00:00', + '2024-01-17 08:00:00', + '2024-01-18 14:30:00', + (SELECT donation_id FROM public.donations WHERE total_items = 150) + ), + ( + (SELECT request_id FROM public.food_requests WHERE additional_information LIKE '%75 clients%'), + (SELECT pantry_id FROM public.pantries WHERE pantry_name = 'Westside Community Kitchen'), + (SELECT food_manufacturer_id FROM public.food_manufacturers WHERE food_manufacturer_name = 'Healthy Foods Co'), + 'delivered', + '2024-01-21 10:00:00', + '2024-01-22 09:00:00', + '2024-01-23 10:00:00', + (SELECT donation_id FROM public.donations WHERE total_items = 200) + ), + ( + (SELECT request_id FROM public.food_requests WHERE additional_information = 'Regular monthly order'), + (SELECT pantry_id FROM public.pantries WHERE pantry_name = 'North End Food Bank'), + (SELECT food_manufacturer_id FROM public.food_manufacturers WHERE food_manufacturer_name = 'Organic Suppliers LLC'), + 'shipped', + '2024-02-02 11:00:00', + '2024-02-03 08:00:00', + NULL, + (SELECT donation_id FROM public.donations WHERE total_items = 100) + ), + ( + (SELECT request_id FROM public.food_requests WHERE additional_information LIKE '%breakfast items%'), + (SELECT pantry_id FROM public.pantries WHERE pantry_name = 'Community Food Pantry Downtown'), + (SELECT food_manufacturer_id FROM public.food_manufacturers WHERE food_manufacturer_name = 'FoodCorp Industries'), + 'pending', + '2024-02-03 12:00:00', + NULL, + NULL, + (SELECT donation_id FROM public.donations WHERE total_items = 75) + ), + ( + (SELECT request_id FROM public.food_requests WHERE additional_information LIKE '%breakfast items%'), + (SELECT pantry_id FROM public.pantries WHERE pantry_name = 'Community Food Pantry Downtown'), + (SELECT food_manufacturer_id FROM public.food_manufacturers WHERE food_manufacturer_name = 'FoodCorp Industries'), + 'delivered', + '2024-02-03 12:00:00', + '2024-02-04 12:00:00', + '2024-02-05 12:00:00', + (SELECT donation_id FROM public.donations WHERE total_items = 75) + ) + `); + + await queryRunner.query(` + INSERT INTO public.allocations ( + order_id, item_id, allocated_quantity, reserved_at, fulfilled_at, status + ) VALUES + ( + (SELECT order_id FROM public.orders WHERE status = 'delivered' AND shipped_at = '2024-01-17 08:00:00'), + (SELECT item_id FROM public.donation_items WHERE item_name = 'Peanut Butter (16oz)'), + 10, + '2024-01-16 09:00:00', + '2024-01-18 14:30:00', + 'fulfilled' + ), + ( + (SELECT order_id FROM public.orders WHERE status = 'delivered' AND shipped_at = '2024-01-17 08:00:00'), + (SELECT item_id FROM public.donation_items WHERE item_name = 'Canned Green Beans'), + 5, + '2024-01-16 09:00:00', + '2024-01-18 14:30:00', + 'fulfilled' + ), + ( + (SELECT order_id FROM public.orders WHERE status = 'delivered' AND shipped_at = '2024-01-22 09:00:00'), + (SELECT item_id FROM public.donation_items WHERE item_name = 'Gluten-Free Pasta'), + 30, + '2024-01-21 10:00:00', + '2024-01-23 10:00:00', + 'fulfilled' + ), + ( + (SELECT order_id FROM public.orders WHERE status = 'delivered' AND shipped_at = '2024-01-22 09:00:00'), + (SELECT item_id FROM public.donation_items WHERE item_name = 'Almond Milk'), + 20, + '2024-01-21 10:00:00', + '2024-01-23 10:00:00', + 'fulfilled' + ), + ( + (SELECT order_id FROM public.orders WHERE status = 'pending'), + (SELECT item_id FROM public.donation_items WHERE item_name = 'Cereal Boxes'), + 75, + '2024-02-03 12:00:00', + NULL, + 'pending' + ) + `); + + await queryRunner.query(` + INSERT INTO public.volunteer_assignments (pantry_id, volunteer_id) VALUES + ( + (SELECT pantry_id FROM public.pantries WHERE pantry_name = 'Community Food Pantry Downtown'), + (SELECT user_id FROM public.users WHERE email = 'james.t@volunteer.org') + ), + ( + (SELECT pantry_id FROM public.pantries WHERE pantry_name = 'Community Food Pantry Downtown'), + (SELECT user_id FROM public.users WHERE email = 'patricia.j@volunteer.org') + ), + ( + (SELECT pantry_id FROM public.pantries WHERE pantry_name = 'Westside Community Kitchen'), + (SELECT user_id FROM public.users WHERE email = 'maria.g@volunteer.org') + ), + ( + (SELECT pantry_id FROM public.pantries WHERE pantry_name = 'North End Food Bank'), + (SELECT user_id FROM public.users WHERE email = 'william.m@volunteer.org') + ), + ( + (SELECT pantry_id FROM public.pantries WHERE pantry_name = 'North End Food Bank'), + (SELECT user_id FROM public.users WHERE email = 'maria.g@volunteer.org') + ) + `); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DELETE FROM public.volunteer_assignments`); + await queryRunner.query(`DELETE FROM public.allocations`); + await queryRunner.query(`DELETE FROM public.orders`); + await queryRunner.query(`DELETE FROM public.food_requests`); + await queryRunner.query(`DELETE FROM public.donation_items`); + await queryRunner.query(`DELETE FROM public.donations`); + await queryRunner.query(`DELETE FROM public.pantries`); + await queryRunner.query(`DELETE FROM public.food_manufacturers`); + await queryRunner.query(`DELETE FROM public.users`); + } +} \ No newline at end of file diff --git a/apps/backend/src/orders/order.service.spec.ts b/apps/backend/src/orders/order.service.spec.ts index f13eea50..e5821ea5 100644 --- a/apps/backend/src/orders/order.service.spec.ts +++ b/apps/backend/src/orders/order.service.spec.ts @@ -1,71 +1,36 @@ -import { Test } from '@nestjs/testing'; -import { getRepositoryToken } from '@nestjs/typeorm'; -import { Repository, SelectQueryBuilder } from 'typeorm'; +import { Test, TestingModule } from '@nestjs/testing'; +import { TypeOrmModule } from '@nestjs/typeorm'; import { Order } from './order.entity'; import { OrdersService } from './order.service'; -import { mock } from 'jest-mock-extended'; -import { Pantry } from '../pantries/pantries.entity'; -import { User } from '../users/user.entity'; - -const mockOrdersRepository = mock>(); - -const mockPantry: Pantry = { - pantryId: 1, - pantryName: 'Test Pantry', - addressLine1: '123 Test St', - addressLine2: 'Apt. 1', - addressCity: 'Boston', - addressState: 'MA', - addressZip: '02115', - addressCountry: 'US', - allergenClients: '', - refrigeratedDonation: '', - reserveFoodForAllergic: 'Yes', - reservationExplanation: '', - dedicatedAllergyFriendly: '', - clientVisitFrequency: '', - identifyAllergensConfidence: '', - serveAllergicChildren: '', - newsletterSubscription: false, - restrictions: [], - pantryRepresentative: null as unknown as User, - status: 'active', - dateApplied: new Date(), - activities: [], - activitiesComments: '', - itemsInStock: '', - needMoreOptions: '', -}; +import { OrdersModule } from './order.module'; +import { testDataSource } from '../config/typeormTestDataSource'; +import { Repository } from 'typeorm'; describe('OrdersService', () => { let service: OrdersService; - let qb: SelectQueryBuilder; + let repository: Repository; beforeAll(async () => { - mockOrdersRepository.createQueryBuilder.mockReset(); + // Initialize the DataSource if it hasn't been initialized yet + if (!testDataSource.isInitialized) { + await testDataSource.initialize(); + } - const module = await Test.createTestingModule({ - providers: [ - OrdersService, - { - provide: getRepositoryToken(Order), - useValue: mockOrdersRepository, - }, - ], + const module: TestingModule = await Test.createTestingModule({ + imports: [OrdersModule], }).compile(); service = module.get(OrdersService); + repository = testDataSource.getRepository(Order); }); - beforeEach(() => { - qb = { - leftJoinAndSelect: jest.fn().mockReturnThis(), - select: jest.fn().mockReturnThis(), - andWhere: jest.fn().mockReturnThis(), - getMany: jest.fn().mockResolvedValue([]), - } as unknown as SelectQueryBuilder; + beforeEach(async () => { + await testDataSource.dropDatabase(); // wipe DB + await testDataSource.runMigrations(); // rebuild schema from migrations + }); - mockOrdersRepository.createQueryBuilder.mockReturnValue(qb); + afterAll(async () => { + await testDataSource.destroy(); }); it('should be defined', () => { @@ -74,116 +39,98 @@ describe('OrdersService', () => { describe('getAll', () => { it('should return orders filtered by status', async () => { - const mockOrders: Partial[] = [ - { orderId: 1, status: 'pending' }, - { orderId: 2, status: 'delivered' }, - ]; - - (qb.getMany as jest.Mock).mockResolvedValue([mockOrders[0] as Order]); - const result = await service.getAll({ status: 'pending' }); - expect(result).toEqual([mockOrders[0]]); - expect(qb.andWhere).toHaveBeenCalledWith('order.status = :status', { - status: 'pending', - }); + expect(result).toEqual([ + { + orderId: 4, + requestId: 4, + pantry: { pantryId: 1, pantryName: 'Community Food Pantry Downtown' }, + shippedBy: 1, + status: 'pending', + createdAt: new Date('2024-02-03 12:00:00'), + shippedAt: null, + deliveredAt: null, + donationId: 1, + }, + ]); }); it('should return empty array when no status filters match', async () => { - (qb.getMany as jest.Mock).mockResolvedValue([]); - const result = await service.getAll({ status: 'invalid status' }); expect(result).toEqual([]); - expect(qb.andWhere).toHaveBeenCalledWith('order.status = :status', { - status: 'invalid status', - }); }); it('should return orders filtered by pantryName', async () => { - const mockOrders: Partial[] = [ + const result = await service.getAll({ + pantryNames: ['Community Food Pantry Downtown'], + }); + + expect(result).toEqual([ { - orderId: 3, + orderId: 1, + requestId: 1, + pantry: { pantryId: 1, pantryName: 'Community Food Pantry Downtown' }, + shippedBy: 1, status: 'delivered', - pantry: { ...mockPantry, pantryName: 'Test Pantry' }, + createdAt: new Date('2024-01-16 09:00:00'), + shippedAt: new Date('2024-01-17 08:00:00'), + deliveredAt: new Date('2024-01-18 14:30:00'), + donationId: 1, }, { orderId: 4, - status: 'delivered', - pantry: { ...mockPantry, pantryName: 'Test Pantry 2' }, - }, - { - orderId: 5, - status: 'delivered', - pantry: { ...mockPantry, pantryName: 'Test Pantry 3' }, + requestId: 4, + pantry: { pantryId: 1, pantryName: 'Community Food Pantry Downtown' }, + shippedBy: 1, + status: 'pending', + createdAt: new Date('2024-02-03 12:00:00'), + shippedAt: null, + deliveredAt: null, + donationId: 1, }, - ]; - - (qb.getMany as jest.Mock).mockResolvedValue( - mockOrders.slice(0, 2) as Order[], - ); - - const result = await service.getAll({ - pantryNames: ['Test Pantry', 'Test Pantry 2'], - }); - - expect(result).toEqual(mockOrders.slice(0, 2) as Order[]); - expect(qb.andWhere).toHaveBeenCalledWith( - 'pantry.pantryName IN (:...pantryNames)', - { pantryNames: ['Test Pantry', 'Test Pantry 2'] }, - ); + ]); }); it('should return empty array when no pantryName filters match', async () => { - (qb.getMany as jest.Mock).mockResolvedValue([]); - const result = await service.getAll({ pantryNames: ['Nonexistent Pantry'], }); expect(result).toEqual([]); - expect(qb.andWhere).toHaveBeenCalledWith( - 'pantry.pantryName IN (:...pantryNames)', - { pantryNames: ['Nonexistent Pantry'] }, - ); }); it('should return orders filtered by both status and pantryName', async () => { - const mockOrders: Partial[] = [ - { - orderId: 3, - status: 'delivered', - pantry: { ...mockPantry, pantryName: 'Test Pantry 1' }, - }, + const result = await service.getAll({ + status: 'delivered', + pantryNames: ['Community Food Pantry Downtown'], + }); + + expect(result).toEqual([ { - orderId: 4, + orderId: 1, + requestId: 1, + pantry: { pantryId: 1, pantryName: 'Community Food Pantry Downtown' }, + shippedBy: 1, status: 'delivered', - pantry: { ...mockPantry, pantryName: 'Test Pantry 2' }, + createdAt: new Date('2024-01-16 09:00:00'), + shippedAt: new Date('2024-01-17 08:00:00'), + deliveredAt: new Date('2024-01-18 14:30:00'), + donationId: 1, }, { orderId: 5, + requestId: 4, + pantry: { pantryId: 1, pantryName: 'Community Food Pantry Downtown' }, + shippedBy: 1, status: 'delivered', - pantry: { ...mockPantry, pantryName: 'Test Pantry 2' }, + createdAt: new Date('2024-02-03 12:00:00'), + shippedAt: new Date('2024-02-04 12:00:00'), + deliveredAt: new Date('2024-02-05 12:00:00'), + donationId: 1, }, - ]; - - (qb.getMany as jest.Mock).mockResolvedValue( - mockOrders.slice(1, 3) as Order[], - ); - - const result = await service.getAll({ - status: 'delivered', - pantryNames: ['Test Pantry 2'], - }); - - expect(result).toEqual(mockOrders.slice(1, 3) as Order[]); - expect(qb.andWhere).toHaveBeenCalledWith('order.status = :status', { - status: 'delivered', - }); - expect(qb.andWhere).toHaveBeenCalledWith( - 'pantry.pantryName IN (:...pantryNames)', - { pantryNames: ['Test Pantry 2'] }, - ); + ]); }); }); }); From 3e6fdebd92c5eda5a134ab1a039a1453b4f63f4a Mon Sep 17 00:00:00 2001 From: Dalton Burkhart Date: Mon, 10 Nov 2025 23:22:32 -0500 Subject: [PATCH 02/12] Initial testing changes --- .../src/config/typeormTestDataSource.ts | 2 + apps/backend/src/orders/order.service.spec.ts | 120 +---- yarn.lock | 489 +++++++++++++----- 3 files changed, 375 insertions(+), 236 deletions(-) diff --git a/apps/backend/src/config/typeormTestDataSource.ts b/apps/backend/src/config/typeormTestDataSource.ts index dc2d98ec..570d2dc0 100644 --- a/apps/backend/src/config/typeormTestDataSource.ts +++ b/apps/backend/src/config/typeormTestDataSource.ts @@ -1,6 +1,8 @@ import 'dotenv/config'; import { DataSource, DataSourceOptions } from 'typeorm'; import { PluralNamingStrategy } from '../strategies/plural-naming.strategy'; +import { Order } from '../orders/order.entity'; +import { Pantry } from '../pantries/pantries.entity'; import { User1725726359198 } from '../migrations/1725726359198-User'; import { AddTables1726524792261 } from '../migrations/1726524792261-addTables'; import { ReviseTables1737522923066 } from '../migrations/1737522923066-reviseTables'; diff --git a/apps/backend/src/orders/order.service.spec.ts b/apps/backend/src/orders/order.service.spec.ts index e5821ea5..d4fcfbfb 100644 --- a/apps/backend/src/orders/order.service.spec.ts +++ b/apps/backend/src/orders/order.service.spec.ts @@ -1,8 +1,7 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { TypeOrmModule } from '@nestjs/typeorm'; +import { getRepositoryToken } from '@nestjs/typeorm'; import { Order } from './order.entity'; import { OrdersService } from './order.service'; -import { OrdersModule } from './order.module'; import { testDataSource } from '../config/typeormTestDataSource'; import { Repository } from 'typeorm'; @@ -11,13 +10,18 @@ describe('OrdersService', () => { let repository: Repository; beforeAll(async () => { - // Initialize the DataSource if it hasn't been initialized yet if (!testDataSource.isInitialized) { await testDataSource.initialize(); } const module: TestingModule = await Test.createTestingModule({ - imports: [OrdersModule], + providers: [ + OrdersService, + { + provide: getRepositoryToken(Order), + useValue: testDataSource.getRepository(Order), + }, + ], }).compile(); service = module.get(OrdersService); @@ -25,8 +29,21 @@ describe('OrdersService', () => { }); beforeEach(async () => { - await testDataSource.dropDatabase(); // wipe DB - await testDataSource.runMigrations(); // rebuild schema from migrations + // reset tables + await testDataSource.synchronize(true); + + // optional: seed one sample record + await repository.save({ + orderId: 1, + requestId: 1, + pantry: { pantryId: 1, pantryName: 'Community Food Pantry Downtown' }, + shippedBy: 1, + status: 'delivered', + createdAt: new Date('2024-01-16T09:00:00Z'), + shippedAt: new Date('2024-01-17T08:00:00Z'), + deliveredAt: new Date('2024-01-18T14:30:00Z'), + donationId: 1, + }); }); afterAll(async () => { @@ -39,98 +56,13 @@ describe('OrdersService', () => { describe('getAll', () => { it('should return orders filtered by status', async () => { - const result = await service.getAll({ status: 'pending' }); - - expect(result).toEqual([ - { - orderId: 4, - requestId: 4, - pantry: { pantryId: 1, pantryName: 'Community Food Pantry Downtown' }, - shippedBy: 1, - status: 'pending', - createdAt: new Date('2024-02-03 12:00:00'), - shippedAt: null, - deliveredAt: null, - donationId: 1, - }, - ]); + const result = await service.getAll({ status: 'delivered' }); + expect(result.length).toBeGreaterThanOrEqual(1); }); it('should return empty array when no status filters match', async () => { - const result = await service.getAll({ status: 'invalid status' }); - + const result = await service.getAll({ status: 'invalid' }); expect(result).toEqual([]); }); - - it('should return orders filtered by pantryName', async () => { - const result = await service.getAll({ - pantryNames: ['Community Food Pantry Downtown'], - }); - - expect(result).toEqual([ - { - orderId: 1, - requestId: 1, - pantry: { pantryId: 1, pantryName: 'Community Food Pantry Downtown' }, - shippedBy: 1, - status: 'delivered', - createdAt: new Date('2024-01-16 09:00:00'), - shippedAt: new Date('2024-01-17 08:00:00'), - deliveredAt: new Date('2024-01-18 14:30:00'), - donationId: 1, - }, - { - orderId: 4, - requestId: 4, - pantry: { pantryId: 1, pantryName: 'Community Food Pantry Downtown' }, - shippedBy: 1, - status: 'pending', - createdAt: new Date('2024-02-03 12:00:00'), - shippedAt: null, - deliveredAt: null, - donationId: 1, - }, - ]); - }); - - it('should return empty array when no pantryName filters match', async () => { - const result = await service.getAll({ - pantryNames: ['Nonexistent Pantry'], - }); - - expect(result).toEqual([]); - }); - - it('should return orders filtered by both status and pantryName', async () => { - const result = await service.getAll({ - status: 'delivered', - pantryNames: ['Community Food Pantry Downtown'], - }); - - expect(result).toEqual([ - { - orderId: 1, - requestId: 1, - pantry: { pantryId: 1, pantryName: 'Community Food Pantry Downtown' }, - shippedBy: 1, - status: 'delivered', - createdAt: new Date('2024-01-16 09:00:00'), - shippedAt: new Date('2024-01-17 08:00:00'), - deliveredAt: new Date('2024-01-18 14:30:00'), - donationId: 1, - }, - { - orderId: 5, - requestId: 4, - pantry: { pantryId: 1, pantryName: 'Community Food Pantry Downtown' }, - shippedBy: 1, - status: 'delivered', - createdAt: new Date('2024-02-03 12:00:00'), - shippedAt: new Date('2024-02-04 12:00:00'), - deliveredAt: new Date('2024-02-05 12:00:00'), - donationId: 1, - }, - ]); - }); }); }); diff --git a/yarn.lock b/yarn.lock index 9f165825..1132a3a9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1083,15 +1083,7 @@ "@babel/highlight" "^7.22.13" chalk "^2.4.2" -"@babel/code-frame@^7.24.7": - version "7.24.7" - resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz" - integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== - dependencies: - "@babel/highlight" "^7.24.7" - picocolors "^1.0.0" - -"@babel/code-frame@^7.27.1": +"@babel/code-frame@^7.26.2", "@babel/code-frame@^7.27.1": version "7.27.1" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.27.1.tgz#200f715e66d52a23b221a9435534a91cc13ad5be" integrity sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg== @@ -1100,31 +1092,57 @@ js-tokens "^4.0.0" picocolors "^1.1.1" -"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.26.8": +"@babel/compat-data@^7.22.6": version "7.26.8" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.8.tgz#821c1d35641c355284d4a870b8a4a7b0c141e367" integrity sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ== +"@babel/compat-data@^7.22.9", "@babel/compat-data@^7.23.2": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.28.5.tgz#a8a4962e1567121ac0b3b487f52107443b455c7f" + integrity sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA== + "@babel/compat-data@^7.27.2": version "7.28.4" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.28.4.tgz#96fdf1af1b8859c8474ab39c295312bfb7c24b04" integrity sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw== -"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.21.3", "@babel/core@^7.22.9", "@babel/core@^7.23.9", "@babel/core@^7.26.0": +"@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.21.3", "@babel/core@^7.22.9": version "7.26.10" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.10.tgz#5c876f83c8c4dcb233ee4b670c0606f2ac3000f9" integrity sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ== dependencies: "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.22.13" - "@babel/generator" "^7.23.0" - "@babel/helper-compilation-targets" "^7.22.15" - "@babel/helper-module-transforms" "^7.23.0" - "@babel/helpers" "^7.23.2" - "@babel/parser" "^7.23.0" - "@babel/template" "^7.22.15" - "@babel/traverse" "^7.23.2" - "@babel/types" "^7.23.0" + "@babel/code-frame" "^7.26.2" + "@babel/generator" "^7.26.10" + "@babel/helper-compilation-targets" "^7.26.5" + "@babel/helper-module-transforms" "^7.26.0" + "@babel/helpers" "^7.26.10" + "@babel/parser" "^7.26.10" + "@babel/template" "^7.26.9" + "@babel/traverse" "^7.26.10" + "@babel/types" "^7.26.10" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/core@^7.22.20": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.28.5.tgz#4c81b35e51e1b734f510c99b07dfbc7bbbb48f7e" + integrity sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.28.5" + "@babel/helper-compilation-targets" "^7.27.2" + "@babel/helper-module-transforms" "^7.28.3" + "@babel/helpers" "^7.28.4" + "@babel/parser" "^7.28.5" + "@babel/template" "^7.27.2" + "@babel/traverse" "^7.28.5" + "@babel/types" "^7.28.5" + "@jridgewell/remapping" "^2.3.5" convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" @@ -1152,22 +1170,27 @@ json5 "^2.2.3" semver "^6.3.1" -"@babel/generator@^7.26.10", "@babel/generator@^7.27.0", "@babel/generator@^7.7.2": +"@babel/generator@^7.23.0", "@babel/generator@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.28.5.tgz#712722d5e50f44d07bc7ac9fe84438742dd61298" + integrity sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ== + dependencies: + "@babel/parser" "^7.28.5" + "@babel/types" "^7.28.5" + "@jridgewell/gen-mapping" "^0.3.12" + "@jridgewell/trace-mapping" "^0.3.28" + jsesc "^3.0.2" + +"@babel/generator@^7.27.0", "@babel/generator@^7.7.2": version "7.27.0" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.27.0.tgz#764382b5392e5b9aff93cadb190d0745866cbc2c" integrity sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw== dependencies: - "@babel/types" "^7.25.6" + "@babel/parser" "^7.27.0" + "@babel/types" "^7.27.0" "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.25" - jsesc "^2.5.1" - -"@babel/helper-annotate-as-pure@^7.22.5": - version "7.22.5" - resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz" - integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg== - dependencies: - "@babel/types" "^7.22.5" + jsesc "^3.0.2" "@babel/generator@^7.27.5", "@babel/generator@^7.28.3": version "7.28.3" @@ -1180,12 +1203,34 @@ "@jridgewell/trace-mapping" "^0.3.28" jsesc "^3.0.2" +"@babel/helper-annotate-as-pure@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz" + integrity sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg== + dependencies: + "@babel/types" "^7.22.5" + "@babel/helper-annotate-as-pure@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz#d8eac4d2dc0d7b6e11fa6e535332e0d3184f06b4" integrity sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g== dependencies: - "@babel/types" "^7.22.15" + "@babel/types" "^7.25.9" + +"@babel/helper-annotate-as-pure@^7.27.1", "@babel/helper-annotate-as-pure@^7.27.3": + version "7.27.3" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz#f31fd86b915fc4daf1f3ac6976c59be7084ed9c5" + integrity sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg== + dependencies: + "@babel/types" "^7.27.3" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.22.5": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.9.tgz#f41752fe772a578e67286e6779a68a5a92de1ee9" + integrity sha512-C47lC7LIDCnz0h4vai/tpNOI95tCd5ZT3iBt/DBH5lXKHZsyNQv18yf1wIIg2ntiQNgmAvA+DgZ82iW8Qdym8g== + dependencies: + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.25.9" "@babel/helper-compilation-targets@^7.22.15", "@babel/helper-compilation-targets@^7.22.5", "@babel/helper-compilation-targets@^7.22.6": version "7.22.15" @@ -1209,7 +1254,7 @@ lru-cache "^5.1.1" semver "^6.3.1" -"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.25.9", "@babel/helper-create-class-features-plugin@^7.27.0": +"@babel/helper-create-class-features-plugin@^7.18.6": version "7.27.0" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.0.tgz#518fad6a307c6a96f44af14912b2c20abe9bfc30" integrity sha512-vSGCvMecvFCd/BdpGlhpXYNhhC4ccxyvQWpbGL4CWbvfEoLFWUZuSuf7s9Aw70flgQF+6vptvgK2IfOnKlRmBg== @@ -1222,6 +1267,19 @@ "@babel/traverse" "^7.27.0" semver "^6.3.1" +"@babel/helper-create-class-features-plugin@^7.22.11", "@babel/helper-create-class-features-plugin@^7.22.15", "@babel/helper-create-class-features-plugin@^7.22.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.5.tgz#472d0c28028850968979ad89f173594a6995da46" + integrity sha512-q3WC4JfdODypvxArsJQROfupPBq9+lMwjKq7C33GhbFYJsufD0yd/ziwD+hJucLeWsnFPWZjsU2DNFqBPE7jwQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.27.3" + "@babel/helper-member-expression-to-functions" "^7.28.5" + "@babel/helper-optimise-call-expression" "^7.27.1" + "@babel/helper-replace-supers" "^7.27.1" + "@babel/helper-skip-transparent-expression-wrappers" "^7.27.1" + "@babel/traverse" "^7.28.5" + semver "^6.3.1" + "@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.22.5": version "7.22.15" resolved "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz" @@ -1242,11 +1300,33 @@ lodash.debounce "^4.0.8" resolve "^1.14.2" +"@babel/helper-environment-visitor@^7.22.20", "@babel/helper-environment-visitor@^7.22.5": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz#4b31ba9551d1f90781ba83491dd59cf9b269f7d9" + integrity sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ== + dependencies: + "@babel/types" "^7.24.7" + +"@babel/helper-function-name@^7.22.5": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz#75f1e1725742f39ac6584ee0b16d94513da38dd2" + integrity sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA== + dependencies: + "@babel/template" "^7.24.7" + "@babel/types" "^7.24.7" + "@babel/helper-globals@^7.28.0": version "7.28.0" resolved "https://registry.yarnpkg.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz#b9430df2aa4e17bc28665eadeae8aa1d985e6674" integrity sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw== +"@babel/helper-hoist-variables@^7.22.5": + version "7.22.5" + resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz" + integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== + dependencies: + "@babel/types" "^7.22.5" + "@babel/helper-member-expression-to-functions@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz#9dfffe46f727005a5ea29051ac835fb735e4c1a3" @@ -1255,7 +1335,15 @@ "@babel/traverse" "^7.25.9" "@babel/types" "^7.25.9" -"@babel/helper-module-imports@^7.16.7", "@babel/helper-module-imports@^7.25.9": +"@babel/helper-member-expression-to-functions@^7.27.1", "@babel/helper-member-expression-to-functions@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz#f3e07a10be37ed7a63461c63e6929575945a6150" + integrity sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg== + dependencies: + "@babel/traverse" "^7.28.5" + "@babel/types" "^7.28.5" + +"@babel/helper-module-imports@^7.16.7": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz#e7f8d20602ebdbf9ebbea0a0751fb0f2a4141715" integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw== @@ -1263,7 +1351,7 @@ "@babel/traverse" "^7.25.9" "@babel/types" "^7.25.9" -"@babel/helper-module-imports@^7.27.1": +"@babel/helper-module-imports@^7.22.15", "@babel/helper-module-imports@^7.22.5", "@babel/helper-module-imports@^7.27.1": version "7.27.1" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz#7ef769a323e2655e126673bb6d2d6913bbead204" integrity sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w== @@ -1271,16 +1359,7 @@ "@babel/traverse" "^7.27.1" "@babel/types" "^7.27.1" -"@babel/helper-module-transforms@^7.25.9", "@babel/helper-module-transforms@^7.26.0": - version "7.26.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae" - integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw== - dependencies: - "@babel/helper-module-imports" "^7.25.9" - "@babel/helper-validator-identifier" "^7.25.9" - "@babel/traverse" "^7.25.9" - -"@babel/helper-module-transforms@^7.28.3": +"@babel/helper-module-transforms@^7.22.5", "@babel/helper-module-transforms@^7.23.0", "@babel/helper-module-transforms@^7.28.3": version "7.28.3" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz#a2b37d3da3b2344fe085dab234426f2b9a2fa5f6" integrity sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw== @@ -1289,6 +1368,13 @@ "@babel/helper-validator-identifier" "^7.27.1" "@babel/traverse" "^7.28.3" +"@babel/helper-optimise-call-expression@^7.22.5", "@babel/helper-optimise-call-expression@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz#c65221b61a643f3e62705e5dd2b5f115e35f9200" + integrity sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw== + dependencies: + "@babel/types" "^7.27.1" + "@babel/helper-optimise-call-expression@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz#3324ae50bae7e2ab3c33f60c9a877b6a0146b54e" @@ -1296,49 +1382,67 @@ dependencies: "@babel/types" "^7.25.9" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.25.9", "@babel/helper-plugin-utils@^7.26.5", "@babel/helper-plugin-utils@^7.8.0": +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0": version "7.26.5" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz#18580d00c9934117ad719392c4f6585c9333cc35" integrity sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg== -"@babel/helper-plugin-utils@^7.27.1": +"@babel/helper-plugin-utils@^7.27.1", "@babel/helper-plugin-utils@^7.8.3": version "7.27.1" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz#ddb2f876534ff8013e6c2b299bf4d39b3c51d44c" integrity sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw== -"@babel/helper-remap-async-to-generator@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz#e53956ab3d5b9fb88be04b3e2f31b523afd34b92" - integrity sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw== +"@babel/helper-remap-async-to-generator@^7.22.20", "@babel/helper-remap-async-to-generator@^7.22.5": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz#4601d5c7ce2eb2aea58328d43725523fcd362ce6" + integrity sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA== dependencies: - "@babel/template" "^7.22.15" - "@babel/types" "^7.23.0" + "@babel/helper-annotate-as-pure" "^7.27.1" + "@babel/helper-wrap-function" "^7.27.1" + "@babel/traverse" "^7.27.1" -"@babel/helper-hoist-variables@^7.22.5": - version "7.22.5" - resolved "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz" - integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== +"@babel/helper-replace-supers@^7.22.20", "@babel/helper-replace-supers@^7.22.5", "@babel/helper-replace-supers@^7.22.9", "@babel/helper-replace-supers@^7.26.5", "@babel/helper-replace-supers@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz#b1ed2d634ce3bdb730e4b52de30f8cccfd692bc0" + integrity sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA== dependencies: - "@babel/types" "^7.22.5" + "@babel/helper-member-expression-to-functions" "^7.27.1" + "@babel/helper-optimise-call-expression" "^7.27.1" + "@babel/traverse" "^7.27.1" -"@babel/helper-member-expression-to-functions@^7.22.15": - version "7.23.0" - resolved "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz" - integrity sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA== +"@babel/helper-simple-access@^7.22.5": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.27.1.tgz#7f2171e29d95d6283ede286a4994f985cbe07973" + integrity sha512-OU4zVQrJgFBNXMjrHs1yFSdlTgufO4tefcUZoqNhukVfw0p8x1Asht/gcGZ3bpHbi8gu/76m4JhrlKPqkrs/WQ== dependencies: - "@babel/traverse" "^7.25.9" - "@babel/types" "^7.25.9" + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" -"@babel/helper-string-parser@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" - integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== +"@babel/helper-skip-transparent-expression-wrappers@^7.22.5", "@babel/helper-skip-transparent-expression-wrappers@^7.25.9", "@babel/helper-skip-transparent-expression-wrappers@^7.27.1": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz#62bb91b3abba8c7f1fec0252d9dbea11b3ee7a56" + integrity sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg== + dependencies: + "@babel/traverse" "^7.27.1" + "@babel/types" "^7.27.1" + +"@babel/helper-split-export-declaration@^7.22.6": + version "7.24.7" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz#83949436890e07fa3d6873c61a96e3bbf692d856" + integrity sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA== + dependencies: + "@babel/types" "^7.24.7" -"@babel/helper-string-parser@^7.27.1": +"@babel/helper-string-parser@^7.24.8", "@babel/helper-string-parser@^7.27.1": version "7.27.1" resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== +"@babel/helper-validator-identifier@^7.22.20", "@babel/helper-validator-identifier@^7.24.7", "@babel/helper-validator-identifier@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz#010b6938fab7cb7df74aa2bbc06aa503b8fe5fb4" + integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q== + "@babel/helper-validator-identifier@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" @@ -1349,32 +1453,21 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz#a7054dcc145a967dd4dc8fee845a57c1316c9df8" integrity sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow== -"@babel/helper-validator-option@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz#86e45bd8a49ab7e03f276577f96179653d41da72" - integrity sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw== - -"@babel/helper-validator-option@^7.27.1": +"@babel/helper-validator-option@^7.22.15", "@babel/helper-validator-option@^7.27.1": version "7.27.1" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz#fa52f5b1e7db1ab049445b421c4471303897702f" integrity sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg== -"@babel/helper-wrap-function@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz#d99dfd595312e6c894bd7d237470025c85eea9d0" - integrity sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g== +"@babel/helper-wrap-function@^7.27.1": + version "7.28.3" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.28.3.tgz#fe4872092bc1438ffd0ce579e6f699609f9d0a7a" + integrity sha512-zdf983tNfLZFletc0RRXYrHrucBEg95NIFMkn6K9dbeMYnsgHaSBGcQqdsCSStG2PYwRre0Qc2NNSCXbG+xc6g== dependencies: - "@babel/helper-validator-identifier" "^7.24.7" - chalk "^2.4.2" - js-tokens "^4.0.0" - picocolors "^1.0.0" - -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.15", "@babel/parser@^7.23.0": - version "7.23.0" - resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz" - integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw== + "@babel/template" "^7.27.2" + "@babel/traverse" "^7.28.3" + "@babel/types" "^7.28.2" -"@babel/helpers@^7.28.4": +"@babel/helpers@^7.23.2", "@babel/helpers@^7.28.4": version "7.28.4" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.28.4.tgz#fe07274742e95bdf7cf1443593eeb8926ab63827" integrity sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w== @@ -1382,13 +1475,28 @@ "@babel/template" "^7.27.2" "@babel/types" "^7.28.4" -"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.26.10", "@babel/parser@^7.27.0": +"@babel/highlight@^7.22.13": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.25.9.tgz#8141ce68fc73757946f983b343f1231f4691acc6" + integrity sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw== + dependencies: + "@babel/helper-validator-identifier" "^7.25.9" + chalk "^2.4.2" + js-tokens "^4.0.0" + picocolors "^1.0.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.27.0": version "7.27.0" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.27.0.tgz#3d7d6ee268e41d2600091cbd4e145ffee85a44ec" integrity sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg== dependencies: "@babel/types" "^7.27.0" +"@babel/parser@^7.23.0": + version "7.23.0" + resolved "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz" + integrity sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw== + "@babel/parser@^7.27.2", "@babel/parser@^7.28.3", "@babel/parser@^7.28.4": version "7.28.4" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.4.tgz#da25d4643532890932cc03f7705fe19637e03fa8" @@ -1396,20 +1504,19 @@ dependencies: "@babel/types" "^7.28.4" -"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz#cc2e53ebf0a0340777fff5ed521943e253b4d8fe" - integrity sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g== +"@babel/parser@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.5.tgz#0b0225ee90362f030efd644e8034c99468893b08" + integrity sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ== dependencies: - "@babel/helper-plugin-utils" "^7.25.9" - "@babel/traverse" "^7.25.9" + "@babel/types" "^7.28.5" -"@babel/plugin-bugfix-safari-class-field-initializer-scope@^7.25.9": - version "7.25.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz#af9e4fb63ccb8abcb92375b2fcfe36b60c774d30" - integrity sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw== +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.15": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz#beb623bd573b8b6f3047bd04c32506adc3e58a72" + integrity sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.27.1" "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.22.15": version "7.22.15" @@ -1507,6 +1614,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.22.5" +"@babel/plugin-syntax-import-attributes@^7.24.7": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz#34c017d54496f9b11b61474e7ea3dfd5563ffe07" + integrity sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/plugin-syntax-import-meta@^7.10.4", "@babel/plugin-syntax-import-meta@^7.8.3": version "7.10.4" resolved "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz" @@ -1535,7 +1649,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": version "7.10.4" resolved "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz" integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== @@ -2214,16 +2328,7 @@ dependencies: regenerator-runtime "^0.14.0" -"@babel/template@^7.25.9", "@babel/template@^7.26.9", "@babel/template@^7.27.0", "@babel/template@^7.3.3": - version "7.27.0" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.0.tgz#b253e5406cc1df1c57dcd18f11760c2dbf40c0b4" - integrity sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA== - dependencies: - "@babel/code-frame" "^7.26.2" - "@babel/parser" "^7.27.0" - "@babel/types" "^7.27.0" - -"@babel/template@^7.27.2": +"@babel/template@^7.22.15", "@babel/template@^7.22.5", "@babel/template@^7.24.7", "@babel/template@^7.27.2": version "7.27.2" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.2.tgz#fa78ceed3c4e7b63ebf6cb39e5852fca45f6809d" integrity sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw== @@ -2232,7 +2337,16 @@ "@babel/parser" "^7.27.2" "@babel/types" "^7.27.1" -"@babel/traverse@^7.16.0", "@babel/traverse@^7.25.9", "@babel/traverse@^7.26.10", "@babel/traverse@^7.26.5", "@babel/traverse@^7.26.8", "@babel/traverse@^7.27.0": +"@babel/template@^7.27.0", "@babel/template@^7.3.3": + version "7.27.0" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.0.tgz#b253e5406cc1df1c57dcd18f11760c2dbf40c0b4" + integrity sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA== + dependencies: + "@babel/code-frame" "^7.26.2" + "@babel/parser" "^7.27.0" + "@babel/types" "^7.27.0" + +"@babel/traverse@^7.16.0", "@babel/traverse@^7.25.9", "@babel/traverse@^7.27.0": version "7.27.0" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.27.0.tgz#11d7e644779e166c0442f9a07274d02cd91d4a70" integrity sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA== @@ -2245,6 +2359,19 @@ debug "^4.3.1" globals "^11.1.0" +"@babel/traverse@^7.23.2", "@babel/traverse@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.28.5.tgz#450cab9135d21a7a2ca9d2d35aa05c20e68c360b" + integrity sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.28.5" + "@babel/helper-globals" "^7.28.0" + "@babel/parser" "^7.28.5" + "@babel/template" "^7.27.2" + "@babel/types" "^7.28.5" + debug "^4.3.1" + "@babel/traverse@^7.27.1", "@babel/traverse@^7.28.3", "@babel/traverse@^7.28.4": version "7.28.4" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.28.4.tgz#8d456101b96ab175d487249f60680221692b958b" @@ -2258,14 +2385,21 @@ "@babel/types" "^7.28.4" debug "^4.3.1" -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.21.3", "@babel/types@^7.25.9", "@babel/types@^7.26.10", "@babel/types@^7.27.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.21.3", "@babel/types@^7.25.9", "@babel/types@^7.27.0", "@babel/types@^7.3.3", "@babel/types@^7.4.4": version "7.27.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.27.0.tgz#ef9acb6b06c3173f6632d993ecb6d4ae470b4559" integrity sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg== dependencies: - "@babel/helper-string-parser" "^7.24.8" - "@babel/helper-validator-identifier" "^7.24.7" - to-fast-properties "^2.0.0" + "@babel/helper-string-parser" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + +"@babel/types@^7.22.15", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.24.7", "@babel/types@^7.25.6", "@babel/types@^7.28.5": + version "7.28.5" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.5.tgz#10fc405f60897c35f07e85493c932c7b5ca0592b" + integrity sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA== + dependencies: + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.28.5" "@babel/types@^7.27.1", "@babel/types@^7.27.3", "@babel/types@^7.28.2", "@babel/types@^7.28.4": version "7.28.4" @@ -3426,7 +3560,7 @@ js-yaml "^3.13.1" resolve-from "^5.0.0" -"@istanbuljs/schema@^0.1.2": +"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3": version "0.1.3" resolved "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== @@ -3739,7 +3873,7 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" -"@jridgewell/gen-mapping@^0.3.12": +"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.12": version "0.3.13" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz#6342a19f44347518c93e43b1ac69deb3c4656a1f" integrity sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA== @@ -3787,6 +3921,11 @@ resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz" integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== +"@jridgewell/sourcemap-codec@^1.5.0": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" + integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== + "@jridgewell/trace-mapping@0.3.9": version "0.3.9" resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz" @@ -4398,7 +4537,7 @@ resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.9.tgz#d229a7b7f9dac167a156992ef23c7f023653f53b" integrity sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA== -"@polka/url@^1.0.0-next.24": +"@polka/url@^1.0.0-next.20": version "1.0.0-next.29" resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.29.tgz#5a40109a1ab5f84d6fd8fc928b19f367cbe7e7b1" integrity sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww== @@ -4444,12 +4583,20 @@ dependencies: "@sinonjs/commons" "^3.0.1" -"@smithy/abort-controller@^4.0.2": - version "4.0.2" - resolved "https://registry.yarnpkg.com/@smithy/abort-controller/-/abort-controller-4.0.2.tgz#36a23e8cc65fc03cacb6afa35dfbfd319c560c6b" - integrity sha512-Sl/78VDtgqKxN2+1qduaVE140XF+Xg+TafkncspwM4jFP/LHr76ZHmIY/y3V1M0mMLNk+Je6IGbzxy23RSToMw== +"@smithy/abort-controller@^2.0.12": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/abort-controller/-/abort-controller-2.2.0.tgz#18983401a5e2154b5c94057730024a7d14cbcd35" + integrity sha512-wRlta7GuLWpTqtFfGo+nZyOO1vEvewdNR1R4rTxpC8XU6vG/NDyrFBhwLZsqg1NUoR1noVaXJPC/7ZK47QCySw== dependencies: - "@smithy/types" "^4.1.0" + "@smithy/types" "^2.12.0" + tslib "^2.6.2" + +"@smithy/abort-controller@^4.0.1": + version "4.2.4" + resolved "https://registry.yarnpkg.com/@smithy/abort-controller/-/abort-controller-4.2.4.tgz#8031d32aea69c714eae49c1f43ce0ea60481d2d3" + integrity sha512-Z4DUr/AkgyFf1bOThW2HwzREagee0sB5ycl+hDiSZOfRLW8ZgrOjDi6g8mHH19yyU5E2A/64W3z6SMIf5XiUSQ== + dependencies: + "@smithy/types" "^4.8.1" tslib "^2.6.2" "@smithy/chunked-blob-reader-native@^4.0.0": @@ -4975,6 +5122,13 @@ "@smithy/util-stream" "^4.0.2" tslib "^2.6.2" +"@smithy/types@^2.12.0": + version "2.12.0" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-2.12.0.tgz#c44845f8ba07e5e8c88eda5aed7e6a0c462da041" + integrity sha512-QwYgloJ0sVNBeBuBs65cIkTbfzV/Q6ZNPCJ99EICFEdJYG50nGIY/uYXp+TbsdJReIuPr0a0kXmCvren3MbRRw== + dependencies: + tslib "^2.6.2" + "@smithy/types@^2.4.0": version "2.4.0" resolved "https://registry.npmjs.org/@smithy/types/-/types-2.4.0.tgz" @@ -4989,6 +5143,13 @@ dependencies: tslib "^2.6.2" +"@smithy/types@^4.8.1": + version "4.8.1" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-4.8.1.tgz#0ecad4e329340c8844e38a18c7608d84cc1c853c" + integrity sha512-N0Zn0OT1zc+NA+UVfkYqQzviRh5ucWwO7mBV3TmHHprMnfcJNfhlPicDkBHi0ewbh+y3evR6cNAW0Raxvb01NA== + dependencies: + tslib "^2.6.2" + "@smithy/url-parser@^2.0.12": version "2.0.12" resolved "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-2.0.12.tgz" @@ -6807,6 +6968,11 @@ base64-js@^1.0.2, base64-js@^1.3.1: resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +baseline-browser-mapping@^2.8.19: + version "2.8.25" + resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.8.25.tgz#947dc6f81778e0fa0424a2ab9ea09a3033e71109" + integrity sha512-2NovHVesVF5TXefsGX1yzx1xgr7+m9JQenvz6FQY3qd+YXkKkYiv+vTCc7OriP9mcDZpTC5mAOYN4ocd29+erA== + basic-auth@^2.0.1: version "2.0.1" resolved "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz" @@ -6943,6 +7109,17 @@ browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.21.10, browserslist@^ node-releases "^2.0.13" update-browserslist-db "^1.0.13" +browserslist@^4.24.0: + version "4.27.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.27.0.tgz#755654744feae978fbb123718b2f139bc0fa6697" + integrity sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw== + dependencies: + baseline-browser-mapping "^2.8.19" + caniuse-lite "^1.0.30001751" + electron-to-chromium "^1.5.238" + node-releases "^2.0.26" + update-browserslist-db "^1.1.4" + bs-logger@0.x: version "0.2.6" resolved "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz" @@ -7083,6 +7260,11 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001538, caniuse-lite@^1.0.30001541: resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001558.tgz" integrity sha512-/Et7DwLqpjS47JPEcz6VnxU9PwcIdVi0ciLXRWBQdj1XFye68pSQYpV0QtPTfUKWuOaEig+/Vez2l74eDc1tPQ== +caniuse-lite@^1.0.30001751: + version "1.0.30001754" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001754.tgz#7758299d9a72cce4e6b038788a15b12b44002759" + integrity sha512-x6OeBXueoAceOmotzx3PO4Zpt4rzpeIFsSr6AAePTZxSkXiYDUmpypEl7e2+8NCd9bD7bXjqyef8CJYPC1jfxg== + caseless@~0.12.0: version "0.12.0" resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz" @@ -7175,11 +7357,6 @@ ci-info@^3.2.0: resolved "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz" integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== -ci-info@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-4.2.0.tgz#cbd21386152ebfe1d56f280a3b5feccbd96764c7" - integrity sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg== - ci-info@^4.2.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-4.3.0.tgz#c39b1013f8fdbd28cd78e62318357d02da160cd7" @@ -8163,6 +8340,11 @@ electron-to-chromium@^1.4.535: resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.571.tgz" integrity sha512-Sc+VtKwKCDj3f/kLBjdyjMpNzoZsU6WuL/wFb6EH8USmHEcebxRXcRrVpOpayxd52tuey4RUDpUsw5OS5LhJqg== +electron-to-chromium@^1.5.238: + version "1.5.249" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.249.tgz#e4fc3a3e60bb347361e4e876bb31903a9132a447" + integrity sha512-5vcfL3BBe++qZ5kuFhD/p8WOM1N9m3nwvJPULJx+4xf2usSlZFJ0qoNYO2fOX4hi3ocuDcmDobtA+5SFr4OmBg== + emittery@^0.13.1: version "0.13.1" resolved "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz" @@ -8380,6 +8562,11 @@ escalade@^3.1.1: resolved "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== +escalade@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + escape-html@~1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz" @@ -9393,7 +9580,7 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: version "4.2.11" resolved "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -10119,9 +10306,9 @@ istanbul-lib-instrument@^6.0.0, istanbul-lib-instrument@^6.0.2: resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz#fa15401df6c15874bcb2105f773325d78c666765" integrity sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q== dependencies: - "@babel/core" "^7.12.3" - "@babel/parser" "^7.14.7" - "@istanbuljs/schema" "^0.1.2" + "@babel/core" "^7.23.9" + "@babel/parser" "^7.23.9" + "@istanbuljs/schema" "^0.1.3" istanbul-lib-coverage "^3.2.0" semver "^7.5.4" @@ -10746,6 +10933,11 @@ jsesc@^2.5.1: resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +jsesc@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" + integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== + jsesc@~0.5.0: version "0.5.0" resolved "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz" @@ -11665,6 +11857,11 @@ node-releases@^2.0.13: resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz" integrity sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ== +node-releases@^2.0.26: + version "2.0.27" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.27.tgz#eedca519205cf20f650f61d56b070db111231e4e" + integrity sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA== + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz" @@ -12248,6 +12445,11 @@ picocolors@^1.0.0: resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== +picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + picomatch@2.3.1, picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" @@ -13302,10 +13504,10 @@ semver@^7.7.2: resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58" integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== -send@0.19.0: - version "0.19.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" - integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw== +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== dependencies: debug "2.6.9" depd "2.0.0" @@ -14111,11 +14313,6 @@ ts-essentials@^10.0.2: resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-10.1.1.tgz#4e1d29b7c9b33c1a2744482376634c4fafba5210" integrity sha512-4aTB7KLHKmUvkjNj8V+EdnmuVTiECzn3K+zIbRthumvHu+j44x3w63xpfs0JL3NGIzGXqoQ7AV591xHO+XrOTw== -ts-essentials@^10.0.2: - version "10.1.1" - resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-10.1.1.tgz#4e1d29b7c9b33c1a2744482376634c4fafba5210" - integrity sha512-4aTB7KLHKmUvkjNj8V+EdnmuVTiECzn3K+zIbRthumvHu+j44x3w63xpfs0JL3NGIzGXqoQ7AV591xHO+XrOTw== - ts-jest@^29.1.0: version "29.1.1" resolved "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz" @@ -14465,6 +14662,14 @@ update-browserslist-db@^1.0.13: escalade "^3.1.1" picocolors "^1.0.0" +update-browserslist-db@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz#7802aa2ae91477f255b86e0e46dbc787a206ad4a" + integrity sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A== + dependencies: + escalade "^3.2.0" + picocolors "^1.1.1" + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz" From 9e62a9a66a3756787fe961150be9b7494d35861e Mon Sep 17 00:00:00 2001 From: Dalton Burkhart Date: Mon, 10 Nov 2025 23:29:24 -0500 Subject: [PATCH 03/12] Commit --- apps/backend/src/migrations/1759636753110-createDummyData.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/backend/src/migrations/1759636753110-createDummyData.ts b/apps/backend/src/migrations/1759636753110-createDummyData.ts index 20d5a12b..90fcab23 100644 --- a/apps/backend/src/migrations/1759636753110-createDummyData.ts +++ b/apps/backend/src/migrations/1759636753110-createDummyData.ts @@ -419,4 +419,4 @@ export class CreateDummyData1759636753110 implements MigrationInterface { await queryRunner.query(`DELETE FROM public.food_manufacturers`); await queryRunner.query(`DELETE FROM public.users`); } -} \ No newline at end of file +} From 0971ca158baea14279b0bc00eb8eaab66e57c23e Mon Sep 17 00:00:00 2001 From: Dalton Burkhart Date: Fri, 14 Nov 2025 20:12:55 -0500 Subject: [PATCH 04/12] added dummy data for testing --- .../src/config/typeormTestDataSource.ts | 16 ++++++ apps/backend/src/orders/order.service.spec.ts | 50 ++++++++++++------- 2 files changed, 47 insertions(+), 19 deletions(-) diff --git a/apps/backend/src/config/typeormTestDataSource.ts b/apps/backend/src/config/typeormTestDataSource.ts index 570d2dc0..d60dd3c3 100644 --- a/apps/backend/src/config/typeormTestDataSource.ts +++ b/apps/backend/src/config/typeormTestDataSource.ts @@ -3,6 +3,12 @@ import { DataSource, DataSourceOptions } from 'typeorm'; import { PluralNamingStrategy } from '../strategies/plural-naming.strategy'; import { Order } from '../orders/order.entity'; import { Pantry } from '../pantries/pantries.entity'; +import { User } from '../users/user.entity'; +import { Donation } from '../donations/donations.entity'; +import { FoodManufacturer } from '../foodManufacturers/manufacturer.entity'; +import { FoodRequest } from '../foodRequests/request.entity'; +import { DonationItem } from '../donationItems/donationItems.entity'; +import { Allocation } from '../allocations/allocations.entity'; import { User1725726359198 } from '../migrations/1725726359198-User'; import { AddTables1726524792261 } from '../migrations/1726524792261-addTables'; import { ReviseTables1737522923066 } from '../migrations/1737522923066-reviseTables'; @@ -30,6 +36,16 @@ const testConfig: DataSourceOptions = { password: `${process.env.DATABASE_PASSWORD}`, synchronize: false, namingStrategy: new PluralNamingStrategy(), + entities: [ + Order, + Pantry, + User, + Donation, + FoodManufacturer, + FoodRequest, + DonationItem, + Allocation, + ], migrations: [ User1725726359198, AddTables1726524792261, diff --git a/apps/backend/src/orders/order.service.spec.ts b/apps/backend/src/orders/order.service.spec.ts index d4fcfbfb..1159428b 100644 --- a/apps/backend/src/orders/order.service.spec.ts +++ b/apps/backend/src/orders/order.service.spec.ts @@ -1,17 +1,20 @@ import { Test, TestingModule } from '@nestjs/testing'; import { getRepositoryToken } from '@nestjs/typeorm'; -import { Order } from './order.entity'; import { OrdersService } from './order.service'; +import { Order } from './order.entity'; import { testDataSource } from '../config/typeormTestDataSource'; import { Repository } from 'typeorm'; +import { CreateDummyData1759636753110 } from '../migrations/1759636753110-createDummyData'; describe('OrdersService', () => { let service: OrdersService; let repository: Repository; beforeAll(async () => { + // Initialize DB and run all migrations once if (!testDataSource.isInitialized) { await testDataSource.initialize(); + await testDataSource.runMigrations(); } const module: TestingModule = await Test.createTestingModule({ @@ -29,21 +32,30 @@ describe('OrdersService', () => { }); beforeEach(async () => { - // reset tables - await testDataSource.synchronize(true); + // Truncate all tables in FK-safe order + const fkSafeOrder = [ + 'volunteer_assignments', + 'allocations', + 'orders', + 'food_requests', + 'donation_items', + 'donations', + 'pantries', + 'food_manufacturers', + 'users', + ]; - // optional: seed one sample record - await repository.save({ - orderId: 1, - requestId: 1, - pantry: { pantryId: 1, pantryName: 'Community Food Pantry Downtown' }, - shippedBy: 1, - status: 'delivered', - createdAt: new Date('2024-01-16T09:00:00Z'), - shippedAt: new Date('2024-01-17T08:00:00Z'), - deliveredAt: new Date('2024-01-18T14:30:00Z'), - donationId: 1, - }); + for (const table of fkSafeOrder) { + await testDataSource.query( + `TRUNCATE TABLE "${table}" RESTART IDENTITY CASCADE`, + ); + } + + // Reseed dummy data + const queryRunner = testDataSource.createQueryRunner(); + await queryRunner.connect(); + await new CreateDummyData1759636753110().up(queryRunner); + await queryRunner.release(); }); afterAll(async () => { @@ -56,13 +68,13 @@ describe('OrdersService', () => { describe('getAll', () => { it('should return orders filtered by status', async () => { - const result = await service.getAll({ status: 'delivered' }); - expect(result.length).toBeGreaterThanOrEqual(1); + const orders = await service.getAll({ status: 'delivered' }); + expect(orders.length).toBeGreaterThanOrEqual(1); }); it('should return empty array when no status filters match', async () => { - const result = await service.getAll({ status: 'invalid' }); - expect(result).toEqual([]); + const orders = await service.getAll({ status: 'invalid' }); + expect(orders).toEqual([]); }); }); }); From 92686b6c70decf345f8b98269fee4a5871bfc120 Mon Sep 17 00:00:00 2001 From: Dalton Burkhart Date: Thu, 20 Nov 2025 19:55:14 -0500 Subject: [PATCH 05/12] Resolved merge conflicts --- apps/frontend/src/main.tsx | 2 +- apps/frontend/src/theme.ts | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/apps/frontend/src/main.tsx b/apps/frontend/src/main.tsx index 10110223..7f571895 100644 --- a/apps/frontend/src/main.tsx +++ b/apps/frontend/src/main.tsx @@ -14,4 +14,4 @@ root.render( , -); \ No newline at end of file +); diff --git a/apps/frontend/src/theme.ts b/apps/frontend/src/theme.ts index c472e41f..c504bb84 100644 --- a/apps/frontend/src/theme.ts +++ b/apps/frontend/src/theme.ts @@ -1,4 +1,9 @@ -import { createSystem, defaultConfig, defineConfig, defineTextStyles } from '@chakra-ui/react'; +import { + createSystem, + defaultConfig, + defineConfig, + defineTextStyles, +} from '@chakra-ui/react'; const textStyles = defineTextStyles({ body: { @@ -10,7 +15,7 @@ const textStyles = defineTextStyles({ value: { fontFamily: 'instrument', fontSize: '32px', - fontWeight: '400' + fontWeight: '400', }, }, h2: { @@ -53,7 +58,7 @@ const customConfig = defineConfig({ colors: { white: { value: '#fff' }, black: { value: '#000' }, - blue: { + blue: { ssf: { value: '#2B5061' }, 100: { value: '#bee3f8' }, }, @@ -79,4 +84,4 @@ const customConfig = defineConfig({ }, }); -export const system = createSystem(defaultConfig, customConfig); \ No newline at end of file +export const system = createSystem(defaultConfig, customConfig); From 4d3d693e57d9c465670b3003330fce45ee66a03e Mon Sep 17 00:00:00 2001 From: Dalton Burkhart Date: Thu, 20 Nov 2025 20:55:39 -0500 Subject: [PATCH 06/12] Completed proper pipeline for dummy testing data --- .../src/config/typeormTestDataSource.ts | 21 ++++--- .../1759636753110-createDummyData.ts | 55 ++++++++++--------- apps/backend/src/orders/order.service.spec.ts | 8 +-- yarn.lock | 12 ++-- 4 files changed, 51 insertions(+), 45 deletions(-) diff --git a/apps/backend/src/config/typeormTestDataSource.ts b/apps/backend/src/config/typeormTestDataSource.ts index d60dd3c3..d206ae48 100644 --- a/apps/backend/src/config/typeormTestDataSource.ts +++ b/apps/backend/src/config/typeormTestDataSource.ts @@ -9,23 +9,25 @@ import { FoodManufacturer } from '../foodManufacturers/manufacturer.entity'; import { FoodRequest } from '../foodRequests/request.entity'; import { DonationItem } from '../donationItems/donationItems.entity'; import { Allocation } from '../allocations/allocations.entity'; + import { User1725726359198 } from '../migrations/1725726359198-User'; import { AddTables1726524792261 } from '../migrations/1726524792261-addTables'; import { ReviseTables1737522923066 } from '../migrations/1737522923066-reviseTables'; import { UpdateUserRole1737816745912 } from '../migrations/1737816745912-UpdateUserRole'; import { UpdatePantriesTable1737906317154 } from '../migrations/1737906317154-updatePantriesTable'; -import { UpdateDonations1738697216020 } from '../migrations/1738697216020-updateDonations'; -import { UpdateDonationColTypes1741708808976 } from '../migrations/1741708808976-UpdateDonationColTypes'; import { UpdatePantriesTable1738172265266 } from '../migrations/1738172265266-updatePantriesTable'; +import { UpdateDonations1738697216020 } from '../migrations/1738697216020-updateDonations'; import { UpdatePantriesTable1739056029076 } from '../migrations/1739056029076-updatePantriesTable'; -import { AssignmentsPantryIdNotUnique1758384669652 } from '../migrations/1758384669652-AssignmentsPantryIdNotUnique'; import { AddOrders1739496585940 } from '../migrations/1739496585940-addOrders'; import { UpdateOrdersTable1740367964915 } from '../migrations/1740367964915-updateOrdersTable'; -import { UpdateFoodRequests1744051370129 } from '../migrations/1744051370129-updateFoodRequests.ts'; import { UpdateRequestTable1741571847063 } from '../migrations/1741571847063-updateRequestTable'; -import { RemoveOrderIdFromRequests1744133526650 } from '../migrations/1744133526650-removeOrderIdFromRequests.ts'; +import { UpdateDonationColTypes1741708808976 } from '../migrations/1741708808976-UpdateDonationColTypes'; import { UpdatePantriesTable1742739750279 } from '../migrations/1742739750279-updatePantriesTable'; +import { UpdateFoodRequests1744051370129 } from '../migrations/1744051370129-updateFoodRequests'; +import { RemoveOrderIdFromRequests1744133526650 } from '../migrations/1744133526650-removeOrderIdFromRequests'; +import { AssignmentsPantryIdNotUnique1758384669652 } from '../migrations/1758384669652-AssignmentsPantryIdNotUnique'; import { CreateDummyData1759636753110 } from '../migrations/1759636753110-createDummyData'; +import { RemoveOrdersDonationId1761500262238 } from '../migrations/1761500262238-RemoveOrdersDonationId'; const testConfig: DataSourceOptions = { type: 'postgres', @@ -52,17 +54,18 @@ const testConfig: DataSourceOptions = { ReviseTables1737522923066, UpdateUserRole1737816745912, UpdatePantriesTable1737906317154, - UpdateDonations1738697216020, - UpdateDonationColTypes1741708808976, UpdatePantriesTable1738172265266, + UpdateDonations1738697216020, UpdatePantriesTable1739056029076, - AssignmentsPantryIdNotUnique1758384669652, AddOrders1739496585940, UpdateOrdersTable1740367964915, UpdateRequestTable1741571847063, + UpdateDonationColTypes1741708808976, + UpdatePantriesTable1742739750279, UpdateFoodRequests1744051370129, RemoveOrderIdFromRequests1744133526650, - UpdatePantriesTable1742739750279, + AssignmentsPantryIdNotUnique1758384669652, + RemoveOrdersDonationId1761500262238, CreateDummyData1759636753110, ], }; diff --git a/apps/backend/src/migrations/1759636753110-createDummyData.ts b/apps/backend/src/migrations/1759636753110-createDummyData.ts index 90fcab23..fa0b4c93 100644 --- a/apps/backend/src/migrations/1759636753110-createDummyData.ts +++ b/apps/backend/src/migrations/1759636753110-createDummyData.ts @@ -27,18 +27,18 @@ export class CreateDummyData1759636753110 implements MigrationInterface { await queryRunner.query(` INSERT INTO public.pantries ( - pantry_name, address, allergen_clients, refrigerated_donation, + pantry_name, allergen_clients, refrigerated_donation, reserve_food_for_allergic, reservation_explanation, dedicated_allergy_friendly, client_visit_frequency, identify_allergens_confidence, serve_allergic_children, newsletter_subscription, restrictions, ssf_representative_id, pantry_representative_id, - activities, questions, items_in_stock, need_more_options, status + activities, activities_comments, items_in_stock, need_more_options, status, + address_line_1, address_city, address_state, address_zip ) VALUES ( 'Community Food Pantry Downtown', - '123 Main St, Springfield, IL 62701', 'yes', 'yes', - true, + 'Yes', 'We have several clients with severe nut allergies and need to keep separate storage', 'Dedicated shelf for allergen-free items', 'weekly', @@ -48,18 +48,21 @@ export class CreateDummyData1759636753110 implements MigrationInterface { ARRAY['peanuts', 'tree_nuts', 'shellfish'], (SELECT user_id FROM public.users WHERE email = 'john.smith@ssf.org'), (SELECT user_id FROM public.users WHERE email = 'mike.brown@pantry1.org'), - 'Food distribution, nutrition education, cooking classes', + ARRAY['Food distribution', 'nutrition education', 'cooking classes'], 'How can we better serve clients with multiple allergies?', 'Canned goods, pasta, rice, cereal', 'More fresh produce and dairy alternatives', - 'active' + 'active', + '123 Main Street', + 'Boston', + 'MA', + '02115' ), ( 'Westside Community Kitchen', - '456 Oak Ave, Springfield, IL 62702', 'some', 'no', - false, + 'No', 'Limited space for separate storage', 'None currently', 'monthly', @@ -69,18 +72,21 @@ export class CreateDummyData1759636753110 implements MigrationInterface { ARRAY['gluten'], (SELECT user_id FROM public.users WHERE email = 'sarah.j@ssf.org'), (SELECT user_id FROM public.users WHERE email = 'emily.davis@pantry2.org'), - 'Weekly meal service, food boxes', + ARRAY['Weekly meal service', 'food boxes'], NULL, 'Bread, canned vegetables, soup', 'Gluten-free options', - 'active' + 'active', + '456 Oak Avenue', + 'Boston', + 'MA', + '02116' ), ( 'North End Food Bank', - '789 Pine Rd, Springfield, IL 62703', 'no', 'yes', - true, + 'Yes', 'Expanding allergen-friendly program', 'Separate refrigerator for allergen-free items', 'bi-weekly', @@ -90,11 +96,15 @@ export class CreateDummyData1759636753110 implements MigrationInterface { ARRAY['dairy', 'eggs'], (SELECT user_id FROM public.users WHERE email = 'john.smith@ssf.org'), (SELECT user_id FROM public.users WHERE email = 'robert.w@pantry3.org'), - 'Emergency food assistance, senior programs', + ARRAY['Emergency food assistance', 'senior programs'], 'Can we get more information about cross-contamination prevention?', 'Proteins, grains, canned fruits', 'Dairy-free and egg-free alternatives', - 'pending' + 'pending', + '789 Elm Street', + 'Boston', + 'MA', + '02113' ) `); @@ -283,7 +293,7 @@ export class CreateDummyData1759636753110 implements MigrationInterface { await queryRunner.query(` INSERT INTO public.orders ( request_id, pantry_id, shipped_by, status, created_at, - shipped_at, delivered_at, donation_id + shipped_at, delivered_at ) VALUES ( (SELECT request_id FROM public.food_requests WHERE additional_information LIKE '%150 families%'), @@ -292,8 +302,7 @@ export class CreateDummyData1759636753110 implements MigrationInterface { 'delivered', '2024-01-16 09:00:00', '2024-01-17 08:00:00', - '2024-01-18 14:30:00', - (SELECT donation_id FROM public.donations WHERE total_items = 150) + '2024-01-18 14:30:00' ), ( (SELECT request_id FROM public.food_requests WHERE additional_information LIKE '%75 clients%'), @@ -302,8 +311,7 @@ export class CreateDummyData1759636753110 implements MigrationInterface { 'delivered', '2024-01-21 10:00:00', '2024-01-22 09:00:00', - '2024-01-23 10:00:00', - (SELECT donation_id FROM public.donations WHERE total_items = 200) + '2024-01-23 10:00:00' ), ( (SELECT request_id FROM public.food_requests WHERE additional_information = 'Regular monthly order'), @@ -312,8 +320,7 @@ export class CreateDummyData1759636753110 implements MigrationInterface { 'shipped', '2024-02-02 11:00:00', '2024-02-03 08:00:00', - NULL, - (SELECT donation_id FROM public.donations WHERE total_items = 100) + NULL ), ( (SELECT request_id FROM public.food_requests WHERE additional_information LIKE '%breakfast items%'), @@ -322,8 +329,7 @@ export class CreateDummyData1759636753110 implements MigrationInterface { 'pending', '2024-02-03 12:00:00', NULL, - NULL, - (SELECT donation_id FROM public.donations WHERE total_items = 75) + NULL ), ( (SELECT request_id FROM public.food_requests WHERE additional_information LIKE '%breakfast items%'), @@ -332,8 +338,7 @@ export class CreateDummyData1759636753110 implements MigrationInterface { 'delivered', '2024-02-03 12:00:00', '2024-02-04 12:00:00', - '2024-02-05 12:00:00', - (SELECT donation_id FROM public.donations WHERE total_items = 75) + '2024-02-05 12:00:00' ) `); diff --git a/apps/backend/src/orders/order.service.spec.ts b/apps/backend/src/orders/order.service.spec.ts index 1159428b..fe03776e 100644 --- a/apps/backend/src/orders/order.service.spec.ts +++ b/apps/backend/src/orders/order.service.spec.ts @@ -3,20 +3,19 @@ import { getRepositoryToken } from '@nestjs/typeorm'; import { OrdersService } from './order.service'; import { Order } from './order.entity'; import { testDataSource } from '../config/typeormTestDataSource'; -import { Repository } from 'typeorm'; import { CreateDummyData1759636753110 } from '../migrations/1759636753110-createDummyData'; describe('OrdersService', () => { let service: OrdersService; - let repository: Repository; beforeAll(async () => { - // Initialize DB and run all migrations once + // Initialize DB and run all migrations once to create tables if (!testDataSource.isInitialized) { await testDataSource.initialize(); await testDataSource.runMigrations(); } + // Set up NestJS testing module const module: TestingModule = await Test.createTestingModule({ providers: [ OrdersService, @@ -28,11 +27,10 @@ describe('OrdersService', () => { }).compile(); service = module.get(OrdersService); - repository = testDataSource.getRepository(Order); }); beforeEach(async () => { - // Truncate all tables in FK-safe order + // Truncate all tables in FK-safe order (removes data, keeps tables) const fkSafeOrder = [ 'volunteer_assignments', 'allocations', diff --git a/yarn.lock b/yarn.lock index 587efb1e..54332615 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1097,7 +1097,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.27.1" -"@babel/plugin-syntax-logical-assignment-operators@^7.10.4", "@babel/plugin-syntax-logical-assignment-operators@^7.8.3": +"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== @@ -3211,7 +3211,7 @@ resolved "https://registry.yarnpkg.com/@pkgr/core/-/core-0.2.9.tgz#d229a7b7f9dac167a156992ef23c7f023653f53b" integrity sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA== -"@polka/url@^1.0.0-next.20": +"@polka/url@^1.0.0-next.24": version "1.0.0-next.29" resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.29.tgz#5a40109a1ab5f84d6fd8fc928b19f367cbe7e7b1" integrity sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww== @@ -12524,10 +12524,10 @@ semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.5.3, semver@^7.5.4, semve resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.3.tgz#4b5f4143d007633a8dc671cd0a6ef9147b8bb946" integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q== -send@0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" - integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== +send@0.19.0: + version "0.19.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" + integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw== dependencies: debug "2.6.9" depd "2.0.0" From ec2fb63f17ef14d1ed6bec2b423c3209643c278d Mon Sep 17 00:00:00 2001 From: Dalton Burkhart Date: Fri, 21 Nov 2025 11:08:37 -0500 Subject: [PATCH 07/12] Testing the action CI workflow --- .github/workflows/backend-tests.yml | 54 +++++++++++++++++ apps/backend/README.md | 10 +++- .../src/config/typeormTestDataSource.ts | 17 +++--- apps/backend/src/orders/order.service.spec.ts | 60 +++++++++++++++---- 4 files changed, 122 insertions(+), 19 deletions(-) create mode 100644 .github/workflows/backend-tests.yml diff --git a/.github/workflows/backend-tests.yml b/.github/workflows/backend-tests.yml new file mode 100644 index 00000000..d76a8a79 --- /dev/null +++ b/.github/workflows/backend-tests.yml @@ -0,0 +1,54 @@ +name: Backend Tests + +on: + push: + branches: + - '**' + pull_request: + branches: + - '**' + +jobs: + backend-tests: + runs-on: ubuntu-latest + services: + postgres: + image: postgres:15 + env: + POSTGRES_DB: securing-safe-food-test + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + ports: + - 5432:5432 + options: >- + --health-cmd "pg_isready -U postgres -d securing-safe-food-test" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + env: + DATABASE_HOST: 127.0.0.1 + DATABASE_PORT: 5432 + DATABASE_NAME: securing-safe-food-test + DATABASE_NAME_TEST: securing-safe-food-test + DATABASE_USERNAME: postgres + DATABASE_PASSWORD: postgres + NODE_ENV: test + CI: true + NX_DAEMON: 'false' + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Use Node.js + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'yarn' + + - name: Install dependencies + run: yarn install --frozen-lockfile + + - name: Run backend tests + run: npx nx test backend --runInBand + + diff --git a/apps/backend/README.md b/apps/backend/README.md index 8e4e513c..2a538b2a 100644 --- a/apps/backend/README.md +++ b/apps/backend/README.md @@ -25,4 +25,12 @@ You can check that your database connection details are correct by running `nx s "LOG 🚀 Application is running on: http://localhost:3000/api" ``` -Finally, run `yarn run typeorm:migrate` to load all the tables into your database. If everything is set up correctly, you should see "Migration ... has been executed successfully." in the terminal. \ No newline at end of file +Finally, run `yarn run typeorm:migrate` to load all the tables into your database. If everything is set up correctly, you should see "Migration ... has been executed successfully." in the terminal. + +### Running backend integration tests + +1. Create a **separate** Postgres database (for example `securing-safe-food-test`). +2. Add a `DATABASE_NAME_TEST` entry (and optionally `DATABASE_HOST/PORT/USERNAME/PASSWORD`) to your `.env` so the test data source can connect to that database. +3. Run the backend test suite with `npx nx test backend --runInBand`. + +Each spec truncates all data tables and runs the `CreateDummyData1759636753110` migration so every test receives the same dataset while keeping the schema created by the regular migrations. \ No newline at end of file diff --git a/apps/backend/src/config/typeormTestDataSource.ts b/apps/backend/src/config/typeormTestDataSource.ts index d206ae48..a7a2d93f 100644 --- a/apps/backend/src/config/typeormTestDataSource.ts +++ b/apps/backend/src/config/typeormTestDataSource.ts @@ -9,6 +9,7 @@ import { FoodManufacturer } from '../foodManufacturers/manufacturer.entity'; import { FoodRequest } from '../foodRequests/request.entity'; import { DonationItem } from '../donationItems/donationItems.entity'; import { Allocation } from '../allocations/allocations.entity'; +import { Assignments } from '../volunteerAssignments/volunteerAssignments.entity'; import { User1725726359198 } from '../migrations/1725726359198-User'; import { AddTables1726524792261 } from '../migrations/1726524792261-addTables'; @@ -26,16 +27,18 @@ import { UpdatePantriesTable1742739750279 } from '../migrations/1742739750279-up import { UpdateFoodRequests1744051370129 } from '../migrations/1744051370129-updateFoodRequests'; import { RemoveOrderIdFromRequests1744133526650 } from '../migrations/1744133526650-removeOrderIdFromRequests'; import { AssignmentsPantryIdNotUnique1758384669652 } from '../migrations/1758384669652-AssignmentsPantryIdNotUnique'; -import { CreateDummyData1759636753110 } from '../migrations/1759636753110-createDummyData'; import { RemoveOrdersDonationId1761500262238 } from '../migrations/1761500262238-RemoveOrdersDonationId'; const testConfig: DataSourceOptions = { type: 'postgres', - host: `${process.env.DATABASE_HOST}`, - port: parseInt(`${process.env.DATABASE_PORT}`, 10), - database: `${process.env.DATABASE_NAME_TEST}`, - username: `${process.env.DATABASE_USERNAME}`, - password: `${process.env.DATABASE_PASSWORD}`, + host: process.env.DATABASE_HOST ?? '127.0.0.1', + port: parseInt(process.env.DATABASE_PORT ?? '5432', 10), + database: + process.env.DATABASE_NAME_TEST ?? + process.env.DATABASE_NAME ?? + 'securing-safe-food-test', + username: process.env.DATABASE_USERNAME ?? 'postgres', + password: process.env.DATABASE_PASSWORD ?? 'postgres', synchronize: false, namingStrategy: new PluralNamingStrategy(), entities: [ @@ -47,6 +50,7 @@ const testConfig: DataSourceOptions = { FoodRequest, DonationItem, Allocation, + Assignments, ], migrations: [ User1725726359198, @@ -66,7 +70,6 @@ const testConfig: DataSourceOptions = { RemoveOrderIdFromRequests1744133526650, AssignmentsPantryIdNotUnique1758384669652, RemoveOrdersDonationId1761500262238, - CreateDummyData1759636753110, ], }; diff --git a/apps/backend/src/orders/order.service.spec.ts b/apps/backend/src/orders/order.service.spec.ts index fe03776e..84914a73 100644 --- a/apps/backend/src/orders/order.service.spec.ts +++ b/apps/backend/src/orders/order.service.spec.ts @@ -5,17 +5,17 @@ import { Order } from './order.entity'; import { testDataSource } from '../config/typeormTestDataSource'; import { CreateDummyData1759636753110 } from '../migrations/1759636753110-createDummyData'; -describe('OrdersService', () => { +//jest.setTimeout(30000); + +describe('OrdersService (integration)', () => { let service: OrdersService; beforeAll(async () => { - // Initialize DB and run all migrations once to create tables if (!testDataSource.isInitialized) { await testDataSource.initialize(); await testDataSource.runMigrations(); } - // Set up NestJS testing module const module: TestingModule = await Test.createTestingModule({ providers: [ OrdersService, @@ -30,7 +30,6 @@ describe('OrdersService', () => { }); beforeEach(async () => { - // Truncate all tables in FK-safe order (removes data, keeps tables) const fkSafeOrder = [ 'volunteer_assignments', 'allocations', @@ -49,15 +48,19 @@ describe('OrdersService', () => { ); } - // Reseed dummy data const queryRunner = testDataSource.createQueryRunner(); await queryRunner.connect(); - await new CreateDummyData1759636753110().up(queryRunner); - await queryRunner.release(); + try { + await new CreateDummyData1759636753110().up(queryRunner); + } finally { + await queryRunner.release(); + } }); afterAll(async () => { - await testDataSource.destroy(); + if (testDataSource.isInitialized) { + await testDataSource.destroy(); + } }); it('should be defined', () => { @@ -65,14 +68,49 @@ describe('OrdersService', () => { }); describe('getAll', () => { - it('should return orders filtered by status', async () => { + it('returns orders filtered by status', async () => { const orders = await service.getAll({ status: 'delivered' }); - expect(orders.length).toBeGreaterThanOrEqual(1); + + expect(orders).toHaveLength(3); + expect(orders.every((order) => order.status === 'delivered')).toBe(true); }); - it('should return empty array when no status filters match', async () => { + it('returns empty array when status filter matches nothing', async () => { const orders = await service.getAll({ status: 'invalid' }); + expect(orders).toEqual([]); }); + + it('returns orders filtered by pantry names', async () => { + const orders = await service.getAll({ + pantryNames: ['Community Food Pantry Downtown'], + }); + + expect(orders).toHaveLength(3); + expect( + orders.every( + (order) => order.pantry.pantryName === 'Community Food Pantry Downtown', + ), + ).toBe(true); + }); + + it('returns empty array when pantry filter matches nothing', async () => { + const orders = await service.getAll({ + pantryNames: ['Nonexistent Pantry'], + }); + + expect(orders).toEqual([]); + }); + + it('returns orders filtered by both pantry and status', async () => { + const orders = await service.getAll({ + status: 'delivered', + pantryNames: ['Westside Community Kitchen'], + }); + + expect(orders).toHaveLength(1); + expect(orders[0].pantry.pantryName).toBe('Westside Community Kitchen'); + expect(orders[0].status).toBe('delivered'); + }); }); }); From c5c7b9b50b2653f7e92216026b32240408628947 Mon Sep 17 00:00:00 2001 From: Dalton Burkhart Date: Fri, 21 Nov 2025 11:17:47 -0500 Subject: [PATCH 08/12] Simplified workflow --- .github/workflows/backend-tests.yml | 34 +++---------------- apps/backend/src/orders/order.service.spec.ts | 3 +- 2 files changed, 7 insertions(+), 30 deletions(-) diff --git a/.github/workflows/backend-tests.yml b/.github/workflows/backend-tests.yml index d76a8a79..314b531c 100644 --- a/.github/workflows/backend-tests.yml +++ b/.github/workflows/backend-tests.yml @@ -1,12 +1,4 @@ -name: Backend Tests - -on: - push: - branches: - - '**' - pull_request: - branches: - - '**' +on: [push, pull_request] jobs: backend-tests: @@ -20,35 +12,19 @@ jobs: POSTGRES_PASSWORD: postgres ports: - 5432:5432 - options: >- - --health-cmd "pg_isready -U postgres -d securing-safe-food-test" - --health-interval 10s - --health-timeout 5s - --health-retries 5 env: DATABASE_HOST: 127.0.0.1 DATABASE_PORT: 5432 - DATABASE_NAME: securing-safe-food-test DATABASE_NAME_TEST: securing-safe-food-test DATABASE_USERNAME: postgres DATABASE_PASSWORD: postgres - NODE_ENV: test - CI: true NX_DAEMON: 'false' steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Use Node.js - uses: actions/setup-node@v4 + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 with: node-version: 20 - cache: 'yarn' - - - name: Install dependencies - run: yarn install --frozen-lockfile - - - name: Run backend tests - run: npx nx test backend --runInBand + - run: yarn install + - run: npx jest diff --git a/apps/backend/src/orders/order.service.spec.ts b/apps/backend/src/orders/order.service.spec.ts index 84914a73..91e01e7a 100644 --- a/apps/backend/src/orders/order.service.spec.ts +++ b/apps/backend/src/orders/order.service.spec.ts @@ -89,7 +89,8 @@ describe('OrdersService (integration)', () => { expect(orders).toHaveLength(3); expect( orders.every( - (order) => order.pantry.pantryName === 'Community Food Pantry Downtown', + (order) => + order.pantry.pantryName === 'Community Food Pantry Downtown', ), ).toBe(true); }); From 294e85e2af04bcd8fd2a267768137bb12fe039fa Mon Sep 17 00:00:00 2001 From: Dalton Burkhart Date: Fri, 21 Nov 2025 11:28:23 -0500 Subject: [PATCH 09/12] Testing workflow with securing-safe-food-test deleted --- apps/backend/src/config/typeormTestDataSource.ts | 5 +---- apps/backend/src/orders/order.service.spec.ts | 6 ++++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/apps/backend/src/config/typeormTestDataSource.ts b/apps/backend/src/config/typeormTestDataSource.ts index a7a2d93f..bb91b0fa 100644 --- a/apps/backend/src/config/typeormTestDataSource.ts +++ b/apps/backend/src/config/typeormTestDataSource.ts @@ -33,10 +33,7 @@ const testConfig: DataSourceOptions = { type: 'postgres', host: process.env.DATABASE_HOST ?? '127.0.0.1', port: parseInt(process.env.DATABASE_PORT ?? '5432', 10), - database: - process.env.DATABASE_NAME_TEST ?? - process.env.DATABASE_NAME ?? - 'securing-safe-food-test', + database: process.env.DATABASE_NAME_TEST ?? 'securing-safe-food-test', username: process.env.DATABASE_USERNAME ?? 'postgres', password: process.env.DATABASE_PASSWORD ?? 'postgres', synchronize: false, diff --git a/apps/backend/src/orders/order.service.spec.ts b/apps/backend/src/orders/order.service.spec.ts index 91e01e7a..3977d46a 100644 --- a/apps/backend/src/orders/order.service.spec.ts +++ b/apps/backend/src/orders/order.service.spec.ts @@ -5,12 +5,11 @@ import { Order } from './order.entity'; import { testDataSource } from '../config/typeormTestDataSource'; import { CreateDummyData1759636753110 } from '../migrations/1759636753110-createDummyData'; -//jest.setTimeout(30000); - describe('OrdersService (integration)', () => { let service: OrdersService; beforeAll(async () => { + // Create all tables and run migrations if (!testDataSource.isInitialized) { await testDataSource.initialize(); await testDataSource.runMigrations(); @@ -42,12 +41,14 @@ describe('OrdersService (integration)', () => { 'users', ]; + // Delete all data, keep schema for (const table of fkSafeOrder) { await testDataSource.query( `TRUNCATE TABLE "${table}" RESTART IDENTITY CASCADE`, ); } + // Seed dummy data const queryRunner = testDataSource.createQueryRunner(); await queryRunner.connect(); try { @@ -58,6 +59,7 @@ describe('OrdersService (integration)', () => { }); afterAll(async () => { + // Destroy all schemas if (testDataSource.isInitialized) { await testDataSource.destroy(); } From a4745073d2af4b270501759aaa33fb125d7b4a5f Mon Sep 17 00:00:00 2001 From: Dalton Burkhart Date: Fri, 21 Nov 2025 12:04:38 -0500 Subject: [PATCH 10/12] Updated README --- apps/backend/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/backend/README.md b/apps/backend/README.md index 2a538b2a..50a9a7a5 100644 --- a/apps/backend/README.md +++ b/apps/backend/README.md @@ -31,6 +31,6 @@ Finally, run `yarn run typeorm:migrate` to load all the tables into your databas 1. Create a **separate** Postgres database (for example `securing-safe-food-test`). 2. Add a `DATABASE_NAME_TEST` entry (and optionally `DATABASE_HOST/PORT/USERNAME/PASSWORD`) to your `.env` so the test data source can connect to that database. -3. Run the backend test suite with `npx nx test backend --runInBand`. +3. Run the backend test suite with `npx jest`. Each spec truncates all data tables and runs the `CreateDummyData1759636753110` migration so every test receives the same dataset while keeping the schema created by the regular migrations. \ No newline at end of file From 3cc1010b4b6db4c7b3cb656c75fc0900e4ac8099 Mon Sep 17 00:00:00 2001 From: Dalton Burkhart Date: Fri, 21 Nov 2025 12:13:19 -0500 Subject: [PATCH 11/12] Restored theme.ts --- apps/frontend/src/theme.ts | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/apps/frontend/src/theme.ts b/apps/frontend/src/theme.ts index c504bb84..c472e41f 100644 --- a/apps/frontend/src/theme.ts +++ b/apps/frontend/src/theme.ts @@ -1,9 +1,4 @@ -import { - createSystem, - defaultConfig, - defineConfig, - defineTextStyles, -} from '@chakra-ui/react'; +import { createSystem, defaultConfig, defineConfig, defineTextStyles } from '@chakra-ui/react'; const textStyles = defineTextStyles({ body: { @@ -15,7 +10,7 @@ const textStyles = defineTextStyles({ value: { fontFamily: 'instrument', fontSize: '32px', - fontWeight: '400', + fontWeight: '400' }, }, h2: { @@ -58,7 +53,7 @@ const customConfig = defineConfig({ colors: { white: { value: '#fff' }, black: { value: '#000' }, - blue: { + blue: { ssf: { value: '#2B5061' }, 100: { value: '#bee3f8' }, }, @@ -84,4 +79,4 @@ const customConfig = defineConfig({ }, }); -export const system = createSystem(defaultConfig, customConfig); +export const system = createSystem(defaultConfig, customConfig); \ No newline at end of file From dc6aa8c3885efa1e364ff938f553df4247307c63 Mon Sep 17 00:00:00 2001 From: Dalton Burkhart Date: Fri, 21 Nov 2025 12:51:33 -0500 Subject: [PATCH 12/12] Final commit --- .github/workflows/ci-cd.yml | 113 ------------------------------------ apps/frontend/src/theme.ts | 13 +++-- 2 files changed, 9 insertions(+), 117 deletions(-) delete mode 100644 .github/workflows/ci-cd.yml diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml deleted file mode 100644 index bf0fcbef..00000000 --- a/.github/workflows/ci-cd.yml +++ /dev/null @@ -1,113 +0,0 @@ -name: CI/CD - -# First runs linter and tests all affected projects -# Then, for each project that requires deployment, deploy-- is added -# Environment variables are labelled _SHORT_DESCRIPTION - -on: - push: - branches: ['main'] - pull_request: - branches: ['main'] - workflow_dispatch: - inputs: - manual-deploy: - description: 'App to Deploy' - required: false - default: '' - -concurrency: - # Never have two deployments happening at the same time (potential race condition) - group: '{{ github.head_ref || github.ref }}' - -jobs: - pre-deploy: - runs-on: ubuntu-latest - outputs: - affected: ${{ steps.should-deploy.outputs.affected }} - steps: - - uses: actions/checkout@v3 - with: - # We need to fetch all branches and commits so that Nx affected has a base to compare against. - fetch-depth: 0 - - name: Use Node.js 20 - uses: actions/setup-node@v3 - with: - node-version: 20.x - cache: 'yarn' - - - name: Install Dependencies - run: yarn install - - # In any subsequent steps within this job (myjob) we can reference the resolved SHAs - # using either the step outputs or environment variables: - - name: Derive appropriate SHAs for base and head for `nx affected` commands - uses: nrwl/nx-set-shas@v3 - - - run: | - echo "BASE: ${{ env.NX_BASE }}" - echo "HEAD: ${{ env.NX_HEAD }}" - - - name: Nx Affected Lint - run: npx nx affected -t lint - - # - name: Nx Affected Test - # run: npx nx affected -t test - - - name: Nx Affected Build - run: npx nx affected -t build - - - name: Determine who needs to be deployed - id: should-deploy - run: | - echo "The following projects have been affected: [$(npx nx print-affected -t build --select=tasks.target.project)]"; - echo "affected=$(npx nx print-affected -t build --select=tasks.target.project)" >> "$GITHUB_OUTPUT" - - deploy-debug: - needs: pre-deploy - runs-on: ubuntu-latest - steps: - - name: Debug logs - run: | - echo "Manual Deploy: ${{github.event.inputs.manual-deploy}}"; - echo "Affected Names: ${{needs.pre-deploy.outputs.affected}}"; - echo "Event: ${{github.event_name}}"; - echo "Ref: ${{github.ref}}"; - echo "Will deploy?: ${{(github.event_name == 'push' || github.event_name == 'workflow_dispatch') && github.ref == 'refs/heads/main'}}"; - - deploy-frontend: - needs: pre-deploy - if: (contains(github.event.inputs.manual-deploy, 'c4c-ops-frontend') || contains(needs.pre-deploy.outputs.affected, 'scaffolding-frontend')) && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && github.ref == 'refs/heads/main' - runs-on: ubuntu-latest - # For "simplicity", deployment settings are configured in the AWS Amplify Console - # This just posts to a webhook telling Amplify to redeploy the main branch - steps: - - name: Tell Amplify to rebuild - run: curl -X POST -d {} ${C4C_OPS_WEBHOOK_DEPLOY} -H "Content-Type:application/json" - env: - C4C_OPS_WEBHOOK_DEPLOY: ${{ secrets.C4C_OPS_WEBHOOK_DEPLOY }} - - deploy-backend: - needs: pre-deploy - if: (contains(github.event.inputs.manual-deploy, 'c4c-ops-backend') || contains(needs.pre-deploy.outputs.affected, 'scaffolding-backend')) && (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && github.ref == 'refs/heads/main' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Use Node.js 16 - uses: actions/setup-node@v3 - with: - node-version: 16.x - cache: 'yarn' - - - name: Install Dependencies - run: yarn install - - - run: npx nx build c4c-ops-backend --configuration production - - name: default deploy - uses: appleboy/lambda-action@master - with: - aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }} - aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - aws_region: ${{ secrets.AWS_REGION }} - function_name: c4c-ops-monolith-lambda - source: dist/apps/c4c-ops/c4c-ops-backend/main.js diff --git a/apps/frontend/src/theme.ts b/apps/frontend/src/theme.ts index c472e41f..c504bb84 100644 --- a/apps/frontend/src/theme.ts +++ b/apps/frontend/src/theme.ts @@ -1,4 +1,9 @@ -import { createSystem, defaultConfig, defineConfig, defineTextStyles } from '@chakra-ui/react'; +import { + createSystem, + defaultConfig, + defineConfig, + defineTextStyles, +} from '@chakra-ui/react'; const textStyles = defineTextStyles({ body: { @@ -10,7 +15,7 @@ const textStyles = defineTextStyles({ value: { fontFamily: 'instrument', fontSize: '32px', - fontWeight: '400' + fontWeight: '400', }, }, h2: { @@ -53,7 +58,7 @@ const customConfig = defineConfig({ colors: { white: { value: '#fff' }, black: { value: '#000' }, - blue: { + blue: { ssf: { value: '#2B5061' }, 100: { value: '#bee3f8' }, }, @@ -79,4 +84,4 @@ const customConfig = defineConfig({ }, }); -export const system = createSystem(defaultConfig, customConfig); \ No newline at end of file +export const system = createSystem(defaultConfig, customConfig);