All checks were successful
Deploy to Test Environment / deploy-to-test (push) Successful in 18m47s
1667 lines
53 KiB
TypeScript
1667 lines
53 KiB
TypeScript
// src/tests/utils/mockFactories.ts
|
|
import {
|
|
UserProfile,
|
|
User,
|
|
Flyer,
|
|
Store,
|
|
SuggestedCorrection,
|
|
Brand,
|
|
Category,
|
|
FlyerItem,
|
|
MasterGroceryItem,
|
|
ShoppingList,
|
|
ShoppingListItem,
|
|
Achievement,
|
|
UserAchievement,
|
|
Budget,
|
|
SpendingByCategory,
|
|
Recipe,
|
|
RecipeIngredient,
|
|
RecipeComment,
|
|
ActivityLogItem,
|
|
DietaryRestriction,
|
|
UserDietaryRestriction,
|
|
Appliance,
|
|
UserAppliance,
|
|
Notification,
|
|
UnmatchedFlyerItem,
|
|
AdminUserView,
|
|
WatchedItemDeal,
|
|
LeaderboardUser,
|
|
UserWithPasswordHash,
|
|
Profile,
|
|
Address,
|
|
StoreLocation,
|
|
StoreLocationWithAddress,
|
|
StoreWithLocations,
|
|
MenuPlan,
|
|
PlannedMeal,
|
|
PantryItem,
|
|
Product,
|
|
ShoppingTrip,
|
|
ShoppingTripItem,
|
|
Receipt,
|
|
ReceiptItem,
|
|
SearchQuery,
|
|
ProcessingStage,
|
|
UserAlert,
|
|
UserSubmittedPrice,
|
|
RecipeRating,
|
|
Tag,
|
|
PantryLocation,
|
|
DealItem,
|
|
ItemPriceHistory,
|
|
HistoricalPriceDataPoint,
|
|
ReceiptDeal,
|
|
RecipeCollection,
|
|
SharedShoppingList,
|
|
MostFrequentSaleItem,
|
|
PantryRecipe,
|
|
RecommendedRecipe,
|
|
UnitPrice,
|
|
Source,
|
|
} from '../../types';
|
|
import type { AppStats } from '../../services/apiClient';
|
|
|
|
// --- ID Generator for Deterministic Mocking ---
|
|
let idCounter = 0;
|
|
|
|
/**
|
|
* Generates a sequential number for deterministic IDs in tests.
|
|
*/
|
|
const getNextId = () => ++idCounter;
|
|
|
|
/**
|
|
* Resets the ID counter. Call this in `beforeEach` in your test setup
|
|
* to ensure tests are isolated.
|
|
*
|
|
* @example
|
|
* beforeEach(() => {
|
|
* resetMockIds();
|
|
* });
|
|
*/
|
|
export const resetMockIds = () => {
|
|
idCounter = 0;
|
|
};
|
|
// --- End ID Generator ---
|
|
|
|
/**
|
|
* Creates a mock User object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe User object.
|
|
*/
|
|
export const createMockUser = (overrides: Partial<User> = {}): User => {
|
|
// Generate a deterministic, valid UUID-like string for mock user IDs.
|
|
// This prevents database errors in integration tests where a UUID is expected.
|
|
const userId =
|
|
overrides.user_id ?? `00000000-0000-0000-0000-${String(getNextId()).padStart(12, '0')}`;
|
|
|
|
const defaultUser: User = {
|
|
user_id: userId,
|
|
email: `${userId}@example.com`,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
return { ...defaultUser, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock UserProfile object for use in tests, ensuring type safety.
|
|
*
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* This allows for easy customization of the mock user for specific test cases.
|
|
* For example: `createMockUserProfile({ role: 'admin', points: 500 })`
|
|
* @returns A complete and type-safe UserProfile object.
|
|
*/
|
|
export const createMockUserProfile = (
|
|
overrides: Partial<Omit<UserProfile, 'user'>> & { user?: Partial<User> } = {},
|
|
): UserProfile => {
|
|
// The user object is the source of truth for user_id and email.
|
|
const user = createMockUser(overrides.user);
|
|
|
|
const defaultProfile: UserProfile = {
|
|
role: 'user',
|
|
points: 0,
|
|
full_name: 'Test User',
|
|
avatar_url: null,
|
|
preferences: {},
|
|
address_id: null,
|
|
created_by: null,
|
|
address: null,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
user,
|
|
};
|
|
|
|
// Exclude 'user' from overrides to prevent overwriting the complete user object with a partial one
|
|
const { user: _, ...profileOverrides } = overrides;
|
|
|
|
// Combine defaults, overrides, and the fully constructed user object.
|
|
return { ...defaultProfile, ...profileOverrides, user };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock Store object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe Store object.
|
|
*/
|
|
export const createMockStore = (overrides: Partial<Store> = {}): Store => {
|
|
const storeId = overrides.store_id ?? getNextId();
|
|
|
|
const defaultStore: Store = {
|
|
store_id: storeId,
|
|
name: 'Mock Store',
|
|
logo_url: null,
|
|
created_by: null,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
return { ...defaultStore, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock Flyer object for use in tests, ensuring type safety.
|
|
*
|
|
* @param overrides - An object containing properties to override the default mock values,
|
|
* including nested properties for the `store`.
|
|
* e.g., `createMockFlyer({ item_count: 50, store: { name: 'Walmart' } })`
|
|
* @returns A complete and type-safe Flyer object.
|
|
*/
|
|
export const createMockFlyer = (
|
|
overrides: Omit<Partial<Flyer>, 'store'> & { store?: Partial<Store> } = {},
|
|
): Flyer => {
|
|
const flyerId = overrides.flyer_id ?? getNextId();
|
|
|
|
// Ensure the store_id is consistent between the flyer and the nested store object
|
|
const store = createMockStore({
|
|
...overrides.store,
|
|
// Prioritize the top-level store_id if provided
|
|
store_id: overrides.store_id ?? overrides.store?.store_id,
|
|
});
|
|
|
|
const baseUrl = 'https://example.com'; // A reasonable default for tests
|
|
|
|
// Determine the final file_name to generate dependent properties from.
|
|
const fileName = overrides.file_name ?? `flyer-${flyerId}.jpg`;
|
|
|
|
// A simple hash function for mock checksum generation.
|
|
const generateMockChecksum = (str: string) => {
|
|
let hash = 0;
|
|
for (let i = 0; i < str.length; i++) {
|
|
const char = str.charCodeAt(i);
|
|
hash = (hash << 5) - hash + char;
|
|
hash |= 0; // Convert to 32bit integer
|
|
}
|
|
return `mock-checksum-${Math.abs(hash).toString(16)}`;
|
|
};
|
|
|
|
const defaultFlyer: Flyer = {
|
|
flyer_id: flyerId,
|
|
file_name: fileName,
|
|
image_url: `${baseUrl}/flyer-images/${fileName}`,
|
|
icon_url: `${baseUrl}/flyer-images/icons/icon-${fileName.replace(/\.[^/.]+$/, '.webp')}`,
|
|
checksum: generateMockChecksum(fileName),
|
|
store_id: store.store_id,
|
|
valid_from: new Date().toISOString().split('T')[0],
|
|
valid_to: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0], // 7 days from now
|
|
store_address: '123 Main St, Anytown, USA',
|
|
status: 'processed',
|
|
item_count: 50,
|
|
uploaded_by: null,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
store,
|
|
};
|
|
|
|
const { store: _, ...flyerOverrides } = overrides;
|
|
|
|
// Apply overrides. If checksum, file_name, etc., are in overrides, they will correctly replace the generated defaults.
|
|
return { ...defaultFlyer, ...flyerOverrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock SuggestedCorrection object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe SuggestedCorrection object.
|
|
*/
|
|
export const createMockSuggestedCorrection = (
|
|
overrides: Partial<SuggestedCorrection> = {},
|
|
): SuggestedCorrection => {
|
|
const defaultCorrection: SuggestedCorrection = {
|
|
suggested_correction_id: getNextId(),
|
|
flyer_item_id: getNextId(),
|
|
user_id: `user-${getNextId()}`,
|
|
correction_type: 'price',
|
|
suggested_value: '$9.99',
|
|
status: 'pending',
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
return { ...defaultCorrection, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock Brand object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe Brand object.
|
|
*/
|
|
export const createMockBrand = (overrides: Partial<Brand> = {}): Brand => {
|
|
const brandId = overrides.brand_id ?? getNextId();
|
|
|
|
const defaultBrand: Brand = {
|
|
brand_id: brandId,
|
|
name: `Brand ${brandId}`,
|
|
logo_url: null,
|
|
store_id: null,
|
|
store_name: null,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
return { ...defaultBrand, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock Category object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe Category object.
|
|
*/
|
|
export const createMockCategory = (overrides: Partial<Category> = {}): Category => {
|
|
const categoryId = overrides.category_id ?? getNextId();
|
|
|
|
const defaultCategory: Category = {
|
|
category_id: categoryId,
|
|
name: `Category ${categoryId}`,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
return { ...defaultCategory, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock Product object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* Can optionally include `master_item` and `brand` to link IDs.
|
|
* @returns A complete and type-safe Product object.
|
|
*/
|
|
export const createMockProduct = (
|
|
overrides: Partial<Product> & {
|
|
master_item?: Partial<MasterGroceryItem>;
|
|
brand?: Partial<Brand>;
|
|
} = {},
|
|
): Product => {
|
|
const productId = overrides.product_id ?? getNextId();
|
|
const masterItemId =
|
|
overrides.master_item_id ?? overrides.master_item?.master_grocery_item_id ?? getNextId();
|
|
const brandId = overrides.brand_id ?? overrides.brand?.brand_id; // brand is optional
|
|
|
|
const defaultProduct: Product = {
|
|
product_id: productId,
|
|
master_item_id: masterItemId,
|
|
brand_id: brandId,
|
|
name: `Mock Product ${productId}`,
|
|
description: 'A mock product description.',
|
|
size: '100g',
|
|
upc_code: `0000${productId}`.slice(-12),
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
const { master_item: _, brand: __, ...itemOverrides } = overrides;
|
|
|
|
return { ...defaultProduct, ...itemOverrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock FlyerItem object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe FlyerItem object.
|
|
*/
|
|
export const createMockFlyerItem = (
|
|
overrides: Partial<FlyerItem> & { flyer?: Partial<Flyer> } = {},
|
|
): FlyerItem => {
|
|
const flyerItemId = overrides.flyer_item_id ?? getNextId();
|
|
const flyerId = overrides.flyer_id ?? overrides.flyer?.flyer_id ?? getNextId();
|
|
|
|
const defaultItem: FlyerItem = {
|
|
flyer_item_id: flyerItemId,
|
|
flyer_id: flyerId,
|
|
item: 'Mock Item',
|
|
price_display: '$1.99',
|
|
price_in_cents: 199,
|
|
unit_price: null,
|
|
quantity: 'each',
|
|
view_count: 0,
|
|
click_count: 0,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
const { flyer: _, ...itemOverrides } = overrides;
|
|
|
|
return { ...defaultItem, ...itemOverrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock Recipe object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe Recipe object.
|
|
*/
|
|
export const createMockRecipe = (
|
|
overrides: Omit<Partial<Recipe>, 'comments' | 'ingredients'> & {
|
|
comments?: Partial<RecipeComment>[];
|
|
ingredients?: Partial<RecipeIngredient>[];
|
|
} = {},
|
|
): Recipe => {
|
|
const recipeId = overrides.recipe_id ?? getNextId();
|
|
|
|
const defaultRecipe: Recipe = {
|
|
recipe_id: recipeId,
|
|
user_id: `user-${getNextId()}`,
|
|
name: `Mock Recipe ${recipeId}`,
|
|
description: 'A delicious mock recipe.',
|
|
instructions: '1. Mock the ingredients. 2. Mock the cooking. 3. Enjoy!',
|
|
avg_rating: 4.5,
|
|
rating_count: 50,
|
|
fork_count: 10,
|
|
status: 'public',
|
|
prep_time_minutes: 15,
|
|
cook_time_minutes: 30,
|
|
servings: 4,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
const {
|
|
comments: commentsOverrides,
|
|
ingredients: ingredientsOverrides,
|
|
...recipeOverrides
|
|
} = overrides;
|
|
const recipe = { ...defaultRecipe, ...recipeOverrides };
|
|
|
|
if (commentsOverrides) {
|
|
recipe.comments = commentsOverrides.map((comment) =>
|
|
createMockRecipeComment({
|
|
recipe_id: recipeId,
|
|
...comment,
|
|
}),
|
|
);
|
|
}
|
|
|
|
if (ingredientsOverrides) {
|
|
recipe.ingredients = ingredientsOverrides.map((ingredient) =>
|
|
createMockRecipeIngredient({
|
|
recipe_id: recipeId,
|
|
...ingredient,
|
|
}),
|
|
);
|
|
}
|
|
|
|
return recipe;
|
|
};
|
|
|
|
/**
|
|
* Creates a mock RecipeIngredient object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* Can optionally include a `master_item` to link IDs.
|
|
* @returns A complete and type-safe RecipeIngredient object.
|
|
*/
|
|
export const createMockRecipeIngredient = (
|
|
overrides: Partial<RecipeIngredient> & { master_item?: Partial<MasterGroceryItem> } = {},
|
|
): RecipeIngredient => {
|
|
const recipeIngredientId = overrides.recipe_ingredient_id ?? getNextId();
|
|
const masterItemId =
|
|
overrides.master_item_id ?? overrides.master_item?.master_grocery_item_id ?? getNextId();
|
|
|
|
const defaultIngredient: RecipeIngredient = {
|
|
recipe_ingredient_id: recipeIngredientId,
|
|
recipe_id: getNextId(),
|
|
master_item_id: masterItemId,
|
|
quantity: 1,
|
|
unit: 'cup',
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
const { master_item: _, ...itemOverrides } = overrides;
|
|
|
|
return { ...defaultIngredient, ...itemOverrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock RecipeComment object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe RecipeComment object.
|
|
*/
|
|
export const createMockRecipeComment = (overrides: Partial<RecipeComment> = {}): RecipeComment => {
|
|
const defaultComment: RecipeComment = {
|
|
recipe_comment_id: getNextId(),
|
|
recipe_id: getNextId(),
|
|
user_id: `user-${getNextId()}`,
|
|
content: 'This is a mock comment.',
|
|
status: 'visible',
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
user_full_name: 'Mock User', // This was correct
|
|
user_avatar_url: undefined,
|
|
};
|
|
|
|
return { ...defaultComment, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock PlannedMeal object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe PlannedMeal object.
|
|
*/
|
|
export const createMockPlannedMeal = (overrides: Partial<PlannedMeal> = {}): PlannedMeal => {
|
|
const defaultMeal: PlannedMeal = {
|
|
planned_meal_id: getNextId(),
|
|
menu_plan_id: getNextId(),
|
|
recipe_id: getNextId(),
|
|
plan_date: new Date().toISOString().split('T')[0],
|
|
meal_type: 'dinner',
|
|
servings_to_cook: 4,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
return { ...defaultMeal, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock MenuPlan object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe MenuPlan object.
|
|
*/
|
|
export const createMockMenuPlan = (
|
|
overrides: Omit<Partial<MenuPlan>, 'planned_meals'> & {
|
|
planned_meals?: Partial<PlannedMeal>[];
|
|
} = {},
|
|
): MenuPlan => {
|
|
const menuPlanId = overrides.menu_plan_id ?? getNextId();
|
|
|
|
const defaultPlan: MenuPlan = {
|
|
menu_plan_id: menuPlanId,
|
|
user_id: `user-${getNextId()}`,
|
|
name: 'Weekly Plan',
|
|
start_date: new Date().toISOString().split('T')[0],
|
|
end_date: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
const { planned_meals: mealsOverrides, ...planOverrides } = overrides;
|
|
const menuPlan = { ...defaultPlan, ...planOverrides };
|
|
|
|
if (mealsOverrides) {
|
|
menuPlan.planned_meals = mealsOverrides.map((meal) =>
|
|
createMockPlannedMeal({
|
|
menu_plan_id: menuPlanId,
|
|
...meal,
|
|
}),
|
|
);
|
|
}
|
|
|
|
return menuPlan;
|
|
};
|
|
|
|
/**
|
|
* Creates a mock ActivityLogItem object for use in tests.
|
|
* This factory handles the discriminated union nature of the ActivityLogItem type.
|
|
* By default, it creates a 'flyer_processed' log item. You can override the 'action'
|
|
* and 'details' to create other types of log items.
|
|
*
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* e.g., `createMockActivityLogItem({ action: 'user_registered', details: { full_name: 'New User' } })`
|
|
* @returns A complete and type-safe ActivityLogItem object.
|
|
*/
|
|
export const createMockActivityLogItem = (
|
|
overrides: Partial<ActivityLogItem> = {},
|
|
): ActivityLogItem => {
|
|
const action = overrides.action ?? 'flyer_processed';
|
|
|
|
const baseLog = {
|
|
activity_log_id: getNextId(),
|
|
user_id: `user-${getNextId()}`,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
let specificLog: ActivityLogItem;
|
|
|
|
// Create a default log based on the action, which can then be overridden.
|
|
switch (action) {
|
|
case 'recipe_created':
|
|
specificLog = {
|
|
...baseLog,
|
|
action: 'recipe_created',
|
|
display_text: 'Created a new recipe: Mock Recipe.',
|
|
icon: 'chef-hat',
|
|
details: { recipe_id: 1, recipe_name: 'Mock Recipe' },
|
|
};
|
|
break;
|
|
case 'user_registered':
|
|
specificLog = {
|
|
...baseLog,
|
|
action: 'user_registered',
|
|
display_text: 'A new user has registered.',
|
|
icon: 'user-plus',
|
|
details: { full_name: 'New Mock User' },
|
|
};
|
|
break;
|
|
case 'list_shared':
|
|
specificLog = {
|
|
...baseLog,
|
|
action: 'list_shared',
|
|
display_text: 'A shopping list was shared.',
|
|
icon: 'share-2',
|
|
details: { list_name: 'Mock List', shopping_list_id: 1, shared_with_name: 'Another User' },
|
|
};
|
|
break;
|
|
case 'recipe_favorited':
|
|
specificLog = {
|
|
...baseLog,
|
|
action: 'recipe_favorited',
|
|
display_text: 'User favorited a recipe.',
|
|
icon: 'heart',
|
|
user_full_name: 'Mock User',
|
|
details: { recipe_name: 'Mock Recipe' },
|
|
};
|
|
break;
|
|
case 'flyer_processed':
|
|
default:
|
|
specificLog = {
|
|
...baseLog,
|
|
action: 'flyer_processed',
|
|
display_text: 'Processed a new flyer for Mock Store.',
|
|
icon: 'file-check',
|
|
details: { flyer_id: 1, store_name: 'Mock Store' },
|
|
};
|
|
break;
|
|
}
|
|
|
|
// Merge the generated log with any specific overrides provided.
|
|
// This allows for deep merging of the 'details' object.
|
|
return {
|
|
...specificLog,
|
|
...overrides,
|
|
details: { ...specificLog.details, ...overrides.details },
|
|
} as ActivityLogItem;
|
|
};
|
|
|
|
/**
|
|
* Creates a mock Achievement object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe Achievement object.
|
|
*/
|
|
export const createMockAchievement = (overrides: Partial<Achievement> = {}): Achievement => {
|
|
const defaultAchievement: Achievement = {
|
|
achievement_id: getNextId(),
|
|
name: 'Mock Achievement',
|
|
description: 'A great accomplishment.',
|
|
icon: 'star',
|
|
points_value: 10,
|
|
created_at: new Date().toISOString(),
|
|
};
|
|
return { ...defaultAchievement, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock object representing a joined UserAchievement and Achievement for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe object representing the joined achievement data.
|
|
*/
|
|
export const createMockUserAchievement = (
|
|
overrides: Partial<UserAchievement & Achievement> = {},
|
|
): UserAchievement & Achievement => {
|
|
const achievementId = overrides.achievement_id ?? getNextId();
|
|
const defaultUserAchievement: UserAchievement & Achievement = {
|
|
user_id: `user-${getNextId()}`,
|
|
achievement_id: achievementId,
|
|
achieved_at: new Date().toISOString(),
|
|
// from Achievement
|
|
name: 'Mock User Achievement',
|
|
description: 'An achievement someone earned.',
|
|
icon: 'award',
|
|
points_value: 20,
|
|
created_at: new Date().toISOString(),
|
|
};
|
|
return { ...defaultUserAchievement, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock Budget object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe Budget object.
|
|
*/
|
|
export const createMockBudget = (overrides: Partial<Budget> = {}): Budget => {
|
|
const defaultBudget: Budget = {
|
|
budget_id: getNextId(),
|
|
user_id: `user-${getNextId()}`,
|
|
name: 'Monthly Groceries',
|
|
amount_cents: 50000,
|
|
period: 'monthly',
|
|
start_date: new Date().toISOString().split('T')[0],
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
return { ...defaultBudget, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock SpendingByCategory object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe SpendingByCategory object.
|
|
*/
|
|
export const createMockSpendingByCategory = (
|
|
overrides: Partial<SpendingByCategory> = {},
|
|
): SpendingByCategory => {
|
|
const defaultSpending: SpendingByCategory = {
|
|
category_id: getNextId(),
|
|
category_name: 'Produce',
|
|
total_spent_cents: 15000,
|
|
};
|
|
return { ...defaultSpending, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock MasterGroceryItem object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe MasterGroceryItem object.
|
|
*/
|
|
export const createMockMasterGroceryItem = (
|
|
overrides: Partial<MasterGroceryItem> & { category?: Partial<Category> } = {},
|
|
): MasterGroceryItem => {
|
|
// Ensure category_id is consistent between the item and the nested category object
|
|
const category = createMockCategory({
|
|
...overrides.category,
|
|
// Prioritize the top-level category_id if provided
|
|
category_id: overrides.category_id ?? overrides.category?.category_id,
|
|
});
|
|
|
|
const defaultItem: MasterGroceryItem = {
|
|
master_grocery_item_id: getNextId(),
|
|
name: 'Mock Master Item',
|
|
category_id: category.category_id,
|
|
category_name: category.name,
|
|
is_allergen: false,
|
|
allergy_info: null,
|
|
created_by: null,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
const { category: _, ...itemOverrides } = overrides;
|
|
|
|
return { ...defaultItem, ...itemOverrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock PantryItem object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* Can optionally include a `master_item` to link IDs.
|
|
* @returns A complete and type-safe PantryItem object.
|
|
*/
|
|
export const createMockPantryItem = (
|
|
overrides: Partial<PantryItem> & { master_item?: Partial<MasterGroceryItem> } = {},
|
|
): PantryItem => {
|
|
const pantryItemId = overrides.pantry_item_id ?? getNextId();
|
|
|
|
const masterItemId =
|
|
overrides.master_item_id ?? overrides.master_item?.master_grocery_item_id ?? getNextId();
|
|
|
|
const defaultItem: PantryItem = {
|
|
pantry_item_id: pantryItemId,
|
|
user_id: `user-${getNextId()}`,
|
|
master_item_id: masterItemId,
|
|
quantity: 1,
|
|
unit: 'each',
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
const { master_item: _, ...itemOverrides } = overrides;
|
|
|
|
return { ...defaultItem, ...itemOverrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock ShoppingList object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe ShoppingList object.
|
|
*/
|
|
export const createMockShoppingList = (
|
|
overrides: Omit<Partial<ShoppingList>, 'items'> & {
|
|
items?: (Partial<ShoppingListItem> & { master_item?: Partial<MasterGroceryItem> | null })[];
|
|
} = {},
|
|
): ShoppingList => {
|
|
const shoppingListId = overrides.shopping_list_id ?? getNextId();
|
|
|
|
const defaultList: ShoppingList = {
|
|
shopping_list_id: shoppingListId,
|
|
user_id: `user-${getNextId()}`,
|
|
name: 'My Mock List',
|
|
items: [],
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
if (overrides.items) {
|
|
defaultList.items = overrides.items.map((item) =>
|
|
createMockShoppingListItem({
|
|
shopping_list_id: shoppingListId,
|
|
...item,
|
|
}),
|
|
);
|
|
}
|
|
|
|
const { items: _, ...listOverrides } = overrides;
|
|
|
|
return { ...defaultList, ...listOverrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock ShoppingListItem object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* Can optionally include a `master_item` to link IDs and populate joined data.
|
|
* @returns A complete and type-safe ShoppingListItem object.
|
|
*/
|
|
export const createMockShoppingListItem = (
|
|
overrides: Partial<ShoppingListItem> & { master_item?: Partial<MasterGroceryItem> | null } = {},
|
|
): ShoppingListItem => {
|
|
const shoppingListItemId = overrides.shopping_list_item_id ?? getNextId();
|
|
const shoppingListId = overrides.shopping_list_id ?? getNextId();
|
|
|
|
const masterItemId = overrides.master_item_id ?? overrides.master_item?.master_grocery_item_id;
|
|
|
|
const defaultItem: ShoppingListItem = {
|
|
shopping_list_item_id: shoppingListItemId,
|
|
shopping_list_id: shoppingListId,
|
|
custom_item_name: 'Mock Shopping List Item',
|
|
quantity: 1,
|
|
is_purchased: false, // This was correct
|
|
added_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
master_item_id: masterItemId,
|
|
};
|
|
|
|
const { master_item: masterItemOverride, ...itemOverrides } = overrides;
|
|
const result = { ...defaultItem, ...itemOverrides };
|
|
|
|
if (masterItemOverride && !result.master_item && masterItemOverride.name) {
|
|
result.master_item = { name: masterItemOverride.name };
|
|
}
|
|
|
|
return result;
|
|
};
|
|
|
|
/**
|
|
* Creates a mock ShoppingTripItem object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe ShoppingTripItem object.
|
|
*/
|
|
export const createMockShoppingTripItem = (
|
|
overrides: Partial<ShoppingTripItem> & { master_item?: Partial<MasterGroceryItem> } = {},
|
|
): ShoppingTripItem => {
|
|
const tripItemId = overrides.shopping_trip_item_id ?? getNextId();
|
|
const masterItemId = overrides.master_item_id ?? overrides.master_item?.master_grocery_item_id;
|
|
|
|
const defaultItem: ShoppingTripItem = {
|
|
shopping_trip_item_id: tripItemId,
|
|
shopping_trip_id: getNextId(),
|
|
master_item_id: masterItemId,
|
|
custom_item_name: masterItemId ? null : 'Custom Trip Item',
|
|
master_item_name: masterItemId ? (overrides.master_item?.name ?? 'Mock Master Item') : null,
|
|
quantity: 1,
|
|
price_paid_cents: 199,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
const { master_item: _, ...itemOverrides } = overrides;
|
|
|
|
return { ...defaultItem, ...itemOverrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock ShoppingTrip object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe ShoppingTrip object.
|
|
*/
|
|
export const createMockShoppingTrip = (
|
|
overrides: Omit<Partial<ShoppingTrip>, 'items'> & { items?: Partial<ShoppingTripItem>[] } = {},
|
|
): ShoppingTrip => {
|
|
const tripId = overrides.shopping_trip_id ?? getNextId();
|
|
|
|
const defaultTrip: ShoppingTrip = {
|
|
shopping_trip_id: tripId,
|
|
user_id: `user-${getNextId()}`,
|
|
shopping_list_id: null,
|
|
completed_at: new Date().toISOString(),
|
|
total_spent_cents: 0,
|
|
items: [],
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
const { items: itemsOverrides, ...tripOverrides } = overrides;
|
|
const trip = { ...defaultTrip, ...tripOverrides };
|
|
|
|
if (itemsOverrides) {
|
|
trip.items = itemsOverrides.map((item) =>
|
|
createMockShoppingTripItem({ shopping_trip_id: tripId, ...item }),
|
|
);
|
|
if (overrides.total_spent_cents === undefined) {
|
|
trip.total_spent_cents = trip.items.reduce(
|
|
(total, item) => total + (item.price_paid_cents ?? 0),
|
|
0,
|
|
);
|
|
}
|
|
}
|
|
|
|
return trip;
|
|
};
|
|
|
|
/**
|
|
* Creates a mock ReceiptItem object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe ReceiptItem object.
|
|
*/
|
|
export const createMockReceiptItem = (overrides: Partial<ReceiptItem> = {}): ReceiptItem => {
|
|
const defaultItem: ReceiptItem = {
|
|
receipt_item_id: getNextId(),
|
|
receipt_id: getNextId(),
|
|
raw_item_description: 'Mock Receipt Item',
|
|
quantity: 1,
|
|
price_paid_cents: 199,
|
|
master_item_id: null,
|
|
product_id: null,
|
|
status: 'unmatched',
|
|
upc_code: null,
|
|
line_number: null,
|
|
match_confidence: null,
|
|
is_discount: false,
|
|
unit_price_cents: null,
|
|
unit_type: null,
|
|
added_to_pantry: false,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
return { ...defaultItem, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock Receipt object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe Receipt object.
|
|
*/
|
|
export const createMockReceipt = (
|
|
overrides: Omit<Partial<Receipt>, 'items'> & { items?: Partial<ReceiptItem>[] } = {},
|
|
): Receipt => {
|
|
const receiptId = overrides.receipt_id ?? getNextId();
|
|
|
|
const defaultReceipt: Receipt = {
|
|
receipt_id: receiptId,
|
|
user_id: `user-${getNextId()}`,
|
|
store_location_id: null,
|
|
receipt_image_url: `/receipts/mock-receipt-${receiptId}.jpg`,
|
|
transaction_date: new Date().toISOString(),
|
|
total_amount_cents: null,
|
|
status: 'pending',
|
|
raw_text: null,
|
|
processed_at: null,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
const { items: itemsOverrides, ...receiptOverrides } = overrides;
|
|
const receipt = { ...defaultReceipt, ...receiptOverrides };
|
|
|
|
if (itemsOverrides) {
|
|
receipt.items = itemsOverrides.map((item) =>
|
|
createMockReceiptItem({ receipt_id: receiptId, ...item }),
|
|
);
|
|
}
|
|
|
|
return receipt;
|
|
};
|
|
|
|
/**
|
|
* Creates a mock DietaryRestriction object for testing.
|
|
* @param overrides - Optional properties to override the defaults.
|
|
* @returns A mock DietaryRestriction object.
|
|
*/
|
|
export const createMockDietaryRestriction = (
|
|
overrides: Partial<DietaryRestriction> = {},
|
|
): DietaryRestriction => {
|
|
return {
|
|
dietary_restriction_id: 1,
|
|
name: 'Vegetarian',
|
|
type: 'diet',
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
...overrides,
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Creates a mock DealItem object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe DealItem object.
|
|
*/
|
|
export const createMockDealItem = (overrides: Partial<DealItem> = {}): DealItem => {
|
|
const defaultDealItem: DealItem = {
|
|
item: 'Mock Deal Item',
|
|
price_display: '$1.99',
|
|
price_in_cents: 199,
|
|
quantity: 'each',
|
|
storeName: 'Mock Store',
|
|
master_item_name: 'Mock Master Item',
|
|
unit_price: null,
|
|
};
|
|
|
|
return { ...defaultDealItem, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock ItemPriceHistory object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe ItemPriceHistory object.
|
|
*/
|
|
export const createMockItemPriceHistory = (
|
|
overrides: Partial<ItemPriceHistory> = {},
|
|
): ItemPriceHistory => {
|
|
const defaultHistory: ItemPriceHistory = {
|
|
item_price_history_id: getNextId(),
|
|
master_item_id: getNextId(),
|
|
summary_date: new Date().toISOString().split('T')[0],
|
|
min_price_in_cents: 199,
|
|
max_price_in_cents: 399,
|
|
avg_price_in_cents: 299,
|
|
data_points_count: 10,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
return { ...defaultHistory, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock HistoricalPriceDataPoint object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe HistoricalPriceDataPoint object.
|
|
*/
|
|
export const createMockHistoricalPriceDataPoint = (
|
|
overrides: Partial<HistoricalPriceDataPoint> = {},
|
|
): HistoricalPriceDataPoint => {
|
|
const defaultPoint: HistoricalPriceDataPoint = {
|
|
master_item_id: getNextId(),
|
|
avg_price_in_cents: 250,
|
|
summary_date: new Date().toISOString().split('T')[0],
|
|
};
|
|
return { ...defaultPoint, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock ReceiptDeal object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe ReceiptDeal object.
|
|
*/
|
|
export const createMockReceiptDeal = (overrides: Partial<ReceiptDeal> = {}): ReceiptDeal => {
|
|
const defaultDeal: ReceiptDeal = {
|
|
receipt_item_id: getNextId(),
|
|
master_item_id: getNextId(),
|
|
item_name: 'Mock Deal Item',
|
|
price_paid_cents: 199,
|
|
current_best_price_in_cents: 150,
|
|
potential_savings_cents: 49,
|
|
deal_store_name: 'Competitor Store',
|
|
flyer_id: getNextId(),
|
|
};
|
|
return { ...defaultDeal, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock RecipeCollection object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe RecipeCollection object.
|
|
*/
|
|
export const createMockRecipeCollection = (
|
|
overrides: Partial<RecipeCollection> = {},
|
|
): RecipeCollection => {
|
|
const defaultCollection: RecipeCollection = {
|
|
recipe_collection_id: getNextId(),
|
|
user_id: `user-${getNextId()}`,
|
|
name: 'My Favorite Recipes',
|
|
description: 'A collection of mock recipes.',
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
return { ...defaultCollection, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock SharedShoppingList object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe SharedShoppingList object.
|
|
*/
|
|
export const createMockSharedShoppingList = (
|
|
overrides: Partial<SharedShoppingList> = {},
|
|
): SharedShoppingList => {
|
|
const defaultSharedList: SharedShoppingList = {
|
|
shared_shopping_list_id: getNextId(),
|
|
shopping_list_id: getNextId(),
|
|
shared_by_user_id: `user-${getNextId()}`,
|
|
shared_with_user_id: `user-${getNextId()}`,
|
|
permission_level: 'view',
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
return { ...defaultSharedList, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock MostFrequentSaleItem object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe MostFrequentSaleItem object.
|
|
*/
|
|
export const createMockMostFrequentSaleItem = (
|
|
overrides: Partial<MostFrequentSaleItem> = {},
|
|
): MostFrequentSaleItem => {
|
|
const defaultItem: MostFrequentSaleItem = {
|
|
master_item_id: getNextId(),
|
|
item_name: 'Chicken Breast',
|
|
sale_count: 25,
|
|
};
|
|
return { ...defaultItem, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock PantryRecipe object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe PantryRecipe object.
|
|
*/
|
|
export const createMockPantryRecipe = (overrides: Partial<PantryRecipe> = {}): PantryRecipe => {
|
|
const defaultRecipe = createMockRecipe({ name: 'Pantry Special', ...overrides });
|
|
const pantryRecipe: PantryRecipe = {
|
|
...defaultRecipe,
|
|
missing_ingredients_count: 2,
|
|
pantry_ingredients_count: 5,
|
|
};
|
|
return { ...pantryRecipe, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock RecommendedRecipe object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe RecommendedRecipe object.
|
|
*/
|
|
export const createMockRecommendedRecipe = (
|
|
overrides: Partial<RecommendedRecipe> = {},
|
|
): RecommendedRecipe => {
|
|
const defaultRecipe = createMockRecipe({ name: 'Highly Recommended', ...overrides });
|
|
const recommendedRecipe: RecommendedRecipe = {
|
|
...defaultRecipe,
|
|
recommendation_score: 0.85,
|
|
reason: 'Based on your recent activity and pantry items.',
|
|
};
|
|
return { ...recommendedRecipe, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock UnitPrice object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe UnitPrice object.
|
|
*/
|
|
export const createMockUnitPrice = (overrides: Partial<UnitPrice> = {}): UnitPrice => {
|
|
const defaultUnitPrice: UnitPrice = {
|
|
value: 100,
|
|
unit: 'g',
|
|
};
|
|
return { ...defaultUnitPrice, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock Source object for use in tests, typically for AI analysis results.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe Source object.
|
|
*/
|
|
export const createMockSource = (overrides: Partial<Source> = {}): Source => {
|
|
const defaultSource: Source = {
|
|
uri: 'https://example.com/mock-source',
|
|
title: 'Mock Source Title',
|
|
};
|
|
return { ...defaultSource, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock UserAlert object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe UserAlert object.
|
|
*/
|
|
export const createMockUserAlert = (overrides: Partial<UserAlert> = {}): UserAlert => {
|
|
const defaultAlert: UserAlert = {
|
|
user_alert_id: getNextId(),
|
|
user_watched_item_id: getNextId(),
|
|
alert_type: 'PRICE_BELOW',
|
|
threshold_value: 499,
|
|
is_active: true,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
return { ...defaultAlert, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock UserSubmittedPrice object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe UserSubmittedPrice object.
|
|
*/
|
|
export const createMockUserSubmittedPrice = (
|
|
overrides: Partial<UserSubmittedPrice> = {},
|
|
): UserSubmittedPrice => {
|
|
const defaultPrice: UserSubmittedPrice = {
|
|
user_submitted_price_id: getNextId(),
|
|
user_id: `user-${getNextId()}`,
|
|
master_item_id: getNextId(),
|
|
store_location_id: getNextId(),
|
|
price_in_cents: 299,
|
|
photo_url: null,
|
|
upvotes: 0,
|
|
downvotes: 0,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
return { ...defaultPrice, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock RecipeRating object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe RecipeRating object.
|
|
*/
|
|
export const createMockRecipeRating = (overrides: Partial<RecipeRating> = {}): RecipeRating => {
|
|
const defaultRating: RecipeRating = {
|
|
recipe_rating_id: getNextId(),
|
|
recipe_id: getNextId(),
|
|
user_id: `user-${getNextId()}`,
|
|
rating: 5,
|
|
comment: 'Great recipe!',
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
return { ...defaultRating, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock Tag object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe Tag object.
|
|
*/
|
|
export const createMockTag = (overrides: Partial<Tag> = {}): Tag => {
|
|
const tagId = overrides.tag_id ?? getNextId();
|
|
const defaultTag: Tag = {
|
|
tag_id: tagId,
|
|
name: `Tag ${tagId}`,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
return { ...defaultTag, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock PantryLocation object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe PantryLocation object.
|
|
*/
|
|
export const createMockPantryLocation = (
|
|
overrides: Partial<PantryLocation> = {},
|
|
): PantryLocation => {
|
|
const locationId = overrides.pantry_location_id ?? getNextId();
|
|
const defaultLocation: PantryLocation = {
|
|
pantry_location_id: locationId,
|
|
user_id: `user-${getNextId()}`,
|
|
name: `Location ${locationId}`,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
return { ...defaultLocation, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock AppStats object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe AppStats object.
|
|
*/
|
|
export const createMockAppStats = (overrides: Partial<AppStats> = {}): AppStats => {
|
|
const defaultStats: AppStats = {
|
|
userCount: 100,
|
|
flyerCount: 50,
|
|
flyerItemCount: 2000,
|
|
storeCount: 5,
|
|
pendingCorrectionCount: 0,
|
|
recipeCount: 500,
|
|
};
|
|
return { ...defaultStats, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock UserDietaryRestriction object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* Can optionally include `user` and `restriction` objects to link IDs.
|
|
* @returns A complete and type-safe UserDietaryRestriction object.
|
|
*/
|
|
export const createMockUserDietaryRestriction = (
|
|
overrides: Partial<UserDietaryRestriction> & {
|
|
user?: Partial<User>;
|
|
restriction?: Partial<DietaryRestriction>;
|
|
} = {},
|
|
): UserDietaryRestriction => {
|
|
const userId = overrides.user_id ?? overrides.user?.user_id ?? `user-${getNextId()}`;
|
|
const restrictionId =
|
|
overrides.restriction_id ?? overrides.restriction?.dietary_restriction_id ?? getNextId();
|
|
|
|
const defaultUserRestriction: UserDietaryRestriction = {
|
|
user_id: userId,
|
|
restriction_id: restrictionId,
|
|
created_at: new Date().toISOString(),
|
|
};
|
|
|
|
return { ...defaultUserRestriction, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock UserAppliance object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* Can optionally include `user` and `appliance` objects to link IDs.
|
|
* @returns A complete and type-safe UserAppliance object.
|
|
*/
|
|
export const createMockUserAppliance = (
|
|
overrides: Partial<UserAppliance> & { user?: Partial<User>; appliance?: Partial<Appliance> } = {},
|
|
): UserAppliance => {
|
|
const userId = overrides.user_id ?? overrides.user?.user_id ?? `user-${getNextId()}`;
|
|
const applianceId = overrides.appliance_id ?? overrides.appliance?.appliance_id ?? getNextId();
|
|
|
|
const defaultUserAppliance = {
|
|
user_id: userId,
|
|
appliance_id: applianceId,
|
|
created_at: new Date().toISOString(),
|
|
};
|
|
|
|
// The 'as UserAppliance' cast is necessary because TypeScript can't guarantee that the spread of a Partial<T> results in a complete T.
|
|
return { ...defaultUserAppliance, ...overrides } as UserAppliance;
|
|
};
|
|
|
|
/**
|
|
* Creates a mock Address object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe Address object.
|
|
*/
|
|
export const createMockAddress = (overrides: Partial<Address> = {}): Address => {
|
|
const defaultAddress: Address = {
|
|
address_id: getNextId(),
|
|
address_line_1: '123 Mock St',
|
|
city: 'Mockville',
|
|
province_state: 'BC',
|
|
postal_code: 'V8T 1A1',
|
|
country: 'CA',
|
|
// Optional fields
|
|
address_line_2: null,
|
|
latitude: null,
|
|
longitude: null,
|
|
location: null,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
return { ...defaultAddress, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock StoreLocation object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe StoreLocation object.
|
|
*/
|
|
export const createMockStoreLocation = (overrides: Partial<StoreLocation> = {}): StoreLocation => {
|
|
const defaultStoreLocation: StoreLocation = {
|
|
store_location_id: getNextId(),
|
|
store_id: overrides.store_id ?? getNextId(),
|
|
address_id: overrides.address_id ?? getNextId(),
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
return { ...defaultStoreLocation, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock StoreLocationWithAddress object for use in tests.
|
|
* Includes a full address object nested within the store location.
|
|
*
|
|
* @param overrides - An object containing properties to override the default mock values,
|
|
* including nested properties for the `address`.
|
|
* e.g., `createMockStoreLocationWithAddress({ address: { city: 'Toronto' } })`
|
|
* @returns A complete and type-safe StoreLocationWithAddress object.
|
|
*/
|
|
export const createMockStoreLocationWithAddress = (
|
|
overrides: Omit<Partial<StoreLocationWithAddress>, 'address'> & {
|
|
address?: Partial<Address>;
|
|
} = {},
|
|
): StoreLocationWithAddress => {
|
|
// Create the address first, using the address_id from overrides if provided
|
|
const address = createMockAddress({
|
|
address_id: overrides.address_id,
|
|
...overrides.address,
|
|
});
|
|
|
|
// Create the store location with the address_id matching the address
|
|
const storeLocation = createMockStoreLocation({
|
|
...overrides,
|
|
address_id: address.address_id,
|
|
});
|
|
|
|
return {
|
|
...storeLocation,
|
|
address,
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Creates a mock StoreWithLocations object for use in tests.
|
|
* Includes the store data along with an array of store locations with addresses.
|
|
*
|
|
* @param overrides - An object containing properties to override the default mock values,
|
|
* including the `locations` array.
|
|
* e.g., `createMockStoreWithLocations({ name: 'Walmart', locations: [{ address: { city: 'Toronto' } }] })`
|
|
* @returns A complete and type-safe StoreWithLocations object.
|
|
*/
|
|
export const createMockStoreWithLocations = (
|
|
overrides: Omit<Partial<StoreWithLocations>, 'locations'> & {
|
|
locations?: Array<
|
|
Omit<Partial<StoreLocationWithAddress>, 'address'> & { address?: Partial<Address> }
|
|
>;
|
|
} = {},
|
|
): StoreWithLocations => {
|
|
const store = createMockStore(overrides);
|
|
|
|
// If locations are provided, create them; otherwise create one default location
|
|
const locations = overrides.locations?.map((locOverride) =>
|
|
createMockStoreLocationWithAddress({
|
|
...locOverride,
|
|
store_id: store.store_id,
|
|
}),
|
|
) ?? [
|
|
createMockStoreLocationWithAddress({
|
|
store_id: store.store_id,
|
|
}),
|
|
];
|
|
|
|
return {
|
|
...store,
|
|
locations,
|
|
};
|
|
};
|
|
|
|
/**
|
|
* Creates a mock UserWithPasswordHash object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe UserWithPasswordHash object.
|
|
*/
|
|
export const createMockUserWithPasswordHash = (
|
|
overrides: Partial<UserWithPasswordHash> = {},
|
|
): UserWithPasswordHash => {
|
|
const userId = overrides.user_id ?? `user-${getNextId()}`;
|
|
|
|
const defaultUser: UserWithPasswordHash = {
|
|
user_id: userId,
|
|
email: `${userId}@example.com`,
|
|
password_hash: 'hashed_password',
|
|
failed_login_attempts: 0,
|
|
last_failed_login: null,
|
|
last_login_ip: null,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
return { ...defaultUser, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock Profile object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe Profile object.
|
|
*/
|
|
export const createMockProfile = (overrides: Partial<Profile> = {}): Profile => {
|
|
const defaultProfile: Profile = {
|
|
full_name: 'Mock Profile User',
|
|
avatar_url: null,
|
|
address_id: null,
|
|
points: 0,
|
|
role: 'user',
|
|
preferences: {},
|
|
created_by: null,
|
|
updated_by: null,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
return { ...defaultProfile, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock WatchedItemDeal object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe WatchedItemDeal object.
|
|
*/
|
|
export const createMockWatchedItemDeal = (
|
|
overrides: Partial<WatchedItemDeal> = {},
|
|
): WatchedItemDeal => {
|
|
const defaultDeal: WatchedItemDeal = {
|
|
master_item_id: getNextId(),
|
|
item_name: 'Mock Deal Item',
|
|
best_price_in_cents: 599,
|
|
store: {
|
|
store_id: getNextId(),
|
|
name: 'Mock Store',
|
|
logo_url: null,
|
|
locations: [],
|
|
},
|
|
flyer_id: getNextId(),
|
|
valid_to: new Date(Date.now() + 5 * 24 * 60 * 60 * 1000).toISOString(), // 5 days from now
|
|
};
|
|
|
|
return { ...defaultDeal, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock LeaderboardUser object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe LeaderboardUser object.
|
|
*/
|
|
export const createMockLeaderboardUser = (
|
|
overrides: Partial<LeaderboardUser> = {},
|
|
): LeaderboardUser => {
|
|
const userId = overrides.user_id ?? `user-${getNextId()}`;
|
|
|
|
const defaultUser: LeaderboardUser = {
|
|
user_id: userId,
|
|
full_name: 'Leaderboard User',
|
|
avatar_url: null,
|
|
points: 500,
|
|
rank: '10',
|
|
};
|
|
|
|
return { ...defaultUser, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock UnmatchedFlyerItem object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe UnmatchedFlyerItem object.
|
|
*/
|
|
export const createMockUnmatchedFlyerItem = (
|
|
overrides: Partial<UnmatchedFlyerItem> = {},
|
|
): UnmatchedFlyerItem => {
|
|
const defaultItem: UnmatchedFlyerItem = {
|
|
unmatched_flyer_item_id: getNextId(),
|
|
status: 'pending',
|
|
reviewed_at: null,
|
|
flyer_item_id: getNextId(),
|
|
flyer_item_name: 'Mystery Product',
|
|
price_display: '$?.??',
|
|
flyer_id: getNextId(),
|
|
store_name: 'Random Store',
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
return { ...defaultItem, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock AdminUserView object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe AdminUserView object.
|
|
*/
|
|
export const createMockAdminUserView = (overrides: Partial<AdminUserView> = {}): AdminUserView => {
|
|
const userId = overrides.user_id ?? `user-${getNextId()}`;
|
|
|
|
const defaultUserView: AdminUserView = {
|
|
user_id: userId,
|
|
email: `${userId}@example.com`,
|
|
role: 'user',
|
|
full_name: 'Mock User',
|
|
avatar_url: null,
|
|
created_at: new Date().toISOString(),
|
|
};
|
|
|
|
return { ...defaultUserView, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock Notification object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe Notification object.
|
|
*/
|
|
export const createMockNotification = (overrides: Partial<Notification> = {}): Notification => {
|
|
const defaultNotification: Notification = {
|
|
notification_id: getNextId(),
|
|
user_id: `user-${getNextId()}`,
|
|
content: 'This is a mock notification.',
|
|
link_url: null,
|
|
is_read: false,
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
};
|
|
|
|
return { ...defaultNotification, ...overrides };
|
|
};
|
|
|
|
/**
|
|
* Creates a mock ProcessingStage object for use in tests.
|
|
* @param overrides - An object containing properties to override the default mock values.
|
|
* @returns A complete and type-safe ProcessingStage object.
|
|
*/
|
|
export const createMockProcessingStage = (
|
|
overrides: Partial<ProcessingStage> = {},
|
|
): ProcessingStage => {
|
|
const defaultStage: ProcessingStage = {
|
|
name: 'Mock Stage',
|
|
status: 'pending',
|
|
detail: '',
|
|
critical: true,
|
|
};
|
|
|
|
return { ...defaultStage, ...overrides };
|
|
};
|
|
|
|
export const createMockAppliance = (overrides: Partial<Appliance> = {}): Appliance => {
|
|
return {
|
|
appliance_id: 1,
|
|
name: 'Oven',
|
|
created_at: new Date().toISOString(),
|
|
updated_at: new Date().toISOString(),
|
|
...overrides,
|
|
};
|
|
};
|
|
|
|
// src/tests/utils/mockFactories.ts
|
|
|
|
// ... existing factories
|
|
|
|
export const createMockShoppingListItemPayload = (
|
|
overrides: Partial<{ masterItemId: number; customItemName: string }> = {},
|
|
): { masterItemId?: number; customItemName?: string } => ({
|
|
customItemName: 'Mock Item',
|
|
...overrides,
|
|
});
|
|
|
|
export const createMockRecipeCommentPayload = (
|
|
overrides: Partial<{ content: string; parentCommentId: number }> = {},
|
|
): { content: string; parentCommentId?: number } => ({
|
|
content: 'This is a mock comment.',
|
|
...overrides,
|
|
});
|
|
|
|
export const createMockProfileUpdatePayload = (
|
|
overrides: Partial<Profile> = {},
|
|
): Partial<Profile> => ({
|
|
full_name: 'Mock User',
|
|
...overrides,
|
|
});
|
|
|
|
export const createMockAddressPayload = (overrides: Partial<Address> = {}): Partial<Address> => ({
|
|
address_line_1: '123 Mock St',
|
|
city: 'Mockville',
|
|
province_state: 'MS',
|
|
postal_code: '12345',
|
|
country: 'Mockland',
|
|
...overrides,
|
|
});
|
|
|
|
export const createMockSearchQueryPayload = (
|
|
overrides: Partial<
|
|
Omit<SearchQuery, 'search_query_id' | 'created_at' | 'updated_at' | 'user_id'>
|
|
> = {},
|
|
): Omit<SearchQuery, 'search_query_id' | 'created_at' | 'updated_at' | 'user_id'> => ({
|
|
query_text: 'mock search',
|
|
result_count: 5,
|
|
was_successful: true,
|
|
...overrides,
|
|
});
|
|
|
|
export const createMockWatchedItemPayload = (
|
|
overrides: Partial<{ itemName: string; category: string }> = {},
|
|
): { itemName: string; category: string } => ({
|
|
itemName: 'Mock Watched Item',
|
|
category: 'Pantry',
|
|
...overrides,
|
|
});
|
|
|
|
export const createMockRegisterUserPayload = (
|
|
overrides: Partial<{
|
|
email: string;
|
|
password: string;
|
|
full_name: string;
|
|
avatar_url: string | undefined;
|
|
}> = {},
|
|
) => ({
|
|
email: 'mock@example.com',
|
|
password: 'password123',
|
|
full_name: 'Mock User',
|
|
avatar_url: undefined,
|
|
...overrides,
|
|
});
|
|
|
|
export const createMockLoginPayload = (
|
|
overrides: Partial<{ email: string; password: string; rememberMe: boolean }> = {},
|
|
) => ({
|
|
email: 'mock@example.com',
|
|
password: 'password123',
|
|
rememberMe: false,
|
|
...overrides,
|
|
});
|