Get all places from a list
This commit is contained in:
@@ -101,6 +101,10 @@ await places.lists.getAll();
|
|||||||
|
|
||||||
// Get specific list
|
// Get specific list
|
||||||
await places.lists.get('to-do');
|
await places.lists.get('to-do');
|
||||||
|
|
||||||
|
// Get all places from a list
|
||||||
|
await places.lists.getPlaces('to-do');
|
||||||
|
```
|
||||||
```
|
```
|
||||||
|
|
||||||
## API Reference
|
## API Reference
|
||||||
|
|||||||
@@ -154,6 +154,13 @@ export interface PlacesClient {
|
|||||||
*/
|
*/
|
||||||
get(id: string): Promise<List | null>;
|
get(id: string): Promise<List | null>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all places from a list.
|
||||||
|
* @param listId - The slug ID of the list.
|
||||||
|
* @returns Array of Place objects.
|
||||||
|
*/
|
||||||
|
getPlaces(listId: string): Promise<Place[]>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create or update a list.
|
* Create or update a list.
|
||||||
* @param id - The slug ID (e.g., "to-go").
|
* @param id - The slug ID (e.g., "to-go").
|
||||||
@@ -249,6 +256,27 @@ const Places = function (
|
|||||||
return privateClient.getObject(path) as Promise<List | null>;
|
return privateClient.getObject(path) as Promise<List | null>;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async getPlaces(listId: string): Promise<Place[]> {
|
||||||
|
const list = await this.get(listId);
|
||||||
|
if (!list) {
|
||||||
|
throw new Error(`List not found: ${listId}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!list.placeRefs || !Array.isArray(list.placeRefs)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
const promises = list.placeRefs.map(async (ref: any) => {
|
||||||
|
if (!ref.id || !ref.geohash) return null;
|
||||||
|
const path = getPath(ref.geohash, ref.id);
|
||||||
|
const place = await privateClient.getObject(path);
|
||||||
|
return place as Place | null;
|
||||||
|
});
|
||||||
|
|
||||||
|
const results = await Promise.all(promises);
|
||||||
|
return results.filter((p): p is Place => !!p);
|
||||||
|
},
|
||||||
|
|
||||||
async create(id: string, title: string, color?: string): Promise<List> {
|
async create(id: string, title: string, color?: string): Promise<List> {
|
||||||
const path = `_lists/${id}`;
|
const path = `_lists/${id}`;
|
||||||
let list = (await privateClient.getObject(path)) as List;
|
let list = (await privateClient.getObject(path)) as List;
|
||||||
|
|||||||
@@ -203,6 +203,64 @@ describe('Places Module', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('getPlaces', () => {
|
||||||
|
it('returns all places from a list', async () => {
|
||||||
|
const mockList = {
|
||||||
|
id: 'hiking',
|
||||||
|
title: 'Hiking',
|
||||||
|
placeRefs: [
|
||||||
|
{ id: 'place-1', geohash: 'u33dc0' },
|
||||||
|
{ id: 'place-2', geohash: 'w1q789' },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockPlace1 = { id: 'place-1', geohash: 'u33dc0', title: 'Hiking Trail' };
|
||||||
|
const mockPlace2 = { id: 'place-2', geohash: 'w1q789', title: 'Mountain Peak' };
|
||||||
|
|
||||||
|
mockClient.getObject.mockImplementation(async (path: string) => {
|
||||||
|
if (path === '_lists/hiking') return mockList;
|
||||||
|
if (path === 'u3/3d/place-1') return mockPlace1;
|
||||||
|
if (path === 'w1/q7/place-2') return mockPlace2;
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await lists.getPlaces('hiking');
|
||||||
|
expect(mockClient.getObject).toHaveBeenCalledWith('_lists/hiking');
|
||||||
|
expect(mockClient.getObject).toHaveBeenCalledWith('u3/3d/place-1');
|
||||||
|
expect(mockClient.getObject).toHaveBeenCalledWith('w1/q7/place-2');
|
||||||
|
expect(result).toEqual([mockPlace1, mockPlace2]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws an error if the list does not exist', async () => {
|
||||||
|
mockClient.getObject.mockResolvedValue(null);
|
||||||
|
|
||||||
|
await expect(lists.getPlaces('non-existent')).rejects.toThrow('List not found: non-existent');
|
||||||
|
expect(mockClient.getObject).toHaveBeenCalledWith('_lists/non-existent');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('filters out any places that failed to load or are missing', async () => {
|
||||||
|
const mockList = {
|
||||||
|
id: 'hiking',
|
||||||
|
title: 'Hiking',
|
||||||
|
placeRefs: [
|
||||||
|
{ id: 'place-1', geohash: 'u33dc0' },
|
||||||
|
{ id: 'place-2', geohash: 'w1q789' },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockPlace1 = { id: 'place-1', geohash: 'u33dc0', title: 'Place 1' };
|
||||||
|
|
||||||
|
mockClient.getObject.mockImplementation(async (path: string) => {
|
||||||
|
if (path === '_lists/hiking') return mockList;
|
||||||
|
if (path === 'u3/3d/place-1') return mockPlace1;
|
||||||
|
return null; // place-2 is missing
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await lists.getPlaces('hiking');
|
||||||
|
expect(result).toEqual([mockPlace1]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('create', () => {
|
describe('create', () => {
|
||||||
it('stores a new list when none exists', async () => {
|
it('stores a new list when none exists', async () => {
|
||||||
const now = '2023-01-01T00:00:00.000Z';
|
const now = '2023-01-01T00:00:00.000Z';
|
||||||
|
|||||||
Reference in New Issue
Block a user