UNPKG

@reduxjs/toolkit

Version:

The official, opinionated, batteries-included toolset for efficient Redux development

84 lines (67 loc) 2.88 kB
import type { EntityAdapter } from '../index' import { createEntityAdapter } from '../index' import type { PayloadAction } from '../../createAction' import { createAction } from '../../createAction' import { createSlice } from '../../createSlice' import type { BookModel } from './fixtures/book' describe('Entity State', () => { let adapter: EntityAdapter<BookModel> beforeEach(() => { adapter = createEntityAdapter({ selectId: (book: BookModel) => book.id, }) }) it('should let you get the initial state', () => { const initialState = adapter.getInitialState() expect(initialState).toEqual({ ids: [], entities: {}, }) }) it('should let you provide additional initial state properties', () => { const additionalProperties = { isHydrated: true } const initialState = adapter.getInitialState(additionalProperties) expect(initialState).toEqual({ ...additionalProperties, ids: [], entities: {}, }) }) it('should allow methods to be passed as reducers', () => { const upsertBook = createAction<BookModel>('otherBooks/upsert') const booksSlice = createSlice({ name: 'books', initialState: adapter.getInitialState(), reducers: { addOne: adapter.addOne, removeOne(state, action: PayloadAction<string>) { // TODO The nested `produce` calls don't mutate `state` here as I would have expected. // TODO (note that `state` here is actually an Immer Draft<S>, from `createReducer`) // TODO However, this works if we _return_ the new plain result value instead // TODO See https://github.com/immerjs/immer/issues/533 const result = adapter.removeOne(state, action) return result }, }, extraReducers: (builder) => { builder.addCase(upsertBook, (state, action) => { return adapter.upsertOne(state, action) }) }, }) const { addOne, removeOne } = booksSlice.actions const { reducer } = booksSlice const selectors = adapter.getSelectors() const book1: BookModel = { id: 'a', title: 'First' } const book1a: BookModel = { id: 'a', title: 'Second' } const afterAddOne = reducer(undefined, addOne(book1)) expect(afterAddOne.entities[book1.id]).toBe(book1) const afterRemoveOne = reducer(afterAddOne, removeOne(book1.id)) expect(afterRemoveOne.entities[book1.id]).toBeUndefined() expect(selectors.selectTotal(afterRemoveOne)).toBe(0) const afterUpsertFirst = reducer(afterRemoveOne, upsertBook(book1)) const afterUpsertSecond = reducer(afterUpsertFirst, upsertBook(book1a)) expect(afterUpsertSecond.entities[book1.id]).toEqual(book1a) expect(selectors.selectTotal(afterUpsertSecond)).toBe(1) }) })