Skip to content

Commit

Permalink
Added the ability select and deselect comics [#584]
Browse files Browse the repository at this point in the history
  • Loading branch information
mcpierce committed Jan 15, 2021
1 parent ff35d4a commit 6300a1e
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 3 deletions.
13 changes: 13 additions & 0 deletions comixed-web/src/app/library/actions/library.actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,25 @@ export const loadComic = createAction(
'[Library] Load a comic',
props<{ id: number }>()
);

export const comicLoaded = createAction(
'[Library] Loaded a comic',
props<{ comic: Comic }>()
);

export const loadComicFailed = createAction('[Library] Failed to load a comic');

export const updateComics = createAction(
'[Library] Library updates received',
props<{ updated: Comic[]; removed: number[] }>()
);

export const selectComics = createAction(
'[Library] Mark a set of comics as selected',
props<{ comics: Comic[] }>()
);

export const deselectComics = createAction(
'[Library] Unmark a set of comics as selected',
props<{ comics: Comic[] }>()
);
64 changes: 63 additions & 1 deletion comixed-web/src/app/library/reducers/library.reducer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ import { initialState, LibraryState, reducer } from './library.reducer';
import { COMIC_1, COMIC_2, COMIC_3 } from '@app/library/library.fixtures';
import {
comicLoaded,
deselectComics,
loadComic,
loadComicFailed,
selectComics,
updateComics
} from '@app/library/actions/library.actions';
import { Comic } from '@app/library';
Expand Down Expand Up @@ -49,9 +51,13 @@ describe('Library Reducer', () => {
expect(state.comic).toBeNull();
});

it('has an empty collection of comics', () => {
it('has no comics', () => {
expect(state.comics).toEqual([]);
});

it('has no selected comic', () => {
expect(state.selected).toEqual([]);
});
});

describe('loading a comic', () => {
Expand Down Expand Up @@ -126,4 +132,60 @@ describe('Library Reducer', () => {
expect(state.comics).not.toContain(REMOVED_COMIC);
});
});

describe('selecting comics', () => {
beforeEach(() => {
state = reducer(
{ ...state, selected: [] },
selectComics({ comics: COMICS })
);
});

it('sets the selected comics', () => {
expect(state.selected).toEqual(COMICS);
});

describe('reselecting the same comic', () => {
beforeEach(() => {
state = reducer(
{ ...state, selected: COMICS },
selectComics({ comics: COMICS })
);
});

it('does not reselect the same comics', () => {
expect(state.selected).toEqual(COMICS);
});
});
});

describe('deselecting comics', () => {
beforeEach(() => {
state = reducer(
{ ...state, selected: COMICS },
deselectComics({ comics: [COMIC] })
);
});

it('removes the deselected comics', () => {
expect(state.selected).not.toContain(COMIC);
});

it('leaves the remaining comics selected', () => {
expect(state.selected).not.toEqual([]);
});

describe('deselecting all comics', () => {
beforeEach(() => {
state = reducer(
{ ...state, selected: COMICS },
deselectComics({ comics: COMICS })
);
});

it('clears the selected comics', () => {
expect(state.selected).toEqual([]);
});
});
});
});
20 changes: 19 additions & 1 deletion comixed-web/src/app/library/reducers/library.reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
import { createReducer, on } from '@ngrx/store';
import {
comicLoaded,
deselectComics,
loadComic,
loadComicFailed,
selectComics,
updateComics
} from '../actions/library.actions';
import { Comic } from '@app/library';
Expand All @@ -31,12 +33,14 @@ export interface LibraryState {
loading: boolean;
comic: Comic;
comics: Comic[];
selected: Comic[];
}

export const initialState: LibraryState = {
loading: false,
comic: null,
comics: []
comics: [],
selected: []
};

export const reducer = createReducer(
Expand All @@ -62,5 +66,19 @@ export const reducer = createReducer(
);

return { ...state, comics };
}),
on(selectComics, (state, action) => {
const selected = state.selected.filter(
comic => action.comics.includes(comic) === false
);

return { ...state, selected: selected.concat(action.comics) };
}),
on(deselectComics, (state, action) => {
const selected = state.selected.filter(
comic => action.comics.includes(comic) === false
);

return { ...state, selected };
})
);
15 changes: 14 additions & 1 deletion comixed-web/src/app/library/selectors/library.selectors.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
selectLibraryState,
selectLocations,
selectPublishers,
selectSelectedComics,
selectSeries,
selectStories,
selectTeams
Expand All @@ -38,6 +39,7 @@ describe('Library Selectors', () => {
{ ...COMIC_2, publisher: '' },
{ ...COMIC_3, series: '' }
];
const SELECTED_COMICS = [COMIC_1, COMIC_2, COMIC_3];
const PUBLISHERS = [
COMIC_1.publisher,
'library.label.no-publisher',
Expand All @@ -58,7 +60,12 @@ describe('Library Selectors', () => {
let state: LibraryState;

beforeEach(() => {
state = { loading: Math.random() > 0.5, comic: COMIC, comics: COMICS };
state = {
loading: Math.random() > 0.5,
comic: COMIC,
comics: COMICS,
selected: SELECTED_COMICS
};
});

it('selects the feature state', () => {
Expand All @@ -77,6 +84,12 @@ describe('Library Selectors', () => {
).toEqual(state.comic);
});

it('selects the selected comics', () => {
expect(selectSelectedComics({ [LIBRARY_FEATURE_KEY]: state })).toEqual(
SELECTED_COMICS
);
});

it('selects the busy state', () => {
expect(
selectLibraryBusy({
Expand Down
6 changes: 6 additions & 0 deletions comixed-web/src/app/library/selectors/library.selectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ export const selectComic = createSelector(
state => state.comic
);

/** Selects the selected comics. */
export const selectSelectedComics = createSelector(
selectLibraryState,
state => state.selected
);

/** Selects if the feature is current busy. */
export const selectLibraryBusy = createSelector(
selectLibraryState,
Expand Down

0 comments on commit 6300a1e

Please sign in to comment.