"use strict";

var _react = _interopRequireDefault(require("react"));

var _enzyme = require("enzyme");

var _enzymeToJson = require("enzyme-to-json");

var _mock_api = require("../mock_api");

var _mock_data = _interopRequireDefault(require("../mock_api/mock_data"));

var _ = _interopRequireDefault(require("../"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }

var MOCK_API_DELAY = 100;
var searchFunction = (0, _mock_api.getSearchFunction)(MOCK_API_DELAY);

var getDelayedPromise = function getDelayedPromise() {
  var delay = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
  return new Promise(function (r) {
    return setTimeout(r, delay);
  });
};

describe("components/SearchPicker", function () {
  var component;
  var renderedData;
  var onItemSelectedStub;
  describe("default case", function () {
    beforeEach(function () {
      onItemSelectedStub = jest.fn();
      component = (0, _enzyme.mount)(_react["default"].createElement(_["default"], {
        onItemSelected: onItemSelectedStub,
        searchFunction: searchFunction,
        supportedTypes: ["feature"]
      }, function (data) {
        renderedData = data;
        return _react["default"].createElement("div", null, data.renderInput(), _react["default"].createElement("p", null, "A list of entities"));
      }));
    });
    it("should render component same as snapshot", function () {
      expect((0, _enzymeToJson.mountToJson)(component)).toMatchSnapshot();
    });
    it("should pass a default list of items on creation", function () {
      return getDelayedPromise().then(function () {
        component.find("input").simulate("click");
      }).then(function () {
        return getDelayedPromise(MOCK_API_DELAY);
      }).then(function () {
        component.update();
        expect(renderedData.availableEntities).toHaveLength(5);
      });
    });
    it("should update the list when a search term is entered", function () {
      return getDelayedPromise().then(function () {
        component.find("input").simulate("mouseenter");
        component.find("input").simulate("click");
        component.find("input").simulate("change", {
          target: {
            value: "123"
          }
        });
      }) // Account for our mock API delay and the debounce delay
      .then(function () {
        return getDelayedPromise(MOCK_API_DELAY + 10);
      }).then(function () {
        component.update();
        expect(renderedData.availableEntities).toHaveLength(1);
        expect(renderedData.availableEntities[0].name).toContain("My feature 123");
      });
    });
    it("should pass isLoading, searchQuery, and availableEntities correctly", function () {
      expect(renderedData.isLoading).toBe(true);
      return getDelayedPromise(MOCK_API_DELAY + 10).then(function () {
        expect(renderedData.searchQuery).toBe("");
        expect(renderedData.isLoading).toBe(false);
        component.find("input").simulate("mouseenter");
        component.find("input").simulate("click");
        component.find("input").simulate("change", {
          target: {
            value: "123"
          }
        });
      }) // Wait for debounce
      .then(function () {
        return getDelayedPromise(10);
      }).then(function () {
        expect(renderedData.searchQuery).toBe("123");
        expect(renderedData.isLoading).toBe(true);
      }) // Account for our mock API delay and the debounce delay
      .then(function () {
        return getDelayedPromise(MOCK_API_DELAY + 10);
      }).then(function () {
        component.update();
        expect(renderedData.isLoading).toBe(false);
        expect(renderedData.availableEntities).toEqual([_mock_data["default"][0]]);
      });
    });
    it("should wait to show results until all queries are completed", function () {
      expect(renderedData.isLoading).toBe(true);
      return getDelayedPromise(MOCK_API_DELAY + 10).then(function () {
        expect(renderedData.resultsText).toEqual({
          summary: "Recently created features"
        });
        component.find("input").simulate("mouseenter");
        component.find("input").simulate("click");
        component.find("input").simulate("change", {
          target: {
            value: "123"
          }
        });
      }) // Wait for debounce
      .then(function () {
        return getDelayedPromise(10);
      }).then(function () {
        expect(renderedData.searchQuery).toBe("123");
        expect(renderedData.isLoading).toBe(true);
        component.update();
        expect(renderedData.resultsText).toEqual({
          summary: 'Searching for "features" matching "123"'
        });
        component.find("input").simulate("mouseenter");
        component.find("input").simulate("click");
        component.find("input").simulate("change", {
          target: {
            value: "202"
          }
        });
      }).then(function () {
        return getDelayedPromise(MOCK_API_DELAY);
      }).then(function () {
        component.update();
        expect(renderedData.resultsText).toEqual({
          summary: 'Searching for "features" matching "202"'
        });
      }) // Account for our mock API delay and the debounce delay
      .then(function () {
        return getDelayedPromise(MOCK_API_DELAY + 10);
      }).then(function () {
        component.update();
        expect(renderedData.isLoading).toBe(false);
        expect(renderedData.resultsText).toEqual({
          summary: 'Found 1 features matching "202"'
        });
      });
    });
    it("should render the number of available entities in the results text", function () {
      // We need to pass in selected entities to properly test this
      component.setProps({
        selectedEntityIds: [202, 205, 207]
      });
      component.update();
      component.find("input").simulate("mouseenter");
      component.find("input").simulate("click");
      component.find("input").simulate("change", {
        target: {
          value: "audience 20"
        }
      });
      return getDelayedPromise(MOCK_API_DELAY + 10).then(function () {
        component.update();
        expect(renderedData.resultsText).toEqual({
          summary: 'Found 4 features matching "audience 20"'
        });
      });
    });
  });
  describe("Custom search result filtering with filterAvailableEntities", function () {
    beforeEach(function () {
      function customSearchResultsFilter(searchResults) {
        return searchResults.filter(function (result) {
          return result.id === 123;
        });
      }

      component = (0, _enzyme.mount)(_react["default"].createElement(_["default"], {
        filterAvailableEntities: customSearchResultsFilter,
        onItemSelected: jest.fn(),
        searchFunction: searchFunction,
        supportedTypes: ["feature"]
      }, function (data) {
        renderedData = data;
        return _react["default"].createElement("div", null, data.renderInput(), _react["default"].createElement("p", null, "A list of entities"));
      }));
    });
    it("should filter based on the criteria defined in the filterAvailableEntities function", function () {
      component.find("input").simulate("mouseenter");
      component.find("input").simulate("click");
      component.find("input").simulate("change", {
        target: {
          value: ""
        }
      });
      return getDelayedPromise(MOCK_API_DELAY + 10).then(function () {
        component.update();
        var _renderedData = renderedData,
            availableEntities = _renderedData.availableEntities;
        expect(availableEntities).toHaveLength(1);
        expect(availableEntities[0].id).toEqual(123);
      });
    });
  });
  describe("searchFunction responses", function () {
    it("should update state when an Array is returned from searchFunction", function () {
      onItemSelectedStub = jest.fn();
      var allGoodSearchFn = jest.fn(function () {
        return new Promise(function (resolve) {
          return resolve([{
            id: 123,
            name: "My feature 123",
            type: "feature",
            description: "A very cool feature"
          }]);
        });
      });
      component = (0, _enzyme.mount)(_react["default"].createElement(_["default"], {
        onItemSelected: onItemSelectedStub,
        searchFunction: allGoodSearchFn,
        supportedTypes: ["feature"]
      }, function (data) {
        renderedData = data;
        return _react["default"].createElement("div", null, data.renderInput(), _react["default"].createElement("p", null, "A list of entities"));
      }));
      return allGoodSearchFn().then(function () {
        var defaultResultsState = component.children().instance().state.defaultResults;
        expect(defaultResultsState).toEqual([{
          id: 123,
          name: "My feature 123",
          type: "feature",
          description: "A very cool feature"
        }]);
      });
    });
    it("should not update state when an object is returned from searchFunction", function () {
      onItemSelectedStub = jest.fn();
      var notGoodSearchFn = jest.fn(function () {
        return new Promise(function (resolve) {
          return resolve({});
        });
      });
      component = (0, _enzyme.mount)(_react["default"].createElement(_["default"], {
        onItemSelected: onItemSelectedStub,
        searchFunction: notGoodSearchFn,
        supportedTypes: ["feature"]
      }, function (data) {
        renderedData = data;
        return _react["default"].createElement("div", null, data.renderInput(), _react["default"].createElement("p", null, "A list of entities"));
      }));
      return notGoodSearchFn().then(function () {
        var defaultResultsState = component.children().instance().state.defaultResults;
        expect(defaultResultsState).toEqual([]);
      });
    });
    it("should not update state when undefined is returned from searchFunction", function () {
      onItemSelectedStub = jest.fn();
      var notGoodSearchFn = jest.fn(function () {
        return new Promise(function (resolve) {
          return resolve(undefined);
        });
      });
      component = (0, _enzyme.mount)(_react["default"].createElement(_["default"], {
        onItemSelected: onItemSelectedStub,
        searchFunction: notGoodSearchFn,
        supportedTypes: ["feature"]
      }, function (data) {
        renderedData = data;
        return _react["default"].createElement("div", null, data.renderInput(), _react["default"].createElement("p", null, "A list of entities"));
      }));
      return notGoodSearchFn().then(function () {
        var defaultResultsState = component.children().instance().state.defaultResults;
        expect(defaultResultsState).toEqual([]);
      });
    });
  });
});