diff --git a/package.json b/package.json index fa27424a..3478f2a7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@duffel/api", - "version": "3.1.1", + "version": "3.2.0", "description": "Javascript client library for the Duffel API", "main": "dist/index.js", "module": "dist/index.es.js", diff --git a/src/Client.ts b/src/Client.ts index d9718e14..87b9ae9d 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -165,7 +165,10 @@ export class Client { response = await this.request({ method: 'GET', path, - params: { limit: response.meta.limit, after: response.meta.after }, + params: { + ...params, + ...{ limit: response.meta.limit, after: response.meta.after }, + }, }) for (const item of response.data) { yield { data: item } diff --git a/src/Stays/Accommodation/Accommodation.spec.ts b/src/Stays/Accommodation/Accommodation.spec.ts index a85e833a..74564218 100644 --- a/src/Stays/Accommodation/Accommodation.spec.ts +++ b/src/Stays/Accommodation/Accommodation.spec.ts @@ -62,4 +62,101 @@ describe('Stays/Accommodation', () => { const response = await duffel.stays.accommodation.get(id) expect(response.data).toEqual(mockResponse.data) }) + + it('should send GET to /stays/accommodation when `list` is called', async () => { + const mockResponse = { + data: [MOCK_ACCOMMODATION], + meta: { limit: 1, before: null, after: null }, + } + + const params = { + radius: 7, + latitude: 13.5276927, + longitude: 122.1160988, + } + + nock(/(.*)/) + .get(`/stays/accommodation`) + .query((queryObject) => { + expect(parseInt(queryObject.radius as string)).toEqual(params.radius) + expect(parseFloat(queryObject.latitude as string)).toEqual( + params.latitude, + ) + expect(parseFloat(queryObject.longitude as string)).toEqual( + params.longitude, + ) + + return true + }) + .reply(200, mockResponse) + + const response = await duffel.stays.accommodation.list(params) + + expect(response.data).toEqual(mockResponse.data) + expect(response.meta).toEqual(mockResponse.meta) + }) + + it('should send GET to /stays/accommodation when an individual item from `listWithGenerator` is executed', async () => { + const mockFirstPageResponse = { + data: [MOCK_ACCOMMODATION], + meta: { limit: 2, before: null, after: 'next_page_token' }, + } + + const mockLastPageResponse = { + data: [MOCK_ACCOMMODATION], + meta: { limit: 1, before: 'prev_page_token', after: null }, + } + + const params = { + radius: 7, + latitude: 13.5276927, + longitude: 122.1160988, + } + + // First Page expectations + nock(/(.*)/) + .get(`/stays/accommodation`) + .query((queryObject) => { + expect(parseInt(queryObject.radius as string)).toEqual(params.radius) + expect(parseFloat(queryObject.latitude as string)).toEqual( + params.latitude, + ) + expect(parseFloat(queryObject.longitude as string)).toEqual( + params.longitude, + ) + + return true + }) + .reply(200, mockFirstPageResponse) + + // Last Page expectations + nock(/(.*)/) + .get(`/stays/accommodation`) + .query((queryObject) => { + expect(parseInt(queryObject.radius as string)).toEqual(params.radius) + expect(parseFloat(queryObject.latitude as string)).toEqual( + params.latitude, + ) + expect(parseFloat(queryObject.longitude as string)).toEqual( + params.longitude, + ) + + return true + }) + .reply(200, mockLastPageResponse) + + const generator = duffel.stays.accommodation.listWithGenerator(params) + + const firstItem = await generator.next() + expect(firstItem.value.data).toEqual(MOCK_ACCOMMODATION) + expect(firstItem.done).toBe(false) + + const lastItem = await generator.next() + expect(lastItem.value.data).toEqual(MOCK_ACCOMMODATION) + expect(lastItem.done).toBe(false) + + const terminatingItem = await generator.next() + expect(terminatingItem.value).toBeUndefined() + expect(terminatingItem.done).toBe(true) + }) }) diff --git a/src/Stays/Accommodation/Accommodation.ts b/src/Stays/Accommodation/Accommodation.ts index aa2ef17f..2402fdff 100644 --- a/src/Stays/Accommodation/Accommodation.ts +++ b/src/Stays/Accommodation/Accommodation.ts @@ -1,6 +1,7 @@ import { Client } from '../../Client' import { LocationParams, + ListAccommodationParams, StaysAccommodationSuggestion, StaysAccommodation, } from '../StaysTypes' @@ -46,4 +47,31 @@ export class Accommodation extends Resource { method: 'GET', path: `${this.path}/${id}`, }) + + /** + * Retrieves a page of accommodation. + * @param {Object.} params - Endpoint options (radius, latitude, longitude, before, after, limit) + * @link https://duffel.com/docs/api/v2/accommodation/list-accommodation + */ + public list = ( + params: ListAccommodationParams, + ): Promise> => + this.request({ + method: 'GET', + path: this.path, + params: params, + }) + + /** + * Retrieves a generator of accommodation pages given the criteria in the params. + * @param {Object.} params - Endpoint options (radius, latitude, longitude, before, after, limit) + * @link https://duffel.com/docs/api/v2/accommodation/list-accommodation + */ + public listWithGenerator = ( + params: ListAccommodationParams, + ): AsyncGenerator> => + this.paginatedRequest({ + path: this.path, + params: params, + }) } diff --git a/src/Stays/StaysTypes.ts b/src/Stays/StaysTypes.ts index 162b2e6c..95b46720 100644 --- a/src/Stays/StaysTypes.ts +++ b/src/Stays/StaysTypes.ts @@ -1,3 +1,5 @@ +import { PaginationMeta } from './../types' + export type StaysBedType = 'single' | 'double' | 'queen' | 'king' | 'sofabed' export interface StaysBed { @@ -628,10 +630,7 @@ interface CommonStaysSearchParams { export type LocationParams = { radius: number - geographic_coordinates: { - latitude: number - longitude: number - } + geographic_coordinates: GeographicCoordinates } type LocationSearchParams = { @@ -647,6 +646,12 @@ type AccommodationSearchParams = { export type StaysSearchParams = LocationSearchParams | AccommodationSearchParams +export interface ListAccommodationParams extends PaginationMeta { + radius?: LocationParams['radius'] + latitude: GeographicCoordinates['latitude'] + longitude: GeographicCoordinates['longitude'] +} + export interface StaysSearchResult { id: string check_in_date: string