import { shallow } from 'enzyme';
import React from 'react';
import {
  BranchUpsell,
  BranchUpsellProps,
  INTERACTION_CONTENT_BRANCH_CONTINUE,
  INTERACTION_CONTENT_BRANCH_CTA,
  INTERACTION_CONTENT_BRANCH_DISMISS,
} from './branchUpsell';
import { BranchJourneyType } from './branchUtils';

jest.useFakeTimers();
const DEFAULT_PROPS: BranchUpsellProps = {
  delaySecondsUntilUpsell: 5,
  deviceID: '321',
  journey: {
    channel: 'BigAndy',
    type: BranchJourneyType.Live,
  },
  sessionID: '123',
  trackEvent: () => undefined,
};

describe('<BranchUpsell />', () => {
  it('kicks off branch upsell timer on mount and closes on unmount', () => {
    const subject = shallow(<BranchUpsell {...DEFAULT_PROPS} />, {
      disableLifecycleMethods: true,
    });

    const instance = subject.instance() as BranchUpsell;
    const closeBranch = jest.fn();
    const openBranch = jest.fn();
    instance.closeBranch = closeBranch;
    instance.openBranch = () => openBranch;

    instance.componentDidMount();
    expect(openBranch.mock.calls.length).toBe(0);
    expect(closeBranch.mock.calls.length).toBe(0);
    expect(closeBranch.mock.calls.length).toBe(0);

    jest.runAllTimers();
    expect(openBranch.mock.calls.length).toBe(1);
    expect(closeBranch.mock.calls.length).toBe(0);

    instance.componentWillUnmount();
    expect(openBranch.mock.calls.length).toBe(1);
    expect(closeBranch.mock.calls.length).toBe(1);
  });

  it('handles when unmount called before timer finishes', () => {
    const subject = shallow(<BranchUpsell {...DEFAULT_PROPS} />, {
      disableLifecycleMethods: true,
    });

    const instance = subject.instance() as BranchUpsell;
    const closeBranch = jest.fn();
    const openBranch = jest.fn();
    instance.closeBranch = closeBranch;
    instance.openBranch = () => openBranch;

    instance.componentDidMount();
    expect(openBranch.mock.calls.length).toBe(0);
    expect(closeBranch.mock.calls.length).toBe(0);

    instance.componentWillUnmount();
    jest.runAllTimers();
    expect(openBranch.mock.calls.length).toBe(0);
    expect(closeBranch.mock.calls.length).toBe(1);
  });

  const trackingTestCase = [
    {
      event: 'didClickJourneyCTA',
      expectedInteractionContent: INTERACTION_CONTENT_BRANCH_CTA,
    },
    {
      event: 'didClickJourneyClose',
      expectedInteractionContent: INTERACTION_CONTENT_BRANCH_DISMISS,
    },
    {
      event: 'didClickJourneyContinue',
      expectedInteractionContent: INTERACTION_CONTENT_BRANCH_CONTINUE,
    },
  ];

  trackingTestCase.forEach(testCase => {
    it(`calls trackEvent with proper interaction content for ${
      testCase.event
    } branch event`, () => {
      const trackEvent = jest.fn();
      trackEvent.mockReturnValue(() => undefined);
      const subject = shallow(
        <BranchUpsell {...DEFAULT_PROPS} trackEvent={trackEvent} />,
        {
          disableLifecycleMethods: true,
        },
      );
      const instance = subject.instance() as BranchUpsell;
      expect(trackEvent.mock.calls.length).toBe(0);
      instance.branchEventListener(testCase.event as Branch.BranchJourneyEvent);
      expect(trackEvent.mock.calls[0][0]).toBe(
        testCase.expectedInteractionContent,
      );
    });
  });
});
