import { factory, MongooseAdapter } from 'factory-girl'; import { Types } from 'mongoose'; import { Recipe, RecipeProps } from '../app/recipe'; import { ManualRecipeCollection, RecipeCollectionType, RecipeCollectionItem, RecipeCollectionItemProps, ManualRecipeCollectionProps, SmartRecipeCollection, RecipeCollectionFilterItemProps, RecipeFilterAction, RecipeFilterAttribute, } from '../app/collection'; import { Ingredient, IngredientProps, IngredientList, IngredientListProps, IngredientListSingle, IngredientListGroup, IngredientGroupProps, IngredientGroup, IngredientItemProps, IngredientItem, Measurement, IngredientListItemKind, } from '../app/ingredient'; import { Chance } from 'chance'; import { UserProps, User } from '../app/user'; import { Enum, enumValues } from '../library/enum'; const chance = new Chance(); export const Factory = new factory.FactoryGirl(); Factory.setAdapter(new MongooseAdapter()); const MeasurementArray = enumValues(Measurement); // // User // Factory.define('user', User, { firstName: () => chance.first(), lastName: () => chance.last(), email: () => chance.email(), password: () => chance.string(), }); // // Recipe // export interface RecipeFactoryOptions { ingredientCount?: number; ingredientGroupCount?: number; } Factory.define( 'recipe', Recipe, options => ({ title: () => chance.sentence({ words: 5 }), ownerId: Factory.assoc('user', '_id'), tags: [], ingredientList: Factory.assocAttrs( 'ingredientList', null, {}, { ingredientCount: options.ingredientCount !== undefined ? options.ingredientCount : chance.natural({ min: 1, max: 6 }), ingredientGroupCount: options.ingredientGroupCount !== undefined ? options.ingredientGroupCount : 0, } ), instructions: () => chance.paragraph(), }) ); // // Ingredients // // ** Ingredient Factory.define('ingredient', Ingredient, { quantity: () => chance.natural({ min: 1, max: 50 }), measurement: () => chance.pickone(MeasurementArray), name: () => chance.word(), }); // ** IngredientSingle Factory.define('ingredientSingle', IngredientListSingle, { kind: IngredientListItemKind.SINGLE, node: Factory.assocAttrs('ingredient'), }); // ** IngredientGroup Factory.define( 'ingredientGroup', IngredientListGroup, optionBuilder => ({ kind: IngredientListItemKind.GROUP, heading: () => chance.sentence({ words: 3 }), nodes: Factory.assocAttrsMany( 'ingredientSingle', optionBuilder.ingredientCount || chance.natural({ min: 2, max: 6 }) ), }) ); // ** Ingredient List Factory.define( 'ingredientList', IngredientList, options => { const ingredientCount = options.ingredientCount !== undefined ? options.ingredientCount : 0; const ingredientGroupCount = options.ingredientGroupCount !== undefined ? options.ingredientGroupCount : 0; return { nodes: async () => { const nodes = []; for (let i = 0; i < ingredientCount; i = i + 1) { nodes.push(await Factory.build('ingredientSingle')); } for (let i = 0; i < ingredientGroupCount; i = i + 1) { nodes.push(await Factory.build('ingredientGroup')); } return nodes; }, }; } ); // // Recipe Collection // interface CollectionBuildOptions { recipeCount?: number; filterCount?: number; user?: User; } Factory.define( 'collection', ManualRecipeCollection, buildOptions => { const options = { recipeCount: 0, ...buildOptions, }; const ownerId = buildOptions.user ? buildOptions.user._id : Types.ObjectId(); const recipes: RecipeCollectionItemProps[] = []; for (let i = 0; i < options.recipeCount; i++) { recipes.push({ recipe: Factory.assoc('recipe', '_id', { ownerId }), }); } return { ownerId: buildOptions.user ? buildOptions.user._id : Factory.assoc('user', '_id', { _id: ownerId }), type: RecipeCollectionType.MANUAL, name: chance.sentence({ words: 3 }), nodes: recipes, }; } ); Factory.define( 'smartCollection', SmartRecipeCollection, buildOptions => { const options = { ...buildOptions, }; const ownerId = buildOptions.user ? buildOptions.user._id : Types.ObjectId(); // ** build filters const filters: RecipeCollectionFilterItemProps[] = []; for (let i = 0; i < options.filterCount; i++) { filters.push({ attribute: chance.pickone(Object.values(RecipeFilterAttribute)), action: chance.pickone(Object.values(RecipeFilterAction)), value: chance.word(), }); } return { filters, nodes: [], ownerId: buildOptions.user ? buildOptions.user._id : Factory.assoc('user', '_id', { _id: ownerId }), type: RecipeCollectionType.SMART, name: chance.sentence({ words: 3 }), }; } );