EntityStore: add tests for reducer, improve types, ensure error gets added to state

develop^2
Alex Gleason 2023-03-13 18:34:42 -05:00
rodzic b93a299009
commit 9df2bb4a86
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 7211D1F99744FBB7
3 zmienionych plików z 86 dodań i 5 usunięć

Wyświetl plik

@ -0,0 +1,79 @@
import { entitiesFetchFail, entitiesFetchRequest, importEntities } from '../actions';
import reducer from '../reducer';
import type { EntityCache } from '../types';
interface TestEntity {
id: string
msg: string
}
test('import entities', () => {
const entities: TestEntity[] = [
{ id: '1', msg: 'yolo' },
{ id: '2', msg: 'benis' },
{ id: '3', msg: 'boop' },
];
const action = importEntities(entities, 'TestEntity');
const result = reducer(undefined, action);
const cache = result.TestEntity as EntityCache<TestEntity>;
expect(cache.store['1']!.msg).toBe('yolo');
expect(Object.values(cache.lists).length).toBe(0);
});
test('import entities into a list', () => {
const entities: TestEntity[] = [
{ id: '1', msg: 'yolo' },
{ id: '2', msg: 'benis' },
{ id: '3', msg: 'boop' },
];
const action = importEntities(entities, 'TestEntity', 'thingies');
const result = reducer(undefined, action);
const cache = result.TestEntity as EntityCache<TestEntity>;
expect(cache.store['2']!.msg).toBe('benis');
expect(cache.lists.thingies?.ids.size).toBe(3);
// Now try adding an additional item.
const entities2: TestEntity[] = [
{ id: '4', msg: 'hehe' },
];
const action2 = importEntities(entities2, 'TestEntity', 'thingies');
const result2 = reducer(result, action2);
const cache2 = result2.TestEntity as EntityCache<TestEntity>;
expect(cache2.store['4']!.msg).toBe('hehe');
expect(cache2.lists.thingies?.ids.size).toBe(4);
// Finally, update an item.
const entities3: TestEntity[] = [
{ id: '2', msg: 'yolofam' },
];
const action3 = importEntities(entities3, 'TestEntity', 'thingies');
const result3 = reducer(result2, action3);
const cache3 = result3.TestEntity as EntityCache<TestEntity>;
expect(cache3.store['2']!.msg).toBe('yolofam');
expect(cache3.lists.thingies?.ids.size).toBe(4); // unchanged
});
test('fetching updates the list state', () => {
const action = entitiesFetchRequest('TestEntity', 'thingies');
const result = reducer(undefined, action);
expect(result.TestEntity!.lists.thingies!.state.fetching).toBe(true);
});
test('failure adds the error to the state', () => {
const error = new Error('whoopsie');
const action = entitiesFetchFail('TestEntity', 'thingies', error);
const result = reducer(undefined, action);
expect(result.TestEntity!.lists.thingies!.state.error).toBe(error);
});

Wyświetl plik

@ -48,6 +48,7 @@ const setFetching = (
entityType: string,
listKey: string | undefined,
isFetching: boolean,
error?: any,
) => {
return produce(state, draft => {
const cache = draft[entityType] ?? createCache();
@ -55,6 +56,7 @@ const setFetching = (
if (typeof listKey === 'string') {
const list = cache.lists[listKey] ?? createList();
list.state.fetching = isFetching;
list.state.error = error;
cache.lists[listKey] = list;
}
@ -72,7 +74,7 @@ function reducer(state: Readonly<State> = {}, action: EntityAction): State {
case ENTITIES_FETCH_REQUEST:
return setFetching(state, action.entityType, action.listKey, true);
case ENTITIES_FETCH_FAIL:
return setFetching(state, action.entityType, action.listKey, false);
return setFetching(state, action.entityType, action.listKey, false, action.error);
default:
return state;
}

Wyświetl plik

@ -5,8 +5,8 @@ interface Entity {
}
/** Store of entities by ID. */
interface EntityStore {
[id: string]: Entity | undefined
interface EntityStore<TEntity extends Entity = Entity> {
[id: string]: TEntity | undefined
}
/** List of entity IDs and fetch state. */
@ -32,9 +32,9 @@ interface EntityListState {
}
/** Cache data pertaining to a paritcular entity type.. */
interface EntityCache {
interface EntityCache<TEntity extends Entity = Entity> {
/** Map of entities of this type. */
store: EntityStore
store: EntityStore<TEntity>
/** Lists of entity IDs for a particular purpose. */
lists: {
[listKey: string]: EntityList | undefined