> For the complete documentation index, see [llms.txt](https://briebug.gitbook.io/ngrx-workshop/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://briebug.gitbook.io/ngrx-workshop/testing/testing-reducers.md).

# Testing Reducers

```typescript
import {
  User,
  generateUser,
  generateUserMap,
  generateUserArray
} from './user.model';
import * as actions from './user.actions';
import {
  userReducer,
  initialUserState,
  getSelectedId,
  getLoading,
  getError,
  getQuery
} from './user.reducer';
import { Update } from '@ngrx/entity';

const INITIAL_STATE_WITH_ERROR = {
  ...initialUserState,
  error: 'some error'
};
const BLANK_ERROR_MESSAGE = '';

describe('userReducer', () => {
  describe('upon an undefined action', () => {
    it('should return the default state upon an undefined action', () => {
      const action = { type: 'NOT DEFINED' } as any;

      expect(userReducer(initialUserState, action)).toEqual(initialUserState);
    });
  });

  describe('upon CreateUser', () => {
    it('should set loading to true and clear any error', () => {
      const action = new actions.CreateUser({ user: generateUser() });

      expect(userReducer(INITIAL_STATE_WITH_ERROR, action)).toEqual({
        ...initialUserState,
        loading: true,
        error: BLANK_ERROR_MESSAGE
      });
    });
  });

  describe('upon CreateUserSuccess', () => {
    it('should add the given User, set loading to false, and clear any error', () => {
      const result = generateUser();
      const action = new actions.CreateUserSuccess({ result });

      expect(userReducer(INITIAL_STATE_WITH_ERROR, action)).toEqual({
        ...initialUserState,
        ...generateUserMap([result]),
        loading: false,
        error: BLANK_ERROR_MESSAGE
      });
    });
  });

  describe('upon CreateUserFail', () => {
    it('should set loading to true and echo the error', () => {
      const error = 'test create error';
      const action = new actions.CreateUserFail({ error });

      expect(userReducer(initialUserState, action)).toEqual({
        ...initialUserState,
        loading: false,
        error: `User create failed: ${error}`
      });
    });
  });

  describe('upon SearchAllUserEntities', () => {
    it('should remove User entities, set loading to true, and clear any error', () => {
      const initialUserStateWithUserEntities = {
        ...INITIAL_STATE_WITH_ERROR,
        ...generateUserMap()
      };
      const action = new actions.SearchAllUserEntities();

      expect(userReducer(initialUserStateWithUserEntities, action)).toEqual({
        ...initialUserState,
        loading: true,
        error: BLANK_ERROR_MESSAGE
      });
    });
  });

  describe('upon SearchAllUserEntitiesSuccess', () => {
    it('should add User entities, set loading to false, and clear any error', () => {
      const result = generateUserArray();
      const action = new actions.SearchAllUserEntitiesSuccess({ result });

      expect(userReducer(INITIAL_STATE_WITH_ERROR, action)).toEqual({
        ...initialUserState,
        ...generateUserMap(result),
        loading: false,
        error: BLANK_ERROR_MESSAGE
      });
    });
  });

  describe('upon SearchAllUserEntitiesFail', () => {
    it('should set loading to false and echo the error', () => {
      const error = 'test search error';
      const action = new actions.SearchAllUserEntitiesFail({ error });

      expect(userReducer(initialUserState, action)).toEqual({
        ...initialUserState,
        loading: false,
        error: `User search failed: ${error}`
      });
    });
  });

  describe('upon LoadUserById', () => {
    it('should remove user entities, set selected id, and clear any error', () => {
      const id = 8675309;
      const initialUserStateWithUserEntities = {
        ...INITIAL_STATE_WITH_ERROR,
        ...generateUserMap()
      };
      const action = new actions.LoadUserById({ id });

      expect(userReducer(initialUserStateWithUserEntities, action)).toEqual({
        ...initialUserState,
        selectedId: id,
        loading: true,
        error: BLANK_ERROR_MESSAGE
      });
    });
  });

  describe('upon LoadUserByIdSuccess', () => {
    it('should add the given User, set loading to false, and clear any error', () => {
      const result = generateUser();
      const action = new actions.LoadUserByIdSuccess({ result });

      expect(userReducer(INITIAL_STATE_WITH_ERROR, action)).toEqual({
        ...initialUserState,
        ...generateUserMap([result]),
        loading: false,
        error: BLANK_ERROR_MESSAGE
      });
    });
  });

  describe('upon LoadUserByIdFail', () => {
    it('should set loading to false and echo the error', () => {
      const error = 'test load by id error';
      const action = new actions.LoadUserByIdFail({ error });

      expect(userReducer(initialUserState, action)).toEqual({
        ...initialUserState,
        loading: false,
        error: `User load failed: ${error}`
      });
    });
  });

  describe('upon UpdateUser', () => {
    it('should set loading to true and clear any errior', () => {
      const user = generateUser();
      const action = new actions.UpdateUser({ user });

      expect(userReducer(INITIAL_STATE_WITH_ERROR, action)).toEqual({
        ...initialUserState,
        loading: true,
        error: BLANK_ERROR_MESSAGE
      });
    });
  });

  describe('upon UpdateUserSuccess', () => {
    it('should add the given User, set loading to false, and clear any error', () => {
      const user = generateUser();
      const initialUserStateWithUser = {
        ...INITIAL_STATE_WITH_ERROR,
        ...generateUserMap([user])
      };
      const updatedUser = {
        ...user,
        name: user.name + ' EDITED',
        description: user.description + ' EDITED'
      };
      const update = {
        id: updatedUser.id,
        changes: updatedUser
      } as Update<User>;
      const action = new actions.UpdateUserSuccess({ update });

      expect(userReducer(initialUserStateWithUser, action)).toEqual({
        ...initialUserStateWithUser,
        ...generateUserMap([updatedUser]),
        loading: false,
        error: BLANK_ERROR_MESSAGE
      });
    });
  });

  describe('upon UpdateUserFail', () => {
    it('should set loading to false and echo the error', () => {
      const error = 'test update error';
      const action = new actions.UpdateUserFail({ error });

      expect(userReducer(initialUserState, action)).toEqual({
        ...initialUserState,
        loading: false,
        error: `User update failed: ${error}`
      });
    });
  });

  describe('upon DeleteUserById', () => {
    it('should set the id, set loading to true, and clear any error', () => {
      const id = 4815162342;
      const action = new actions.DeleteUserById({ id });

      expect(userReducer(INITIAL_STATE_WITH_ERROR, action)).toEqual({
        ...initialUserState,
        selectedId: id,
        loading: true,
        error: BLANK_ERROR_MESSAGE
      });
    });
  });

  describe('upon DeleteUserByIdSuccess', () => {
    it('should remove the id-given user, set loading to false, and clear any error', () => {
      const id = 18009453669;
      const userToBeRemoved = generateUser(id);
      const expectedUserEntities = generateUserArray();
      const userEntitiesWithUserToBeRemoved = [
        ...expectedUserEntities,
        userToBeRemoved
      ];
      const initialUserStateWithAllUserEntities = {
        ...INITIAL_STATE_WITH_ERROR,
        ...generateUserMap(userEntitiesWithUserToBeRemoved)
      };
      const action = new actions.DeleteUserByIdSuccess({ id });

      expect(
        userReducer(initialUserStateWithAllUserEntities, action)
      ).toEqual({
        ...initialUserStateWithAllUserEntities,
        ...generateUserMap(expectedUserEntities),
        loading: false,
        error: BLANK_ERROR_MESSAGE
      });
    });
  });

  describe('upon DeleteUserByIdFail', () => {
    it('should set loading to false and echo the error', () => {
      const error = 'test delete error';
      const action = new actions.DeleteUserByIdFail({ error });

      expect(userReducer(initialUserState, action)).toEqual({
        ...initialUserState,
        loading: false,
        error: `User delete failed: ${error}`
      });
    });
  });

  describe('upon SetSearchQuery', () => {
    it('should set the query', () => {
      const query = {
        filter: 'someFilter',
        sorting: 'someSort',
        limit: 1000000000000,
        page: 888888
      };
      const action = new actions.SetSearchQuery(query);

      expect(userReducer(initialUserState, action)).toEqual({
        ...initialUserState,
        query
      });
    });
  });

  describe('upon SelectUserById', () => {
    it('should set the id and clear any error', () => {
      const id = 73;
      const action = new actions.SelectUserById({ id });

      expect(userReducer(INITIAL_STATE_WITH_ERROR, action)).toEqual({
        ...initialUserState,
        selectedId: id,
        error: BLANK_ERROR_MESSAGE
      });
    });
  });
});

describe('getters', () => {
  describe('getSelectedId', () => {
    it('should return the selected id', () => {
      expect(getSelectedId(initialUserState)).toEqual(initialUserState.selectedId);
    });
  });
  describe('getLoading', () => {
    it('should return the selected id', () => {
      expect(getLoading(initialUserState)).toEqual(initialUserState.loading);
    });
  });
  describe('getError', () => {
    it('should return the selected id', () => {
      expect(getError(INITIAL_STATE_WITH_ERROR))
        .toEqual(INITIAL_STATE_WITH_ERROR.error);
    });
  });
  describe('getQuery', () => {
    it('should return the selected id', () => {
      expect(getQuery(initialUserState))
        .toEqual(initialUserState.query);
    });
  });
});

```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://briebug.gitbook.io/ngrx-workshop/testing/testing-reducers.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
