Skip to content

Commit

Permalink
fix(signals): allow modifying entity id on update
Browse files Browse the repository at this point in the history
Closes #4235
  • Loading branch information
markostanimirovic committed Jun 29, 2024
1 parent 1b1cf5b commit 9990abd
Show file tree
Hide file tree
Showing 8 changed files with 591 additions and 52 deletions.
15 changes: 12 additions & 3 deletions modules/signals/entities/spec/updaters/update-all-entities.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,10 @@ describe('updateAllEntities', () => {

patchState(
store,
updateAllEntities({ text: '' }),
updateAllEntities((todo) => ({ completed: !todo.completed }))
updateAllEntities({ text: '' }, { selectId: (todo) => todo._id }),
updateAllEntities((todo) => ({ completed: !todo.completed }), {
selectId: (todo) => todo._id,
})
);

expect(store.entityMap()).toBe(entityMap);
Expand All @@ -79,7 +81,13 @@ describe('updateAllEntities', () => {
collection: 'todo',
selectId: selectTodoId,
}),
updateAllEntities({ completed: false }, { collection: 'todo' })
updateAllEntities(
{ completed: false },
{
collection: 'todo',
selectId: (todo) => todo._id,
}
)
);

expect(store.todoEntityMap()).toEqual({
Expand All @@ -98,6 +106,7 @@ describe('updateAllEntities', () => {
store,
updateAllEntities(({ completed }) => ({ completed: !completed }), {
collection: 'todo',
selectId: (todo) => todo._id,
})
);

Expand Down
247 changes: 239 additions & 8 deletions modules/signals/entities/spec/updaters/update-entities.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,20 @@ describe('updateEntities', () => {

patchState(
store,
updateEntities({
predicate: (todo) => todo.text.startsWith('Buy'),
changes: { completed: false },
}),
updateEntities({
predicate: ({ completed }) => !completed,
changes: ({ text }) => ({ text: `Don't ${text}` }),
})
updateEntities(
{
predicate: (todo) => todo.text.startsWith('Buy'),
changes: { completed: false },
},
{ selectId: (todo) => todo._id }
),
updateEntities(
{
predicate: ({ completed }) => !completed,
changes: ({ text }) => ({ text: `Don't ${text}` }),
},
{ selectId: (todo) => todo._id }
)
);

expect(store.entityMap()).toEqual({
Expand Down Expand Up @@ -228,4 +234,229 @@ describe('updateEntities', () => {
expect(store.todoIds()).toEqual(['x', 'y', 'z']);
expect(store.todoEntities()).toEqual([todo1, todo2, todo3]);
});

it('updates entity ids', () => {
const Store = signalStore(withEntities<User>());
const store = new Store();

patchState(
store,
addEntities([user1, user2, user3]),
updateEntities({
ids: [user1.id, user2.id],
changes: ({ id }) => ({ id: id + 10, firstName: `Jimmy${id}` }),
}),
updateEntities({
ids: [user3.id],
changes: { id: 303, lastName: 'Hendrix' },
})
);

expect(store.entityMap()).toEqual({
11: { ...user1, id: 11, firstName: 'Jimmy1' },
12: { ...user2, id: 12, firstName: 'Jimmy2' },
303: { ...user3, id: 303, lastName: 'Hendrix' },
});
expect(store.ids()).toEqual([11, 12, 303]);

patchState(
store,
updateEntities({
predicate: ({ id }) => id > 300,
changes: ({ id }) => ({ id: id - 300 }),
}),
updateEntities({
predicate: ({ firstName }) => firstName === 'Jimmy1',
changes: { id: 1, firstName: 'Jimmy' },
})
);

expect(store.entityMap()).toEqual({
1: { ...user1, id: 1, firstName: 'Jimmy' },
12: { ...user2, id: 12, firstName: 'Jimmy2' },
3: { ...user3, id: 3, lastName: 'Hendrix' },
});
expect(store.ids()).toEqual([1, 12, 3]);
});

it('updates custom entity ids', () => {
const Store = signalStore(withEntities<Todo>());
const store = new Store();

patchState(
store,
addEntities([todo1, todo2, todo3], { selectId: (todo) => todo._id }),
updateEntities(
{
ids: [todo1._id, todo2._id],
changes: ({ _id }) => ({ _id: _id + 10, text: `Todo ${_id}` }),
},
{ selectId: (todo) => todo._id }
),
updateEntities(
{
ids: [todo3._id],
changes: { _id: 'z30' },
},
{ selectId: (todo) => todo._id }
)
);

expect(store.entityMap()).toEqual({
x10: { ...todo1, _id: 'x10', text: 'Todo x' },
y10: { ...todo2, _id: 'y10', text: 'Todo y' },
z30: { ...todo3, _id: 'z30' },
});
expect(store.ids()).toEqual(['x10', 'y10', 'z30']);

patchState(
store,
updateEntities(
{
predicate: ({ text }) => text.startsWith('Todo '),
changes: ({ _id }) => ({ _id: `${_id}0` }),
},
{ selectId: (todo) => todo._id }
),
updateEntities(
{
predicate: ({ _id }) => _id === 'z30',
changes: { _id: 'z' },
},
{ selectId: (todo) => todo._id }
)
);

expect(store.entityMap()).toEqual({
x100: { ...todo1, _id: 'x100', text: 'Todo x' },
y100: { ...todo2, _id: 'y100', text: 'Todo y' },
z: { ...todo3, _id: 'z' },
});
expect(store.ids()).toEqual(['x100', 'y100', 'z']);
});

it('updates entity ids from specified collection', () => {
const Store = signalStore(
withEntities({
entity: type<User>(),
collection: 'user',
})
);
const store = new Store();

patchState(
store,
addEntities([user1, user2, user3], { collection: 'user' }),
updateEntities(
{
ids: [user1.id, user2.id],
changes: ({ id }) => ({ id: id + 100, firstName: `Jimmy${id}` }),
},
{ collection: 'user' }
),
updateEntities(
{
ids: [user3.id],
changes: { id: 303, lastName: 'Hendrix' },
},
{ collection: 'user' }
)
);

expect(store.userEntityMap()).toEqual({
101: { ...user1, id: 101, firstName: 'Jimmy1' },
102: { ...user2, id: 102, firstName: 'Jimmy2' },
303: { ...user3, id: 303, lastName: 'Hendrix' },
});
expect(store.userIds()).toEqual([101, 102, 303]);

patchState(
store,
updateEntities(
{
predicate: ({ id }) => id > 300,
changes: ({ id }) => ({ id: id - 300 }),
},
{ collection: 'user' }
),
updateEntities(
{
predicate: ({ firstName }) => firstName === 'Jimmy1',
changes: { id: 1, firstName: 'Jimmy' },
},
{ collection: 'user' }
)
);

expect(store.userEntityMap()).toEqual({
1: { ...user1, id: 1, firstName: 'Jimmy' },
102: { ...user2, id: 102, firstName: 'Jimmy2' },
3: { ...user3, id: 3, lastName: 'Hendrix' },
});
expect(store.userIds()).toEqual([1, 102, 3]);
});

it('updates custom entity ids from specified collection', () => {
const Store = signalStore(
withEntities({
entity: type<Todo>(),
collection: 'todo',
})
);
const store = new Store();

patchState(
store,
addEntities([todo1, todo2, todo3], {
collection: 'todo',
selectId: (todo) => todo._id,
}),
updateEntities(
{
ids: [todo1._id, todo2._id],
changes: ({ _id }) => ({ _id: _id + 10, text: `Todo ${_id}` }),
},
{ collection: 'todo', selectId: (todo) => todo._id }
),
updateEntities(
{
ids: [todo3._id],
changes: { _id: 'z30' },
},
{ collection: 'todo', selectId: (todo) => todo._id }
)
);

expect(store.todoEntityMap()).toEqual({
x10: { ...todo1, _id: 'x10', text: 'Todo x' },
y10: { ...todo2, _id: 'y10', text: 'Todo y' },
z30: { ...todo3, _id: 'z30' },
});
expect(store.todoIds()).toEqual(['x10', 'y10', 'z30']);

patchState(
store,
updateEntities(
{
predicate: ({ text }) => text.startsWith('Todo '),
changes: ({ _id }) => ({ _id: `${_id}0` }),
},
{ collection: 'todo', selectId: (todo) => todo._id }
),
updateEntities(
{
predicate: ({ _id }) => _id === 'z30',
changes: { _id: 'z' },
},
{ collection: 'todo', selectId: (todo) => todo._id }
)
);

expect(store.todoEntityMap()).toEqual({
x100: { ...todo1, _id: 'x100', text: 'Todo x' },
y100: { ...todo2, _id: 'y100', text: 'Todo y' },
z: { ...todo3, _id: 'z' },
});
expect(store.todoIds()).toEqual(['x100', 'y100', 'z']);
});
});
Loading

0 comments on commit 9990abd

Please sign in to comment.