// @ts-nocheck import { expect } from 'chai'; import { addDays, subDays, formatISO } from 'date-fns'; import { STATES, StateManager } from '../../src/state-manager'; import { UserStates } from '../../src/types/states'; import { transitionEvent, cancellationEvent, undoTransitionEvent, undoCancellationEvent } from '../fixtures/states'; describe('State Manager', () => { const pastDate = new Date('2020-05-19T11:07:17.931'); const oneMonthAway = formatISO(addDays(new Date(), 30)); const slightlyAhead = formatISO(addDays(new Date(), 5)); const oneMonthAgo = formatISO(subDays(new Date(), 30)); const eventDate = formatISO(subDays(pastDate, 30)); const eventDateOneDayAfter = formatISO(addDays(pastDate, 1)); const eventDateTwoDaysAfter = formatISO(addDays(pastDate, 2)); const scenarios = [ { name: 'when user has transitioned then undone the transition and then transitioned again - mark as transition', userData: {}, subscriptionHistory: { history: [ transitionEvent({ effectiveDate: oneMonthAway, eventDate: eventDateTwoDaysAfter }), undoTransitionEvent({ effectiveDate: slightlyAhead, eventDate: eventDateOneDayAfter }), transitionEvent({ effectiveDate: oneMonthAway, eventDate }) ] }, expectedState: UserStates.TRANSITION }, { name: 'when user has transitioned but subsequently undone the transition - mark as default', userData: {}, subscriptionHistory: { history: [ undoTransitionEvent({ effectiveDate: slightlyAhead, eventDate: eventDateOneDayAfter }), transitionEvent({ effectiveDate: oneMonthAway, eventDate }) ] }, expectedState: UserStates.DEFAULT }, { name: 'when user has taken a transition with the same price but different payment terms - mark as default', userData: {}, subscriptionHistory: { history: [ transitionEvent({ oldProducts: ['N6D'], newProducts: ['N6D'], oldPrice: 50, newPrice: 150, term: 'P1M', newTerm: 'P13W' }) ] }, expectedState: UserStates.DEFAULT }, { name: 'when user has taken a transition to a cheaper equivalent product - mark as discounted', userData: {}, subscriptionHistory: { history: [ transitionEvent({ newPrice: 20, term: 'P1M', effectiveDate: oneMonthAway }) ] }, expectedState: UserStates.DISCOUNT }, { name: 'when user has taken a transition to a cheaper equivalent product and then undone the transition - mark as default', userData: {}, subscriptionHistory: { history: [ transitionEvent({ newPrice: 20, term: 'P1M', effectiveDate: oneMonthAway }), undoTransitionEvent({ effectiveDate: slightlyAhead, eventDate: eventDateOneDayAfter }), ] }, expectedState: UserStates.DEFAULT }, { name: 'when user has taken a transition to a cheaper equivalent product, undone the transition, transitioned again - mark as discount', userData: {}, subscriptionHistory: { history: [ transitionEvent({ newPrice: 20, term: 'P1M', effectiveDate: oneMonthAway, eventDate: eventDateTwoDaysAfter }), undoTransitionEvent({ effectiveDate: slightlyAhead, eventDate: eventDateOneDayAfter }), transitionEvent({ newPrice: 20, term: 'P1M', effectiveDate: oneMonthAway, eventDate }), ] }, expectedState: UserStates.DISCOUNT }, { name: 'when user has taken a transition to same product but on a more expensive term (monthly -> annual) - mark as discounted', userData: {}, subscriptionHistory: { history: [ transitionEvent({ newPrice: 240, term: 'P1Y', effectiveDate: oneMonthAway }) ] }, expectedState: UserStates.DISCOUNT }, { name: 'when user has taken a transition to a different product - mark as transitioned', userData: {}, subscriptionHistory: { history: [ transitionEvent({ newProducts: ['P2'], effectiveDate: oneMonthAway }) ] }, expectedState: UserStates.TRANSITION }, { name: 'when user has cancelled then undone the cancellation and then cancelled again - mark as cancelled', userData: {}, subscriptionHistory: { history: [ cancellationEvent({ effectiveDate: oneMonthAway, eventDate: eventDateTwoDaysAfter }), undoCancellationEvent({ effectiveDate: slightlyAhead, eventDate: eventDateOneDayAfter }), cancellationEvent({ effectiveDate: oneMonthAway, eventDate }) ] }, expectedState: UserStates.CANCELLATION }, { name: 'when user has cancelled but subsequently undone the cancellation - mark as default', userData: {}, subscriptionHistory: { history: [ undoCancellationEvent({ effectiveDate: slightlyAhead, eventDate: eventDateOneDayAfter }), cancellationEvent({ effectiveDate: oneMonthAway, eventDate }) ] }, expectedState: UserStates.DEFAULT }, { name: 'when user has a future cancellation - mark as cancelled', userData: {}, subscriptionHistory: { history: [ cancellationEvent({ effectiveDate: oneMonthAway }) ] }, expectedState: UserStates.CANCELLATION }, { name: 'when user is in stepup - mark as stepup', userData: {}, subscriptionHistory: { isInStepUp: true }, expectedState: UserStates.STEPUP }, { name: 'when user is in frozen price - mark as frozen', userData: {}, subscriptionHistory: { hasFrozenPrice: true }, expectedState: UserStates.FREEZE }, { name: 'when user has transitioned but subsequently cancelled - mark as cancelled', userData: {}, subscriptionHistory: { history: [ cancellationEvent({ effectiveDate: oneMonthAway }), transitionEvent({ effectiveDate: slightlyAhead }) ] }, expectedState: UserStates.CANCELLATION }, { name: 'when user has cancelled in the past - do not mark as cancelled', userData: {}, subscriptionHistory: { history: [ cancellationEvent(oneMonthAgo) ] }, expectedState: UserStates.DEFAULT }, { name: 'when user has no important events and is a trialist - mark as a trialist', userData: { isTrialist: true }, subscriptionHistory: { isInStepUp: false, hasFrozenPrice: false, history: [] }, expectedState: UserStates.TRIALIST }, { name: 'when user has no applicable events, fallback to default', userData: {}, subscriptionHistory: { isInStepUp: false, hasFrozenPrice: false, history: [] }, expectedState: UserStates.DEFAULT }, { name: 'when user is in frozen price, but has also transitioned to a cheaper product - mark as discount', userData: {}, subscriptionHistory: { isInStepUp: false, hasFrozenPrice: true, history: [ transitionEvent({ newPrice: 240, term: 'P1Y', effectiveDate: oneMonthAway }) ], }, expectedState: UserStates.DISCOUNT } ]; scenarios.map(scenario => { it(scenario.name, () => { const stateManager = new StateManager(scenario.userData); stateManager.setSubscriptionHistory(scenario.subscriptionHistory); const state = stateManager.identify(); expect(state).to.equal(scenario.expectedState); }); }); });