Skip to content

Commit

Permalink
fix: unit test, and small bug fixes found in unit test
Browse files Browse the repository at this point in the history
Missing unit test, and fixed bug in entitiesSelected() of withEntitiesMultiSelection
  • Loading branch information
Gabriel Guerrero authored and gabrielguerrero committed Apr 19, 2024
1 parent 061a9b1 commit 6138fd1
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,9 @@ import {
export function withEntitiesRemoteFilter<
Entity extends { id: string | number },
Filter extends Record<string, unknown>,
>(options: {
>(config: {
defaultFilter: Filter;
entity: Entity;
entity?: Entity;
}): SignalStoreFeature<
{
state: EntityState<Entity>;
Expand Down Expand Up @@ -198,9 +198,9 @@ export function withEntitiesRemoteFilter<
Entity extends { id: string | number },
Collection extends string,
Filter extends Record<string, unknown>,
>(options: {
>(config: {
defaultFilter: Filter;
entity: Entity;
entity?: Entity;
collection?: Collection;
}): SignalStoreFeature<
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { withEntitiesMultiSelection } from '@ngrx-traits/signals';
import { patchState, signalStore, type } from '@ngrx/signals';
import { setAllEntities, withEntities } from '@ngrx/signals/entities';

import { mockProducts } from '../test.mocks';
import { Product } from '../test.model';

describe('withEntitiesMultiSelection', () => {
const entity = type<Product>();

describe('without collection', () => {
const Store = signalStore(
withEntities({ entity }),
withEntitiesMultiSelection({ entity }),
);
it('selectEntities should select the entity', () => {
const store = new Store();
patchState(store, setAllEntities(mockProducts));
store.selectEntities({ ids: [mockProducts[4].id, mockProducts[8].id] });
expect(store.entitiesSelected()).toEqual([
mockProducts[4],
mockProducts[8],
]);
});

it('deselectEntities should deselect the entity', () => {
const store = new Store();
patchState(store, setAllEntities(mockProducts));
store.selectEntities({ ids: [mockProducts[4].id, mockProducts[8].id] });
store.deselectEntities({ ids: [mockProducts[4].id, mockProducts[8].id] });
expect(store.entitiesSelected()).toEqual([]);
});

it('toggleSelectEntities should toggle selection of the entity', () => {
const store = new Store();
patchState(store, setAllEntities(mockProducts));
store.toggleSelectEntities({ id: mockProducts[4].id });
expect(store.entitiesSelected()).toEqual([mockProducts[4]]);
store.toggleSelectEntities({ id: mockProducts[4].id });
expect(store.entitiesSelected()).toEqual([]);
});

it('toggleSelectAllEntities should toggle selection of the entity', () => {
const store = new Store();
patchState(store, setAllEntities(mockProducts));
store.toggleSelectAllEntities();
expect(store.entitiesSelected().length).toEqual(mockProducts.length);
store.toggleSelectAllEntities();
expect(store.entitiesSelected()).toEqual([]);
});

it('isAllEntitiesSelected should toggle selection of the entity', () => {
const store = new Store();
patchState(store, setAllEntities(mockProducts));
store.toggleSelectAllEntities();
expect(store.isAllEntitiesSelected()).toEqual('all');
store.toggleSelectAllEntities();
expect(store.isAllEntitiesSelected()).toEqual('none');
store.toggleSelectEntities({ ids: mockProducts.map((p) => p.id) });
expect(store.isAllEntitiesSelected()).toEqual('all');
store.toggleSelectEntities({ id: mockProducts[4].id });
expect(store.isAllEntitiesSelected()).toEqual('some');
});
});

describe('with collection', () => {
const collection = 'products';
const Store = signalStore(
withEntities({ entity, collection }),
withEntitiesMultiSelection({ entity, collection }),
);
it('select[Collection]Entities should select the entity', () => {
const store = new Store();
patchState(store, setAllEntities(mockProducts, { collection }));
store.selectProductsEntities({
ids: [mockProducts[4].id, mockProducts[8].id],
});
expect(store.productsSelectedEntities()).toEqual([
mockProducts[4],
mockProducts[8],
]);
});

it('deselect[Collection]Entities should deselect the entity', () => {
const store = new Store();
patchState(store, setAllEntities(mockProducts, { collection }));
store.selectProductsEntities({
ids: [mockProducts[4].id, mockProducts[8].id],
});
store.deselectProductsEntities({
ids: [mockProducts[4].id, mockProducts[8].id],
});
expect(store.productsSelectedEntities()).toEqual([]);
});

it('toggle[Collection]Entities should toggle selection of the entity', () => {
const store = new Store();
patchState(store, setAllEntities(mockProducts, { collection }));
store.toggleSelectProductsEntities({ id: mockProducts[4].id });
expect(store.productsSelectedEntities()).toEqual([mockProducts[4]]);
store.toggleSelectProductsEntities({ id: mockProducts[4].id });
expect(store.productsSelectedEntities()).toEqual([]);
});

it('isAll[Collection]Selected should toggle selection of the entity', () => {
const store = new Store();
patchState(store, setAllEntities(mockProducts, { collection }));
store.toggleSelectAllProductsEntities();
expect(store.isAllProductsSelected()).toEqual('all');
store.toggleSelectAllProductsEntities();
expect(store.isAllProductsSelected()).toEqual('none');
store.toggleSelectProductsEntities({
ids: mockProducts.map((p) => p.id),
});
expect(store.isAllProductsSelected()).toEqual('all');
store.toggleSelectProductsEntities({ id: mockProducts[4].id });
expect(store.isAllProductsSelected()).toEqual('some');
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,17 @@ export function withEntitiesMultiSelection<
const selectedIdsMap = state[selectedIdsMapKey] as Signal<
Record<string | number, boolean>
>;
const selectedIdsArray = computed(() => Object.keys(selectedIdsMap()));
const selectedIdsArray = computed(() =>
Object.entries(selectedIdsMap()).reduce(
(aux, [id, selected]) => {
if (selected) {
aux.push(id);
}
return aux;
},
[] as (string | number)[],
),
);
return {
[selectedEntitiesKey]: computed(() => {
return selectedIdsArray().map((id) => entityMap()[id]);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { withEntitiesSingleSelection } from '@ngrx-traits/signals';
import { patchState, signalStore, type } from '@ngrx/signals';
import { setAllEntities, withEntities } from '@ngrx/signals/entities';

import { mockProducts } from '../test.mocks';
import { Product } from '../test.model';

describe('withEntitiesSingleSelection', () => {
const entity = type<Product>();

describe('without collection', () => {
const Store = signalStore(
withEntities({ entity }),
withEntitiesSingleSelection({ entity }),
);
it('selectEntity should select the entity', () => {
const store = new Store();
patchState(store, setAllEntities(mockProducts));
store.selectEntity({ id: mockProducts[4].id });
expect(store.entitiesSelectedEntity()).toEqual(mockProducts[4]);
});

it('deselectEntity should deselect the entity', () => {
const store = new Store();
patchState(store, setAllEntities(mockProducts));
store.selectEntity({ id: mockProducts[4].id });
store.deselectEntity({ id: mockProducts[4].id });
expect(store.entitiesSelectedEntity()).toEqual(undefined);
});

it('toggleEntity should toggle selection of the entity', () => {
const store = new Store();
patchState(store, setAllEntities(mockProducts));
store.toggleEntity({ id: mockProducts[4].id });
expect(store.entitiesSelectedEntity()).toEqual(mockProducts[4]);
store.toggleEntity({ id: mockProducts[4].id });
expect(store.entitiesSelectedEntity()).toEqual(undefined);
});
});

describe('with collection', () => {
const collection = 'products';
const Store = signalStore(
withEntities({ entity, collection }),
withEntitiesSingleSelection({ entity, collection }),
);
it('selectEntity should select the entity', () => {
const store = new Store();
patchState(store, setAllEntities(mockProducts, { collection }));
store.selectProductsEntity({ id: mockProducts[4].id });
expect(store.productsSelectedEntity()).toEqual(mockProducts[4]);
});

it('deselectEntity should deselect the entity', () => {
const store = new Store();
patchState(store, setAllEntities(mockProducts, { collection }));
store.selectProductsEntity({ id: mockProducts[4].id });
store.deselectProductsEntity({ id: mockProducts[4].id });
expect(store.productsSelectedEntity()).toEqual(undefined);
});

it('toggleEntity should toggle selection of the entity', () => {
const store = new Store();
patchState(store, setAllEntities(mockProducts, { collection }));
store.toggleProductsEntity({ id: mockProducts[4].id });
expect(store.productsSelectedEntity()).toEqual(mockProducts[4]);
store.toggleProductsEntity({ id: mockProducts[4].id });
expect(store.productsSelectedEntity()).toEqual(undefined);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ function getEntitiesSingleSelectionKeys(config?: { collection?: string }) {

export function withEntitiesSingleSelection<
Entity extends { id: string | number },
>(config: {
>(config?: {
entity?: Entity;
}): SignalStoreFeature<
{
Expand Down Expand Up @@ -127,7 +127,7 @@ export function withEntitiesSingleSelection<
export function withEntitiesSingleSelection<
Entity extends { id: string | number },
Collection extends string,
>(config: {
>(config?: {
entity?: Entity;
collection?: Collection;
}): SignalStoreFeature<
Expand All @@ -147,7 +147,7 @@ export function withEntitiesSingleSelection<
export function withEntitiesSingleSelection<
Entity extends { id: string | number },
Collection extends string,
>(config: {
>(config?: {
entity?: Entity;
collection?: Collection;
}): SignalStoreFeature<any, any> {
Expand Down

0 comments on commit 6138fd1

Please sign in to comment.