import test from 'ava'; import { Types } from 'mongoose'; import { UserInputError } from 'apollo-server-micro'; import { Factory } from '../../../database/factory'; import * as testUtils from '../../../test/utils'; import { RecipeCollection, RecipeCollectionType } from '../collection-model'; import { Recipe } from '../../recipe'; import { User } from '../../../app/user'; import { createContext } from '../../../test/utils/create-mock-context'; import { defineUserAbility } from '../../../server/authorization/user-authorization'; import { createRecipeCollection } from '../schema/create-collection'; import { AuthenticationError } from 'apollo-server-micro'; import { SmartRecipeCollection } from '../smart-collection-model'; import { ManualRecipeCollection } from '../manual-collection-model'; test.before(testUtils.setupDB); test.afterEach.always(testUtils.cleanupDB); test.after.always(testUtils.tearDownDB); // // Tests // test.serial('Should save RecipeCollection to DB', async t => { const user = await Factory.create('user'); const context = createContext({ state: { user, abilities: defineUserAbility(user) }, }); const recipes = await Factory.createMany('recipe', 3, { ownerId: user.id, }); const collection = await createRecipeCollection( null, { input: { name: 'Test Collection', recipes: recipes.map(r => r.id), }, }, context, null ); const dbCollection = await RecipeCollection.findById(collection.id).exec(); // collection exists in the DB t.truthy(dbCollection); // Added the correct amount of recipes t.is(dbCollection.nodes.length, 3); }); test.serial('Should return correct Collection types', async t => { const user = await Factory.create('user'); const context = createContext({ state: { user, abilities: defineUserAbility(user) }, }); const defaultCollection = await createRecipeCollection( null, {}, context, null ); const manualCollection = await createRecipeCollection( null, { input: { type: 'MANUAL' } }, context, null ); const smartCollection = await createRecipeCollection( null, { input: { type: 'SMART' } }, context, null ); // Returns the correct collection types t.true(defaultCollection instanceof ManualRecipeCollection); t.true(manualCollection instanceof ManualRecipeCollection); t.true(smartCollection instanceof SmartRecipeCollection); }); test.serial( 'Should return RecipeCollection with populated Recipes', async t => { const user = await Factory.create('user'); const context = createContext({ state: { user, abilities: defineUserAbility(user) }, }); const recipes = await Factory.createMany('recipe', 3, { ownerId: user.id, }); const collection = await createRecipeCollection( null, { input: { name: 'Test Collection', recipes: recipes.map(r => r.id), }, }, context, null ); t.truthy(collection.nodes[0].recipe instanceof Recipe); } ); test.serial( 'Should return blank RecipeCollection when no input is provided', async t => { const user = await Factory.create('user'); const context = createContext({ state: { user, abilities: defineUserAbility(user) }, }); const collection = await createRecipeCollection(null, {}, context, null); t.is(collection.nodes.length, 0); t.is(collection.name, undefined); } ); test.todo('Should not save invalid recipe ids to the collection'); test.serial( 'Should throw an error when trying to add recipes to a Smart Collection', async t => { const user = await Factory.create('user'); const context = createContext({ state: { user, abilities: defineUserAbility(user) }, }); await t.throwsAsync(async () => { return createRecipeCollection( null, { input: { type: 'SMART', recipes: [Types.ObjectId().toHexString()] } }, context, null ); }, UserInputError); } ); test.serial( 'Should throw an error when trying to add filters to a Manual Collection', async t => { const user = await Factory.create('user'); const context = createContext({ state: { user, abilities: defineUserAbility(user) }, }); await t.throwsAsync(async () => { return createRecipeCollection( null, { input: { type: 'MANUAL', filters: [] } }, context, null ); }, UserInputError); } ); test.serial( 'Should return an error when the user is not logged in', async t => { const context = createContext({ state: { user: null, abilities: defineUserAbility(null) }, }); await t.throwsAsync(async () => { return createRecipeCollection( null, { input: { name: 'Test Collection', }, }, context, null ); }, AuthenticationError); } );