// @ts-nocheck import { expect } from 'chai'; import { mapSubscription, mapSubscriptionRatePlan, mapSubscriptionFutureRatePlan, mapSubscriptionRatePlanCharge, mapSubscriptionHistory, } from '../../../src/mappers/subscription'; import { Subscription, SubscriptionRatePlan, SubscriptionFutureRatePlan, SubscriptionRatePlanCharge, SubscriptionHistoryModel, } from '../../../src/models/subscription'; import { stepUpUserHistory } from '../../fixtures/subscription-history'; import { formatISO } from 'date-fns'; let data: any; function scheduleStepUp(history: any, { yearOffset = 1 }: any = {}) { const newYear = new Date().getFullYear() + yearOffset; const stepUpEventIndex = history.findIndex((ev: any) => ev.event_type === 'StepUp'); // lazy clone const newHistory = JSON.parse(JSON.stringify(history)); newHistory[stepUpEventIndex].event_effective_date = `${newYear}-11-28T00:00:00.000Z`; return newHistory; } describe('mapSubscription', () => { beforeEach(() => { data = { source: 'Source', id: 'Id', number: 'Number', accountId: 'AccountId', accountNumber: 'AccountNumber', status: 'Status', effectiveStartDate: 'Start Date', effectiveEndDate: 'End Date', trial: true, offerId: '1234', offer: { offerId: "6c7b7f36-", discount: null }, stepUp: { isInStepUp: false, priceBeforeStepUp: "39.00", priceAfterStepUp: null } }; }); it('should return a Subscription model', () => { const mapped = mapSubscription(data); expect(mapped instanceof Subscription).to.be.true; }); it('should map data correctly', () => { const mapped = mapSubscription(data); expect(mapped.source).to.equal(data.source); expect(mapped.id).to.equal(data.id); expect(mapped.number).to.equal(data.number); expect(mapped.accountId).to.equal(data.accountId); expect(mapped.accountNumber).to.equal(data.accountNumber); expect(mapped.status).to.equal(data.status); expect(mapped.effectiveStartDate).to.equal(data.effectiveStartDate); expect(mapped.effectiveEndDate).to.equal(data.effectiveEndDate); expect(mapped.trial).to.equal(data.trial); expect(mapped.displayName).to.equal(''); expect(mapped.offerId).to.equal(data.offerId); expect(mapped.offer).to.deep.equal(data.offer); expect(mapped.stepUp).to.deep.equal(data.stepUp); }); it('should use an override map with offers ids to map a display name', () => { const overrides = { '1234': 'Trial', }; const mapped = mapSubscription(data, overrides); expect(mapped.displayName).to.equal('Trial'); }); it('should not set ratePlans if none passed', () => { const mapped = mapSubscription(data); expect(mapped.ratePlans).to.deep.equal([]); }); it('should map ratePlans to SubscriptionRatePlan model', () => { data.ratePlans = [{ id: 'Rate Plan 1' }]; const mapped = mapSubscription(data); expect(mapped.ratePlans[0] instanceof SubscriptionRatePlan).to.be.true; }); it('should map all ratePlans', () => { data.ratePlans = [{ id: 'Rate Plan 1' }, { id: 'Rate Plan 2' }]; const mapped = mapSubscription(data); expect(mapped.ratePlans.length).to.equal(2); }); }); describe('mapSubscriptionRatePlan', () => { beforeEach(() => { data = { id: 'Id', productName: 'Product Name', productCode: 'Product Code', term: 'Term', option: 'Option' }; }); it('should return a SubscriptionRatePlan model', () => { const mapped = mapSubscriptionRatePlan(data); expect(mapped instanceof SubscriptionRatePlan).to.be.true; }); it('should map data correctly', () => { const mapped = mapSubscriptionRatePlan(data); expect(mapped.id).to.equal(data.id); expect(mapped.productCode).to.equal(data.productCode); expect(mapped.productName).to.equal(data.productName); expect(mapped.term).to.equal(data.term); expect(mapped.option).to.equal(data.option); }); it('should not set charges if none passed', () => { const mapped = mapSubscriptionRatePlan(data); expect(mapped.ratePlanCharges).to.deep.equal([]); }); it('should map ratePlanCharges to SubscriptionRatePlanCharge model', () => { data.ratePlanCharges = [{ name: 'Charge 1' }]; const mapped = mapSubscriptionRatePlan(data); expect(mapped.ratePlanCharges[0] instanceof SubscriptionRatePlanCharge).to.be.true; }); it('should map all ratePlanCharges', () => { data.ratePlanCharges = [{ name: 'Charge 1' }, { name: 'Charge 2' }]; const mapped = mapSubscriptionRatePlan(data); expect(mapped.ratePlanCharges.length).to.equal(2); }); }); describe('mapSubscriptionFutureRatePlan', () => { beforeEach(() => { data = { id: 'Id', productName: 'Product Name', productCode: 'Product Code', term: 'Term', option: 'Option' }; }); it('should return a SubscriptionFutureRatePlan model', () => { const mapped = mapSubscriptionFutureRatePlan(data); expect(mapped instanceof SubscriptionFutureRatePlan).to.be.true; }); it('should map data correctly', () => { const mapped = mapSubscriptionFutureRatePlan(data); expect(mapped.id).to.equal(data.id); expect(mapped.productCode).to.equal(data.productCode); expect(mapped.productName).to.equal(data.productName); expect(mapped.term).to.equal(data.term); expect(mapped.option).to.equal(data.option); }); it('should not set charges if none passed', () => { const mapped = mapSubscriptionFutureRatePlan(data); expect(mapped.ratePlanCharge).to.undefined; }); it('should map ratePlanCharge to SubscriptionRatePlanCharge model', () => { data.ratePlanCharges = [{ name: 'Charge 1' }]; const mapped = mapSubscriptionFutureRatePlan(data); expect(mapped.ratePlanCharge instanceof SubscriptionRatePlanCharge).to.be.true; }); }); describe('mapSubscriptionRatePlanCharge', () => { beforeEach(() => { data = { name: 'Name', description: 'Description', type: 'type', productType: 'productType', productCode: 'productCode', effectiveStartDate: 'Start Date', effectiveEndDate: 'End Date', chargedThroughDate: 'Charge Through Date', price: 100.00, currency: 'Currency' }; }); it('should return a SubscriptionRatePlan model', () => { const mapped = mapSubscriptionRatePlanCharge(data); expect(mapped instanceof SubscriptionRatePlanCharge).to.be.true; }); it('should map data correctly', () => { const mapped = mapSubscriptionRatePlanCharge(data); expect(mapped.name).to.equal(data.name); expect(mapped.description).to.equal(data.description); expect(mapped.type).to.equal(data.type); expect(mapped.productType).to.equal(data.productType); expect(mapped.productCode).to.equal(data.productCode); expect(mapped.effectiveStartDate).to.equal(data.effectiveStartDate); expect(mapped.effectiveEndDate).to.equal(data.effectiveEndDate); expect(mapped.chargedThroughDate).to.equal(data.chargedThroughDate); expect(mapped.price).to.equal(data.price); expect(mapped.currency).to.equal(data.currency); }); }); describe('mapSubscriptionHistory', () => { it('history is mapped to the correct model properly', () => { const { history }: any = mapSubscriptionHistory(stepUpUserHistory as any); const isMappedProperly = history.every((item: any) => item instanceof SubscriptionHistoryModel); expect(isMappedProperly).to.be.true; }); it('history is mapped with the right properties', () => { const { history }: any = mapSubscriptionHistory(stepUpUserHistory as any); const isMappedProperly = history.every((item: any) => !!item.eventEffectiveDate && !!item.eventDate && !!item.eventType); expect(isMappedProperly).to.be.true; }); it('isInStepUp is false if there is no future stepup returned', () => { const { isInStepUp, stepUpEvent, freezeEvent } = mapSubscriptionHistory(stepUpUserHistory); expect(isInStepUp).to.be.false; expect(stepUpEvent).to.equal(undefined); expect(freezeEvent).to.equal(undefined); }); it('isInStepUp is true if there is a future stepup returned', () => { const newHistory = scheduleStepUp(stepUpUserHistory, { yearOffset: 1 }); const { isInStepUp, stepUpEvent, freezeEvent } = mapSubscriptionHistory(newHistory); expect(isInStepUp).to.be.true; expect(stepUpEvent).to.have.property('eventType', 'StepUp'); expect(freezeEvent).to.be.undefined; }); it('isInStepUp is false if there is an undo step up BEFORE (array position) the step up event', () => { const [stepUp, creationEvent] = scheduleStepUp(stepUpUserHistory, { year: 1 }); const undoEvent = { user_id: 'some uuid', event_effective_date: formatISO(new Date()), event_type: 'UndoStepUp', event_data: { subscriptionAfter: { productName: 'Standard FT.com' } } }; const newHistory = [undoEvent, stepUp, creationEvent]; const { isInStepUp, hasFrozenPrice, stepUpEvent, freezeEvent } = mapSubscriptionHistory(newHistory); expect(isInStepUp).to.be.false; expect(hasFrozenPrice).to.be.true; expect(stepUpEvent).to.have.property('eventType', 'StepUp'); expect(stepUpEvent).to.have.property('eventEffectiveDate', stepUp.event_effective_date); expect(freezeEvent).to.have.property('eventType', 'UndoStepUp'); expect(freezeEvent).to.have.property('eventEffectiveDate', undoEvent.event_effective_date); }); // if someone was stepped up, then froze, then they transitioned but the transition has not yet happened (effective date in the future) // they should not be frozen or inStepUp it('ensure ordering reflects reality when stepUp -> undoStepUp -> transition (future)', () => { const [pastStepUp] = scheduleStepUp(stepUpUserHistory, { yearOffset: -1 }); const [stepUp, creation] = scheduleStepUp(stepUpUserHistory, { yearOffset: 1 }); let twoWeeksFromToday = new Date(); twoWeeksFromToday.setDate(twoWeeksFromToday.getDate() + 14); const undoEvent: any = { user_id: 'some uuid', event_type: 'UndoStepUp', event_data: { subscriptionAfter: { productName: 'Standard FT.com' } } }; const transition: any = { user_id: 'some uuid', event_type: 'Transition', event_data: { subscriptionAfter: { productName: 'Standard FT.com' } }, event_effective_date: twoWeeksFromToday.toISOString() }; const newHistory = [transition, undoEvent, pastStepUp, creation]; const { isInStepUp, hasFrozenPrice } = mapSubscriptionHistory(newHistory); expect(isInStepUp).to.be.false; expect(hasFrozenPrice).to.be.false; }); // if someone was stepped up, then froze, then they transitioned and the the transition has already happened (effective date in the past) // they should not be frozen or inStepUp it('ensure ordering reflects reality when stepUp -> undoStepUp -> transition (past)', () => { const [pastStepUp] = scheduleStepUp(stepUpUserHistory, { yearOffset: -1 }); const [stepUp, creation] = scheduleStepUp(stepUpUserHistory, { yearOffset: 1 }); let twoWeeksAgoToday = new Date(); twoWeeksAgoToday.setDate(twoWeeksAgoToday.getDate() - 14); const undoEvent: any = { user_id: 'some uuid', event_type: 'UndoStepUp', event_data: { subscriptionAfter: { productName: 'Standard FT.com' } } }; const transition: any = { user_id: 'some uuid', event_type: 'Transition', event_data: { subscriptionAfter: { productName: 'Standard FT.com' } }, event_effective_date: twoWeeksAgoToday.toISOString() }; const newHistory = [transition, undoEvent, pastStepUp, creation]; const { isInStepUp, hasFrozenPrice } = mapSubscriptionHistory(newHistory); expect(isInStepUp).to.be.false; expect(hasFrozenPrice).to.be.false; }); // if someone was stepped up, then froze, then they stepped up but there is no future step up or transition // they should not be frozen or inStepUp it('ensure ordering reflects reality when stepUp -> undoStepUp -> stepUp (in past)', () => { const [pastStepUp, creation] = scheduleStepUp(stepUpUserHistory, { yearOffset: -1 }); const undoEvent: any = { user_id: 'some uuid', event_type: 'UndoStepUp', event_data: { subscriptionAfter: { productName: 'Standard FT.com' } } }; const newHistory = [pastStepUp, undoEvent, pastStepUp, creation]; const { isInStepUp, hasFrozenPrice } = mapSubscriptionHistory(newHistory); expect(isInStepUp).to.be.false; expect(hasFrozenPrice).to.be.false; }); // if someone was stepped up, then froze, then has been stepped up again // then they should be in stepup! it('ensure ordering reflects reality stepUp -> undoStepUp -> stepUp (in future)', () => { const [pastStepUp] = scheduleStepUp(stepUpUserHistory, { yearOffset: -1 }); const [stepUp, creation] = scheduleStepUp(stepUpUserHistory, { yearOffset: 1 }); const undoEvent: any = { user_id: 'some uuid', event_type: 'UndoStepUp', event_data: { subscriptionAfter: { productName: 'Standard FT.com' } } }; const newHistory = [stepUp, undoEvent, pastStepUp, creation]; const { isInStepUp, hasFrozenPrice, stepUpEvent, freezeEvent } = mapSubscriptionHistory(newHistory); expect(isInStepUp).to.be.true; expect(hasFrozenPrice).to.be.false; expect(stepUpEvent).to.have.property('eventType', 'StepUp'); expect(stepUpEvent).to.have.property('eventEffectiveDate', stepUp.event_effective_date); expect(freezeEvent).to.have.property('eventType', 'UndoStepUp'); expect(freezeEvent).to.have.property('eventEffectiveDate', undoEvent.event_effective_date); }); it('augments event with subscription changes if event is a StepUp event', () => { const { history } = mapSubscriptionHistory(stepUpUserHistory); const stepUpEvent = history.find(ev => ev.eventType === 'StepUp'); // Base level properties expect(stepUpEvent).to.have.property('subscriptionBefore'); expect(stepUpEvent?.subscriptionBefore).to.have.property('subNumber'); expect(stepUpEvent?.subscriptionBefore).to.have.property('productName'); expect(stepUpEvent?.subscriptionBefore).to.have.property('products'); expect(stepUpEvent?.subscriptionBefore).to.have.property('price'); expect(stepUpEvent?.subscriptionBefore).to.have.property('term'); // Base level properties expect(stepUpEvent).to.have.property('subscriptionAfter'); expect(stepUpEvent?.subscriptionAfter).to.have.property('subNumber'); expect(stepUpEvent?.subscriptionAfter).to.have.property('productName'); expect(stepUpEvent?.subscriptionAfter).to.have.property('products'); expect(stepUpEvent?.subscriptionAfter).to.have.property('price'); expect(stepUpEvent?.subscriptionAfter).to.have.property('term'); }); });