Lists: use separate add/remove functions instead of toggle

This commit is contained in:
2026-03-13 13:06:42 +04:00
parent c5c999ac79
commit d459a12115
2 changed files with 145 additions and 22 deletions

View File

@@ -48,10 +48,39 @@ describe('Places Module', () => {
const id = 'some-id';
const geohash = 'u33dc0'; // u3/3d/
mockClient.getAll.mockResolvedValue([]);
await places.remove(id, geohash);
expect(mockClient.remove).toHaveBeenCalledWith('u3/3d/some-id');
});
it('cleans up references from lists', async () => {
const id = 'some-id';
const geohash = 'u33dc0';
const mockLists = {
'to-go': {
id: 'to-go',
placeRefs: [{ id: 'some-id', geohash: 'u33dc0' }],
},
'to-do': { id: 'to-do', placeRefs: [] },
};
mockClient.getAll.mockResolvedValue(Object.values(mockLists));
await places.remove(id, geohash);
expect(mockClient.getAll).toHaveBeenCalledWith('_lists/');
// Expect "to-go" to be updated without the reference
expect(mockClient.storeObject).toHaveBeenCalledWith(
'list',
'_lists/to-go',
expect.objectContaining({
placeRefs: [],
})
);
});
});
describe('get', () => {
@@ -241,7 +270,7 @@ describe('Places Module', () => {
});
});
describe('togglePlace', () => {
describe('addPlace', () => {
it('adds a place reference when not present', async () => {
const now = '2023-01-03T00:00:00.000Z';
vi.setSystemTime(new Date(now));
@@ -253,7 +282,7 @@ describe('Places Module', () => {
};
mockClient.getObject.mockResolvedValue(list);
await lists.togglePlace('hiking', 'place-123', 'w1q7');
await lists.addPlace('hiking', 'place-123', 'w1q7');
expect(mockClient.storeObject).toHaveBeenCalledWith(
'list',
@@ -267,6 +296,21 @@ describe('Places Module', () => {
vi.useRealTimers();
});
it('does nothing if place is already present', async () => {
const list = {
id: 'hiking',
placeRefs: [{ id: 'place-123', geohash: 'w1q7' }],
updatedAt: 'old-date',
};
mockClient.getObject.mockResolvedValue(list);
await lists.addPlace('hiking', 'place-123', 'w1q7');
expect(mockClient.storeObject).not.toHaveBeenCalled();
});
});
describe('removePlace', () => {
it('removes a place reference when present', async () => {
const now = '2023-01-04T00:00:00.000Z';
vi.setSystemTime(new Date(now));
@@ -278,7 +322,7 @@ describe('Places Module', () => {
};
mockClient.getObject.mockResolvedValue(list);
await lists.togglePlace('hiking', 'place-123', 'w1q7');
await lists.removePlace('hiking', 'place-123');
expect(mockClient.storeObject).toHaveBeenCalledWith(
'list',
@@ -291,35 +335,80 @@ describe('Places Module', () => {
vi.useRealTimers();
});
it('does nothing if place is not present', async () => {
const list = {
id: 'hiking',
placeRefs: [],
updatedAt: 'old-date',
};
mockClient.getObject.mockResolvedValue(list);
await lists.removePlace('hiking', 'place-123');
expect(mockClient.storeObject).not.toHaveBeenCalled();
});
});
describe('initDefaults', () => {
it('creates default lists if they do not exist', async () => {
// Mock getObject to return null for both
it('creates "Want to go" list if missing', async () => {
mockClient.getObject.mockResolvedValue(null);
await lists.initDefaults();
// Should check and create "to-go"
expect(mockClient.getObject).toHaveBeenCalledWith('_lists/to-go');
expect(mockClient.storeObject).toHaveBeenCalledWith(
'list',
'_lists/to-go',
expect.objectContaining({
title: 'Want to go',
id: 'to-go',
color: '#ff00ff',
})
);
});
it('creates "To do" list if missing', async () => {
mockClient.getObject.mockResolvedValue(null);
await lists.initDefaults();
// Should check and create "to-do"
expect(mockClient.getObject).toHaveBeenCalledWith('_lists/to-do');
expect(mockClient.storeObject).toHaveBeenCalledWith(
'list',
'_lists/to-do',
expect.objectContaining({
title: 'To do',
id: 'to-do',
color: '#008000',
})
);
});
it('does not overwrite existing lists', async () => {
// Mock that "to-go" exists but "to-do" does not
mockClient.getObject.mockImplementation(async (path: string) => {
if (path === '_lists/to-go')
return { id: 'to-go', title: 'Existing' };
return null;
});
await lists.initDefaults();
// Should NOT write to-go
expect(mockClient.storeObject).not.toHaveBeenCalledWith(
'list',
'_lists/to-go',
expect.anything()
);
// Should write to-do
expect(mockClient.storeObject).toHaveBeenCalledWith(
'list',
'_lists/to-do',
expect.anything()
);
});
});
});
});