diff --git a/src/DuffelPayments/PaymentIntents/mockPaymentIntents.ts b/src/DuffelPayments/PaymentIntents/mockPaymentIntents.ts index f0178fca..c280af32 100644 --- a/src/DuffelPayments/PaymentIntents/mockPaymentIntents.ts +++ b/src/DuffelPayments/PaymentIntents/mockPaymentIntents.ts @@ -30,6 +30,7 @@ export const mockPaymentIntents: PaymentIntent = { created_at: '2020-04-11T15:48:11.642Z', confirmed_at: '2020-04-11T15:48:11.642Z', client_token: + // eslint-disable-next-line spellcheck/spell-checker 'eyJjbGllbnRfc2VjcmV0IjoicGlfMUl5YTBiQW5rMVRkeXJvRE1iWkJPN0ZSX3NlY3JldF9TbGFrYnJjYnFHZGZha2VrcjdCNE5jZWVyIiwicHVibGlzaGFibGVfa2V5IjoicGtfbGl2ZV81MUl0Q3YwQW5rMUdkeXJvRFlFU3M3RnBTUEdrNG9kbDhneDF3Y1RBNVEzaUcyWEFWVEhxdFlKSVhWMUxoSU5GQUtFMjA1dFdmRGVIcXhwUVdnYkIzTkVFbzAwMmdVY1hzR0YifQ==', card_network: 'visa', card_last_four_digits: '4242', diff --git a/src/booking/Offers/OfferTypes.ts b/src/booking/Offers/OfferTypes.ts index 1692ddac..e8053f2b 100644 --- a/src/booking/Offers/OfferTypes.ts +++ b/src/booking/Offers/OfferTypes.ts @@ -449,3 +449,24 @@ export interface ListOffersParams extends PaginationMeta { */ sort?: 'total_amount' | 'total_duration' } + +export interface LoyaltyProgrammeAccounts { + /** + * The passenger's account number for this Loyalty Programme Account + */ + account_number: string + + /** + * The IATA code for the airline that this Loyalty Programme Account belongs to + */ + airline_iata_code: string +} + +export interface UpdateOffer { + type: string + loyalty_programme_accounts: LoyaltyProgrammeAccounts + id: string + given_name: string + family_name: string + age: number +} diff --git a/src/booking/Offers/Offers.spec.ts b/src/booking/Offers/Offers.spec.ts index 87f2e7db..dc3aab76 100644 --- a/src/booking/Offers/Offers.spec.ts +++ b/src/booking/Offers/Offers.spec.ts @@ -1,8 +1,10 @@ import nock from 'nock' import { Client } from '../../Client' -import { mockOffer } from './mockOffer' +import { Duffel } from '../../index' +import { mockOffer, mockUpdatedOffer } from './mockOffer' import { Offers } from './Offers' +const duffel = new Duffel({ token: 'mockToken' }) describe('offers', () => { afterEach(() => { nock.cleanAll() @@ -13,9 +15,7 @@ describe('offers', () => { .get(`/air/offers/${mockOffer.id}`) .reply(200, { data: { ...mockOffer, available_services: [] } }) - const response = await new Offers(new Client({ token: 'mockToken' })).get( - mockOffer.id - ) + const response = await duffel.offers.get(mockOffer.id) expect(response.data?.id).toBe(mockOffer.id) expect(response.data?.available_services).toHaveLength(0) }) @@ -25,12 +25,9 @@ describe('offers', () => { .get(`/air/offers/${mockOffer.id}?return_available_services=true`) .reply(200, { data: mockOffer }) - const response = await new Offers(new Client({ token: 'mockToken' })).get( - mockOffer.id, - { - return_available_services: true, - } - ) + const response = await duffel.offers.get(mockOffer.id, { + return_available_services: true, + }) expect(response.data?.id).toBe(mockOffer.id) expect(response.data?.available_services).toHaveLength(1) }) @@ -48,7 +45,7 @@ describe('offers', () => { meta: { limit: 1, before: null, after: null }, }) - const response = await new Offers(new Client({ token: 'mockToken' })).list({ + const response = await duffel.offers.list({ offer_request_id: mockOffer.id, limit: 1, }) @@ -77,4 +74,24 @@ describe('offers', () => { expect(page.data.id).toBe(mockOffer.id) } }) + + test('should update a single offer', async () => { + nock(/(.*)/) + .patch(`/air/offers/${mockOffer.id}/passengers/pas_00009hj8USM7Ncg31cBCL`) + .reply(200, { data: mockUpdatedOffer }) + + const response = await new Offers( + new Client({ token: 'mockToken' }) + ).update(mockOffer.id, 'pas_00009hj8USM7Ncg31cBCL', { + loyalty_programme_accounts: [ + { + airline_iata_code: 'BA', + account_number: '12901014', + }, + ], + given_name: 'Amelia', + family_name: 'Earhart', + }) + expect(response.data?.id).toBe('pas_00009hj8USM7Ncg31cBCL') + }) }) diff --git a/src/booking/Offers/Offers.ts b/src/booking/Offers/Offers.ts index 17c6eebd..27b68932 100644 --- a/src/booking/Offers/Offers.ts +++ b/src/booking/Offers/Offers.ts @@ -1,5 +1,21 @@ import { Resource } from '../../Resource' -import { DuffelResponse, ListOffersParams, Offer } from '../../types' +import { + DuffelResponse, + ListOffersParams, + Offer, + LoyaltyProgrammeAccounts, + UpdateOffer, +} from '../../types' + +interface UpdateOfferBodyParameters { + loyalty_programme_accounts: LoyaltyProgrammeAccounts[] + given_name: string + family_name: string +} + +interface UpdateOfferBodyParametersWithoutLoyalty { + loyalty_programme_accounts: never +} /** * Each offer represents flights you can buy from an airline at a particular price that meet your search criteria. @@ -65,4 +81,23 @@ export class Offers extends Resource { offer_request_id, }, }) + + /** + * Some offer passenger fields are updateable. Each field that can be updated is detailed in the request object. + * @param {string} offerId - Duffel's unique identifier for the offer + * @param {string} passengerId - The identifier for the passenger. This ID will be generated by Duffel + * @param {string} params.family_name - The passenger's family name. Only space, -, ', and letters from the ASCII, Latin-1 Supplement and Latin Extended-A (with the exceptions of Æ, æ, IJ, ij, Œ, œ, Þ, and ð) Unicode charts are accepted. All other characters will result in a validation error. The minimum length is 1 character, and the maximum is 20 characters. This is only required if you're also including Loyalty Programme Accounts. + * @param {string} params.given_name - The passenger's given name. Only space, -, ', and letters from the ASCII, Latin-1 Supplement and Latin Extended-A (with the exceptions of Æ, æ, IJ, ij, Œ, œ, Þ, and ð) Unicode charts are accepted. All other characters will result in a validation error. The minimum length is 1 character, and the maximum is 20 characters. This is only required if you're also including Loyalty Programme Accounts. + * @param {Object.} params.loyalty_programme_accounts - The Loyalty Programme Accounts for this passenger + */ + public update = async ( + offerId: string, + passengerId: string, + params?: UpdateOfferBodyParameters | UpdateOfferBodyParametersWithoutLoyalty + ): Promise> => + this.request({ + method: 'PATCH', + path: `${this.path}/${offerId}/passengers/${passengerId}`, + ...(params && { data: params }), + }) } diff --git a/src/booking/Offers/mockOffer.ts b/src/booking/Offers/mockOffer.ts index 94a5558d..0f51f5bd 100644 --- a/src/booking/Offers/mockOffer.ts +++ b/src/booking/Offers/mockOffer.ts @@ -184,3 +184,17 @@ export const mockOffer: Offer = { ], allowed_passenger_identity_document_types: ['passport'], } + +export const mockUpdatedOffer = { + type: 'adult', + loyalty_programme_accounts: [ + { + airline_iata_code: 'BA', + account_number: '12901014', + }, + ], + id: 'pas_00009hj8USM7Ncg31cBCL', + given_name: 'Amelia', + family_name: 'Earhart', + age: 14, +}