Skip to content

Commit 113afc4

Browse files
iisaclaude
andcommitted
Add unit tests for setNewPaymentMethod merge behavior
Tests field preservation (dates, status), sequential updates tracking, and PayPal/Venmo optional field handling. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent a80f843 commit 113afc4

File tree

1 file changed

+150
-0
lines changed

1 file changed

+150
-0
lines changed

test/models/plan.test.ts

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,5 +268,155 @@ describe('MonthlyPlan', () => {
268268
mp.setNewPaymentMethod(request);
269269
expect(mp.plan.btdata.last4).to.equal('unknown');
270270
});
271+
272+
it('preserves nextBillingDate and lastBillingDate through the merge', () => {
273+
const mp = new MonthlyPlan(makePlan());
274+
275+
const request = new PaymentMethodRequest({
276+
paymentMethodInfo: {
277+
description: 'New card',
278+
nonce: 'nonce_789',
279+
type: 'CreditCard',
280+
details: {
281+
cardType: 'Amex',
282+
lastFour: '9999',
283+
},
284+
},
285+
donorContactInfo: {},
286+
paymentProvider: PaymentProvider.CreditCard,
287+
});
288+
289+
mp.setNewPaymentMethod(request);
290+
291+
expect(mp.plan.btdata.nextBillingDate.date).to.equal(
292+
'2024-08-15 00:00:00',
293+
);
294+
expect(mp.plan.btdata.lastBillingDate.date).to.equal(
295+
'2024-07-15 00:00:00',
296+
);
297+
});
298+
299+
it('preserves status field through the merge', () => {
300+
const mp = new MonthlyPlan(makePlan());
301+
302+
const request = new PaymentMethodRequest({
303+
paymentMethodInfo: {
304+
description: 'New card',
305+
nonce: 'nonce_abc',
306+
type: 'CreditCard',
307+
details: {
308+
cardType: 'Visa',
309+
lastFour: '1111',
310+
},
311+
},
312+
donorContactInfo: {},
313+
paymentProvider: PaymentProvider.CreditCard,
314+
});
315+
316+
mp.setNewPaymentMethod(request);
317+
expect(mp.plan.btdata.status).to.equal('Active');
318+
expect(mp.plan.btdata.paymentMethodType).to.equal('CreditCard');
319+
});
320+
321+
it('stores old_btData as a snapshot when called twice', () => {
322+
const mp = new MonthlyPlan(makePlan());
323+
324+
const firstRequest = new PaymentMethodRequest({
325+
paymentMethodInfo: {
326+
description: 'First update',
327+
nonce: 'nonce_1',
328+
type: 'CreditCard',
329+
details: {
330+
cardType: 'Mastercard',
331+
lastFour: '2222',
332+
expirationMonth: '03',
333+
expirationYear: '2027',
334+
},
335+
},
336+
donorContactInfo: {},
337+
paymentProvider: PaymentProvider.CreditCard,
338+
});
339+
340+
mp.setNewPaymentMethod(firstRequest);
341+
const afterFirstUpdate = mp.plan.btdata;
342+
343+
const secondRequest = new PaymentMethodRequest({
344+
paymentMethodInfo: {
345+
description: 'Second update',
346+
nonce: 'nonce_2',
347+
type: 'CreditCard',
348+
details: {
349+
cardType: 'Amex',
350+
lastFour: '3333',
351+
expirationMonth: '11',
352+
expirationYear: '2029',
353+
},
354+
},
355+
donorContactInfo: {},
356+
paymentProvider: PaymentProvider.CreditCard,
357+
});
358+
359+
mp.setNewPaymentMethod(secondRequest);
360+
361+
// old_btData should be the intermediate state, not the original
362+
expect(mp.plan.old_btData).to.equal(afterFirstUpdate);
363+
expect(mp.plan.btdata.cardType).to.equal('Amex');
364+
expect(mp.plan.btdata.last4).to.equal('3333');
365+
});
366+
367+
it('handles PayPal details with paypalEmail on original btdata', () => {
368+
const btdata = makeBtData({
369+
paymentMethodType: 'PayPal',
370+
paypalEmail: 'donor@example.com',
371+
last4: null,
372+
cardType: null,
373+
});
374+
const mp = new MonthlyPlan(makePlan({ btdata }));
375+
376+
const request = new PaymentMethodRequest({
377+
paymentMethodInfo: {
378+
description: 'New PayPal',
379+
nonce: 'nonce_pp',
380+
type: 'PayPal',
381+
details: {
382+
description: 'new-donor@example.com',
383+
},
384+
},
385+
donorContactInfo: {},
386+
paymentProvider: PaymentProvider.CreditCard,
387+
});
388+
389+
mp.setNewPaymentMethod(request);
390+
391+
// paypalEmail from original btdata is preserved via spread
392+
expect(mp.plan.btdata.paypalEmail).to.equal('donor@example.com');
393+
expect(mp.plan.btdata.last4).to.equal('unknown');
394+
});
395+
396+
it('handles Venmo details with venmoUsername on original btdata', () => {
397+
const btdata = makeBtData({
398+
paymentMethodType: 'Venmo',
399+
venmoUsername: '@donor',
400+
last4: null,
401+
cardType: null,
402+
});
403+
const mp = new MonthlyPlan(makePlan({ btdata }));
404+
405+
const request = new PaymentMethodRequest({
406+
paymentMethodInfo: {
407+
description: 'New Venmo',
408+
nonce: 'nonce_venmo',
409+
type: 'Venmo',
410+
details: {},
411+
},
412+
donorContactInfo: {},
413+
paymentProvider: PaymentProvider.CreditCard,
414+
});
415+
416+
mp.setNewPaymentMethod(request);
417+
418+
expect(mp.plan.btdata.venmoUsername).to.equal('@donor');
419+
expect(mp.plan.btdata.last4).to.equal('unknown');
420+
});
271421
});
272422
});

0 commit comments

Comments
 (0)