source: node_modules/@reduxjs/toolkit/src/entities/tests/entity_state.test.ts

Last change on this file was a762898, checked in by istevanoska <ilinastevanoska@…>, 6 months ago

Added visualizations

  • Property mode set to 100644
File size: 3.3 KB
Line 
1import type { EntityAdapter } from '../index'
2import { createEntityAdapter } from '../index'
3import type { PayloadAction } from '../../createAction'
4import { createAction } from '../../createAction'
5import { createSlice } from '../../createSlice'
6import type { BookModel } from './fixtures/book'
7
8describe('Entity State', () => {
9 let adapter: EntityAdapter<BookModel, string>
10
11 beforeEach(() => {
12 adapter = createEntityAdapter({
13 selectId: (book: BookModel) => book.id,
14 })
15 })
16
17 it('should let you get the initial state', () => {
18 const initialState = adapter.getInitialState()
19
20 expect(initialState).toEqual({
21 ids: [],
22 entities: {},
23 })
24 })
25
26 it('should let you provide additional initial state properties', () => {
27 const additionalProperties = { isHydrated: true }
28
29 const initialState = adapter.getInitialState(additionalProperties)
30
31 expect(initialState).toEqual({
32 ...additionalProperties,
33 ids: [],
34 entities: {},
35 })
36 })
37
38 it('should let you provide initial entities', () => {
39 const book1: BookModel = { id: 'a', title: 'First' }
40
41 const initialState = adapter.getInitialState(undefined, [book1])
42
43 expect(initialState).toEqual({
44 ids: [book1.id],
45 entities: { [book1.id]: book1 },
46 })
47
48 const additionalProperties = { isHydrated: true }
49
50 const initialState2 = adapter.getInitialState(additionalProperties, [book1])
51
52 expect(initialState2).toEqual({
53 ...additionalProperties,
54 ids: [book1.id],
55 entities: { [book1.id]: book1 },
56 })
57 })
58
59 it('should allow methods to be passed as reducers', () => {
60 const upsertBook = createAction<BookModel>('otherBooks/upsert')
61
62 const booksSlice = createSlice({
63 name: 'books',
64 initialState: adapter.getInitialState(),
65 reducers: {
66 addOne: adapter.addOne,
67 removeOne(state, action: PayloadAction<string>) {
68 // TODO The nested `produce` calls don't mutate `state` here as I would have expected.
69 // TODO (note that `state` here is actually an Immer Draft<S>, from `createReducer`)
70 // TODO However, this works if we _return_ the new plain result value instead
71 // TODO See https://github.com/immerjs/immer/issues/533
72 const result = adapter.removeOne(state, action)
73 return result
74 },
75 },
76 extraReducers: (builder) => {
77 builder.addCase(upsertBook, (state, action) => {
78 return adapter.upsertOne(state, action)
79 })
80 },
81 })
82
83 const { addOne, removeOne } = booksSlice.actions
84 const { reducer } = booksSlice
85
86 const selectors = adapter.getSelectors()
87
88 const book1: BookModel = { id: 'a', title: 'First' }
89 const book1a: BookModel = { id: 'a', title: 'Second' }
90
91 const afterAddOne = reducer(undefined, addOne(book1))
92 expect(afterAddOne.entities[book1.id]).toBe(book1)
93
94 const afterRemoveOne = reducer(afterAddOne, removeOne(book1.id))
95 expect(afterRemoveOne.entities[book1.id]).toBeUndefined()
96 expect(selectors.selectTotal(afterRemoveOne)).toBe(0)
97
98 const afterUpsertFirst = reducer(afterRemoveOne, upsertBook(book1))
99 const afterUpsertSecond = reducer(afterUpsertFirst, upsertBook(book1a))
100
101 expect(afterUpsertSecond.entities[book1.id]).toEqual(book1a)
102 expect(selectors.selectTotal(afterUpsertSecond)).toBe(1)
103 })
104})
Note: See TracBrowser for help on using the repository browser.