UNPKG

@jeremyckahn/farmhand

Version:
362 lines (329 loc) 11.5 kB
import { testCrop } from '../../test-utils/index.js' import { RAIN_MESSAGE, STORM_MESSAGE, STORM_DESTROYS_SCARECROWS_MESSAGE, LIGHTNING_ROD_STRUCK_MESSAGE, LIGHTNING_ROD_DESTROYED_MESSAGE, LIGHTNING_ROD_REPLANTED_MESSAGE, } from '../../strings.js' import { SCARECROW_ITEM_ID } from '../../constants.js' import { fertilizerType } from '../../enums.js' import { getPlotContentFromItemId } from '../../utils/getPlotContentFromItemId.js' import { saveDataStubFactory } from '../../test-utils/stubs/saveDataStubFactory.js' import { applyPrecipitation } from './applyPrecipitation.js' const LIGHTNING_ROD_ITEM_ID = 'sample-lightning-rod-1' vitest.mock('../../data/maps.js') vitest.mock('../../data/items.js') describe('applyPrecipitation', () => { test('waters all plots', () => { const state = applyPrecipitation( saveDataStubFactory({ field: [ [ testCrop({ wasWateredToday: false, }), testCrop({ wasWateredToday: false, }), ], ], inventory: [], newDayNotifications: [], }) ) expect(state.field[0][0]?.wasWateredToday).toBe(true) expect(state.field[0][1]?.wasWateredToday).toBe(true) }) describe('rain shower', () => { test('waters all plots', () => { vitest.spyOn(Math, 'random').mockReturnValue(1) const state = applyPrecipitation( saveDataStubFactory({ field: [[]], inventory: [], newDayNotifications: [], }) ) expect(state.newDayNotifications[0]).toEqual({ message: RAIN_MESSAGE, severity: 'info', }) }) }) describe('storm', () => { beforeEach(() => { vitest.spyOn(Math, 'random').mockReturnValue(0) }) describe('lightning rod is planted', () => { describe('rod has not reached its strike capacity', () => { test('accumulates a strike and survives', () => { const state = applyPrecipitation( saveDataStubFactory({ field: [ [ { itemId: LIGHTNING_ROD_ITEM_ID, fertilizerType: fertilizerType.NONE, lightningStrikesSustained: 0, }, ], ], inventory: [], newDayNotifications: [], }) ) expect(state.field[0][0]).toEqual({ itemId: LIGHTNING_ROD_ITEM_ID, fertilizerType: fertilizerType.NONE, lightningStrikesSustained: 1, }) expect(state.newDayNotifications[0]).toEqual({ message: LIGHTNING_ROD_STRUCK_MESSAGE, severity: 'info', }) }) }) describe('rod reaches its strike capacity', () => { test('is destroyed and refunds ore', () => { const state = applyPrecipitation( saveDataStubFactory({ field: [ [ { itemId: LIGHTNING_ROD_ITEM_ID, fertilizerType: fertilizerType.NONE, lightningStrikesSustained: 1, }, ], ], inventory: [], newDayNotifications: [], }) ) expect(state.field[0][0]).toBe(null) expect(state.inventory).toEqual([{ id: 'sample-ore-1', quantity: 2 }]) expect(state.newDayNotifications[0]).toEqual({ message: LIGHTNING_ROD_DESTROYED_MESSAGE, severity: 'error', }) }) describe('rod is rainbow fertilized', () => { test('is replanted from inventory instead of being destroyed', () => { const state = applyPrecipitation( saveDataStubFactory({ field: [ [ { itemId: LIGHTNING_ROD_ITEM_ID, fertilizerType: fertilizerType.RAINBOW, lightningStrikesSustained: 1, }, ], ], inventory: [{ id: LIGHTNING_ROD_ITEM_ID, quantity: 1 }], newDayNotifications: [], }) ) expect(state.field[0][0]).toEqual({ itemId: LIGHTNING_ROD_ITEM_ID, fertilizerType: fertilizerType.RAINBOW, lightningStrikesSustained: 0, }) expect(state.inventory).toEqual([]) expect(state.newDayNotifications[0]).toEqual({ message: LIGHTNING_ROD_REPLANTED_MESSAGE, severity: 'success', }) }) describe('no spare rod is available in inventory', () => { test('is destroyed and refunds ore as usual', () => { const state = applyPrecipitation( saveDataStubFactory({ field: [ [ { itemId: LIGHTNING_ROD_ITEM_ID, fertilizerType: fertilizerType.RAINBOW, lightningStrikesSustained: 1, }, ], ], inventory: [], newDayNotifications: [], }) ) expect(state.field[0][0]).toBe(null) expect(state.inventory).toEqual([ { id: 'sample-ore-1', quantity: 2 }, ]) expect(state.newDayNotifications[0]).toEqual({ message: LIGHTNING_ROD_DESTROYED_MESSAGE, severity: 'error', }) }) }) }) }) describe('multiple rods are planted', () => { test('every rod is struck, not just one', () => { const state = applyPrecipitation( saveDataStubFactory({ field: [ [ { itemId: LIGHTNING_ROD_ITEM_ID, fertilizerType: fertilizerType.NONE, lightningStrikesSustained: 0, }, { itemId: LIGHTNING_ROD_ITEM_ID, fertilizerType: fertilizerType.NONE, lightningStrikesSustained: 0, }, ], ], inventory: [], newDayNotifications: [], }) ) expect(state.field[0][0]).toEqual({ itemId: LIGHTNING_ROD_ITEM_ID, fertilizerType: fertilizerType.NONE, lightningStrikesSustained: 1, }) expect(state.field[0][1]).toEqual({ itemId: LIGHTNING_ROD_ITEM_ID, fertilizerType: fertilizerType.NONE, lightningStrikesSustained: 1, }) }) describe('more rods reach capacity than there are spares to replant them', () => { test('the shared spare pool is only consumed once per available unit', () => { const state = applyPrecipitation( saveDataStubFactory({ field: [ [ { itemId: LIGHTNING_ROD_ITEM_ID, fertilizerType: fertilizerType.RAINBOW, lightningStrikesSustained: 1, }, { itemId: LIGHTNING_ROD_ITEM_ID, fertilizerType: fertilizerType.RAINBOW, lightningStrikesSustained: 1, }, ], ], inventory: [{ id: LIGHTNING_ROD_ITEM_ID, quantity: 1 }], newDayNotifications: [], }) ) // One rod is replanted using the single spare in inventory... expect(state.field[0][0]).toEqual({ itemId: LIGHTNING_ROD_ITEM_ID, fertilizerType: fertilizerType.RAINBOW, lightningStrikesSustained: 0, }) // ...but the other has no spare left, so it's destroyed normally. expect(state.field[0][1]).toBe(null) expect(state.inventory).toEqual([ { id: 'sample-ore-1', quantity: 2 }, ]) }) }) }) describe('a scarecrow is also planted', () => { test('the scarecrow is protected instead of being destroyed', () => { const state = applyPrecipitation( saveDataStubFactory({ field: [ [ { itemId: LIGHTNING_ROD_ITEM_ID, fertilizerType: fertilizerType.NONE, lightningStrikesSustained: 0, }, getPlotContentFromItemId(SCARECROW_ITEM_ID), ], ], inventory: [], newDayNotifications: [], }) ) expect(state.field[0][1]).toEqual( getPlotContentFromItemId(SCARECROW_ITEM_ID) ) expect(state.newDayNotifications[0]).toEqual({ message: LIGHTNING_ROD_STRUCK_MESSAGE, severity: 'info', }) }) }) }) describe('scarecrows are planted', () => { test('scarecrows are destroyed', () => { const state = applyPrecipitation( saveDataStubFactory({ field: [[getPlotContentFromItemId(SCARECROW_ITEM_ID)]], inventory: [], newDayNotifications: [], }) ) expect(state.field[0][0]).toBe(null) expect(state.newDayNotifications[0]).toEqual({ message: STORM_DESTROYS_SCARECROWS_MESSAGE, severity: 'error', }) }) describe('scarecows are rainbow fertilized', () => { test('scarecrows are replaced based on available inventory', () => { const { field, inventory } = applyPrecipitation( saveDataStubFactory({ field: [ [ { ...getPlotContentFromItemId(SCARECROW_ITEM_ID), fertilizerType: fertilizerType.RAINBOW, }, { ...getPlotContentFromItemId(SCARECROW_ITEM_ID), fertilizerType: fertilizerType.RAINBOW, }, ], ], inventory: [{ id: 'scarecrow', quantity: 1 }], newDayNotifications: [], }) ) // Scarecrow is replanted from inventory expect(field[0][0]).toEqual({ ...getPlotContentFromItemId(SCARECROW_ITEM_ID), fertilizerType: fertilizerType.RAINBOW, }) // Scarecrow replacement was not available expect(field[0][1]).toBe(null) // Scarecrow inventory is consumed expect(inventory).toEqual([]) }) }) }) describe('scarecrows are not planted', () => { test('shows appropriate message', () => { const state = applyPrecipitation( saveDataStubFactory({ field: [[]], inventory: [], newDayNotifications: [], }) ) expect(state.newDayNotifications[0]).toEqual({ message: STORM_MESSAGE, severity: 'info', }) }) }) }) })