import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import {
  getContent,
  getEventIcon,
  getFirstLettersofContent,
  getLastCommentContent,
  getOriginalUsername,
  getPreviousVersionNumber,
} from '../helpers/eventHelpers';
import {
  badComment3,
  goodComment1,
  goodComment4,
  goodComment5,
  goodComment6,
  goodError1,
  goodError2,
  singleLetterStringGenerator,
} from './GoodEventLibrary';

/**
 * This file tests the helper functions defined in helper.js
 */

describe('The helpers functions', () => {
  describe('getContent()', () => {
    it('return plain text when content is filled with plain text only', () => {
      const actualContent = [
        {
          format: 'plainText',
          text: 'hello',
        },
      ];
      expect(getContent(actualContent, 'plainText')).toBe('hello');
    });

    it('returns null when content is null', () => {
      const actualContent = null;
      expect(getContent(actualContent, 'plainText')).toBe(null);
    });

    it('returns null when content is an empty array', () => {
      const actualContent = [];
      expect(getContent(actualContent, 'plainText')).toBe(null);
    });

    test('returns html text when content is filled with html text only', () => {
      const actualContent = [
        {
          format: 'html',
          text: '<p> hello </p>',
        },
      ];
      expect(getContent(actualContent, 'html')).toBe('<p> hello </p>');
    });

    test('returns null when text property is not defined', () => {
      const actualContent = [
        {
          format: 'text',
        },
      ];
      expect(getContent(actualContent, 'plainText')).toBe(null);
    });

    test(' returns null when format property is not defined', () => {
      const actualContent = [
        {
          text: 'hello',
        },
      ];
      expect(getContent(actualContent, 'plainText')).toBe(null);
    });
  });

  describe('getFirstLettersofContent()', () => {
    test('plainText contains more than 100 letters', () => {
      const actualContent = [
        {
          format: 'plainText',
          text: `${singleLetterStringGenerator(95)}123456789`,
        },
      ];
      const expectedText = `${singleLetterStringGenerator(95)}12345 ...`;
      expect(getFirstLettersofContent(actualContent, 100)).toBe(expectedText);
    });

    test('plainText contains less than 100 letters', () => {
      const actualContent = [
        {
          format: 'plainText',
          text: 'This is some text',
        },
      ];
      const expectedText = 'This is some text';
      expect(getFirstLettersofContent(actualContent, 100)).toBe(expectedText);
    });

    test('content is null', () => {
      const actualContent = null;
      expect(getFirstLettersofContent(actualContent, 100)).toBe('');
    });

    test('content is an empty array', () => {
      const actualContent = [];
      expect(getFirstLettersofContent(actualContent, 100)).toBe('');
    });

    test('content does not contain the plain text object', () => {
      const actualContent = [
        {
          format: 'html',
          text: '<p> hello </p>',
        },
      ];
      expect(getFirstLettersofContent(actualContent, 100)).toBe('');
    });

    test('text property is not defined in the object but format is there', () => {
      const actualContent = [
        {
          format: 'text',
        },
      ];
      expect(getFirstLettersofContent(actualContent, 100)).toBe('');
    });

    test('format property is not defined in the object but text is there', () => {
      const actualContent = [
        {
          text: 'hello',
        },
      ];
      expect(getFirstLettersofContent(actualContent, 100)).toBe('');
    });

    test('number of character is not provided', () => {
      const actualContent = [
        {
          format: 'plainText',
          text: 'ten characters should be displayed ',
        },
      ];
      expect(getFirstLettersofContent(actualContent)).toBe('ten charac ...');
    });
  });

  describe('getPreviousVersionNumber', () => {
    test('it returns 0 when no event is provided', () => {
      let actualEvent;

      expect(getPreviousVersionNumber(actualEvent)).toBe(0);
    });

    test('it returns 0 when the event has a previousEventVersion of null', () => {
      const actualEvent = goodComment1;

      expect(getPreviousVersionNumber(actualEvent)).toBe(0);
    });

    test('it returns 0 when the event has a previousEventVersion of undefined', () => {
      const actualEvent = goodError1;

      expect(getPreviousVersionNumber(actualEvent)).toBe(0);
    });

    test('it returns the number of previous version an event has', () => {
      const actualEvent = goodError2;

      expect(getPreviousVersionNumber(actualEvent)).toBe(1);
    });
  });

  describe('getEventIcon', () => {
    it('returns an icon of size 25 when the size is not specified', () => {
      Enzyme.configure({ adapter: new Adapter() });

      const actualCategory = 'comment';
      expect(Enzyme.shallow(getEventIcon(actualCategory)).prop('width')).toBe(
        '25px'
      );
    });

    it('returns an icon which size corresponds to the specified one', () => {
      Enzyme.configure({ adapter: new Adapter() });

      const actualCategory = 'comment';
      const actualSize = '40';
      expect(
        Enzyme.shallow(getEventIcon(actualCategory, actualSize)).prop('width')
      ).toBe('40px');
    });
  });

  describe('getLastCommentContent', () => {
    it('returns the last comment of an annotation without previous version', () => {
      const actualEvent = goodComment1;
      const expectedContent = [
        {
          format: 'plainText',
          text: 'plain text content 1',
        },
        {
          format: 'html',
          text: '<p> html text content 1 </p>',
        },
      ];

      expect(getLastCommentContent(actualEvent)).toEqual(expectedContent);
    });

    it('returns the last comment of an annotation with several versions', () => {
      const actualEvent = goodComment4;
      const expectedContent = [
        {
          format: 'plainText',
          text: 'new version of plain text',
        },
        {
          format: 'html',
          text: '<p> new version of plain text </p>',
        },
      ];

      expect(getLastCommentContent(actualEvent)).toEqual(expectedContent);
    });

    it('returns null for an uncommented notification', () => {
      const actualEvent = goodError1;
      const expectedContent = null;

      expect(getLastCommentContent(actualEvent)).toBe(expectedContent);
    });

    it('returns the last comment for a commented notification', () => {
      const actualEvent = goodError2;
      const expectedContent = [
        {
          format: 'plainText',
          text: 'this is a user comment on the error',
        },
      ];

      expect(getLastCommentContent(actualEvent)).toEqual(expectedContent);
    });

    it('returns null when the event has no type', () => {
      const actualEvent = badComment3;
      const expectedContent = null;

      expect(getLastCommentContent(actualEvent)).toBe(expectedContent);
    });
  });

  describe('getOriginalUsername', () => {
    it('returns the original username for an event which has no previous version', () => {
      const actualEvent = goodComment1;
      expect(getOriginalUsername(actualEvent)).toBe('mchaille');
    });

    it('returns the original username for an event which has a previous version', () => {
      const actualEvent = goodComment5;
      expect(getOriginalUsername(actualEvent)).toBe('agoetz');
    });

    it('returns null when the original username does not exist', () => {
      const actualEvent = goodComment6;
      expect(getOriginalUsername(actualEvent)).toBe(null);
    });
  });
});
