import expect from 'expect';
import { spy } from 'sinon';

import createTestState from 'mtest/helpers/createTestState';

import { StatusCode } from 'mweb/common/reducers/root';
import { respondThroughCallback } from 'mweb/server/responder';
import { Location } from 'mweb/common/reducers/app';
import { getCacheControlHeader } from 'mweb/server/selectors/cache';
import { Render } from 'mweb/server/renderer';

describe('respondThroughCallback', () => {
  const HTML =
    '<html><head></head><body><span>Stop wasting time reading this!</span></body></html>';
  function createRender(responseCode: StatusCode): Render {
    return {
      state: createTestState({
        app: { status: responseCode, location: Location.Channel },
      }),
      html: HTML,
    };
  }

  describe('when SUCCESS', () => {
    it('calls the callback in an AWS Lambda success mode', () => {
      const mock = spy();
      const render = createRender(StatusCode.SUCCESS);
      respondThroughCallback(mock, render);
      expect(mock.calledOnce).toBe(true);
      expect(
        mock.calledWith(null, {
          html: HTML,
          headers: {
            cacheControl: getCacheControlHeader(render.state),
          },
        }),
      ).toBe(true);
    });
  });

  describe('when NOT_FOUND', () => {
    it('calls the callback in an AWS Lambda fail mode with proper metadata', () => {
      const mock = spy();
      const render = createRender(StatusCode.NOT_FOUND);

      respondThroughCallback(mock, render);
      expect(mock.calledOnce).toBe(true);
      expect(
        mock.calledWith(
          JSON.stringify({
            status: 'not found',
            html: HTML,
            headers: {
              cacheControl: getCacheControlHeader(render.state),
            },
          }),
          null,
        ),
      ).toBe(true);
    });
  });

  describe('when unexpected return status', () => {
    it('calls the callback in an AWS Lambda fail mode with proper metadata', () => {
      const mock = spy();
      const render = createRender(StatusCode.INTERNAL_SERVER_ERROR);

      respondThroughCallback(mock, render);
      expect(mock.calledOnce).toBe(true);
      expect(
        mock.calledWith(
          JSON.stringify({
            status: 'Internal server error',
            html: HTML,
            headers: {
              cacheControl: getCacheControlHeader(render.state),
            },
          }),
          null,
        ),
      ).toBe(true);
    });
  });
});
