UNPKG

@jeremyckahn/farmhand

Version:
224 lines (183 loc) 5.92 kB
import React from 'react' import { render, screen } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { INFINITE_STORAGE_LIMIT } from '../../constants.js' import { testItem, testRecipe } from '../../test-utils/index.js' import { Recipe } from './Recipe.js' vitest.mock('../../data/maps.js', async importOriginal => { const actual = await importOriginal() return { // @ts-ignore - vitest mock typing issue ...actual, itemsMap: { // @ts-ignore - vitest mock typing issue ...actual.itemsMap, 'sample-recipe-1': { id: 'sample-recipe-1', name: 'Test Recipe', value: 100, type: 'CRAFTED_ITEM', }, 'sample-item-1': { id: 'sample-item-1', name: 'Sample Item 1', value: 10, type: 'CROP', }, 'sample-item-2': { id: 'sample-item-2', name: 'Sample Item 2', value: 20, type: 'CROP', }, 'missing-ingredient': { id: 'missing-ingredient', name: 'Missing Ingredient', value: 5, type: 'CROP', }, 'test-item': { id: 'test-item', name: 'Test Item', value: 50, type: 'CRAFTED_ITEM', }, }, } }) vitest.mock('../../data/items.js') vitest.mock('../../img/index.js', () => ({ craftedItems: { 'sample-recipe-1': 'recipe-image.png', 'test-item': 'test-item-image.png', }, items: {}, })) const defaultProps = { handleMakeRecipeClick: vitest.fn(), inventory: [], inventoryLimit: INFINITE_STORAGE_LIMIT, playerInventoryQuantities: { 'sample-recipe-1': 0, 'sample-item-1': 0, 'sample-item-2': 0, 'missing-ingredient': 0, 'test-item': 0, }, recipe: testRecipe({ ingredients: { 'sample-item-1': 2, 'sample-item-2': 1, }, }), } test('renders', () => { render(<Recipe {...defaultProps} />) expect(screen.getByText('Test Recipe')).toBeInTheDocument() }) test('displays recipe name and description', () => { render(<Recipe {...defaultProps} />) expect(screen.getByText('Test Recipe')).toBeInTheDocument() expect(screen.getByText('A test recipe')).toBeInTheDocument() }) test('displays sell price information', () => { const recipe = testRecipe({ id: 'test-item', }) render(<Recipe {...defaultProps} recipe={recipe} />) expect(screen.getByText(/Sell price:/)).toBeInTheDocument() }) test('displays current inventory quantity', () => { const playerInventoryQuantities = { 'sample-recipe-1': 5, } render( <Recipe {...defaultProps} playerInventoryQuantities={playerInventoryQuantities} /> ) expect(screen.getByText(/In Inventory: 5/)).toBeInTheDocument() }) test('displays make button', () => { render(<Recipe {...defaultProps} />) const makeButton = screen.getByRole('button', { name: 'Make' }) expect(makeButton).toBeInTheDocument() }) test('displays quantity input', () => { render(<Recipe {...defaultProps} />) expect(screen.getByDisplayValue('0')).toBeInTheDocument() }) test('disables make button when recipe cannot be made', () => { const recipe = testRecipe({ ingredients: { 'missing-ingredient': 1 }, }) render(<Recipe {...defaultProps} recipe={recipe} />) const makeButton = screen.getByRole('button', { name: 'Make' }) expect(makeButton).toBeDisabled() }) test('enables make button when recipe can be made', () => { const recipe = testRecipe({ ingredients: { 'sample-item-1': 1 }, }) const inventory = [testItem({ id: 'sample-item-1', quantity: 5 })] render(<Recipe {...defaultProps} recipe={recipe} inventory={inventory} />) const makeButton = screen.getByRole('button', { name: 'Make' }) expect(makeButton).not.toBeDisabled() }) test('calls handleMakeRecipeClick when make button is clicked', async () => { const user = userEvent.setup() const handleMakeRecipeClick = vitest.fn() const recipe = testRecipe({ ingredients: { 'sample-item-1': 1 }, }) const inventory = [testItem({ id: 'sample-item-1', quantity: 5 })] render( <Recipe {...defaultProps} recipe={recipe} inventory={inventory} handleMakeRecipeClick={handleMakeRecipeClick} /> ) const makeButton = screen.getByRole('button', { name: 'Make' }) await user.click(makeButton) expect(handleMakeRecipeClick).toHaveBeenCalledWith(recipe, 1) }) test('updates quantity when quantity input changes', async () => { const user = userEvent.setup() const recipe = testRecipe({ ingredients: { 'sample-item-1': 1 }, }) const inventory = [testItem({ id: 'sample-item-1', quantity: 3 })] render(<Recipe {...defaultProps} recipe={recipe} inventory={inventory} />) const quantityInput = screen.getByDisplayValue('1') await user.clear(quantityInput) await user.type(quantityInput, '3') expect(screen.getByDisplayValue('3')).toBeInTheDocument() }) test('indicates when recipe can be made', () => { const recipe = testRecipe({ ingredients: { 'sample-item-1': 1 }, }) const inventory = [testItem({ id: 'sample-item-1', quantity: 5 })] render(<Recipe {...defaultProps} recipe={recipe} inventory={inventory} />) const recipeCard = document.querySelector('.Recipe') expect(recipeCard).toHaveClass('can-be-made') }) test('indicates when recipe cannot be made', () => { const recipe = testRecipe({ ingredients: { 'missing-ingredient': 1 }, }) render(<Recipe {...defaultProps} recipe={recipe} />) const recipeCard = document.querySelector('.Recipe') expect(recipeCard).not.toHaveClass('can-be-made') }) test('renders without description when not provided', () => { const recipe = testRecipe({ description: undefined, }) render(<Recipe {...defaultProps} recipe={recipe} />) expect(screen.getByText('Test Recipe')).toBeInTheDocument() expect(screen.queryByText('A test recipe')).not.toBeInTheDocument() })