Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/DuffelPayments/PaymentIntents/mockPaymentIntents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
21 changes: 21 additions & 0 deletions src/booking/Offers/OfferTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
39 changes: 28 additions & 11 deletions src/booking/Offers/Offers.spec.ts
Original file line number Diff line number Diff line change
@@ -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()
Expand All @@ -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)
})
Expand All @@ -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)
})
Expand All @@ -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,
})
Expand Down Expand Up @@ -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')
})
})
37 changes: 36 additions & 1 deletion src/booking/Offers/Offers.ts
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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.<LoyaltyProgrammeAccounts>} params.loyalty_programme_accounts - The Loyalty Programme Accounts for this passenger
*/
public update = async (
offerId: string,
passengerId: string,
params?: UpdateOfferBodyParameters | UpdateOfferBodyParametersWithoutLoyalty
): Promise<DuffelResponse<UpdateOffer>> =>
this.request({
method: 'PATCH',
path: `${this.path}/${offerId}/passengers/${passengerId}`,
...(params && { data: params }),
})
}
14 changes: 14 additions & 0 deletions src/booking/Offers/mockOffer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}