import './searchbar.js';

describe('Component vnSearchbar', () => {
    let controller;
    let $element;
    let $state;
    let $params;
    let $scope;
    let filter = {id: 1, search: 'needle'};

    beforeEach(ngModule('vnCore'));

    beforeEach(angular.mock.inject(($componentController, $rootScope, _$state_) => {
        $scope = $rootScope.$new();
        $state = _$state_;
        $params = $state.params;

        $params.q = JSON.stringify(filter);

        $element = angular.element(`<div></div>`);
        controller = $componentController('vnSearchbar', {$element, $scope});
        controller.panel = 'vn-client-search-panel';
    }));

    describe('$postLink()', () => {
        it(`should fetch the filter from the state if it's in the filter state`, () => {
            controller.$postLink();

            expect(controller.filter).toEqual(filter);
            expect(controller.searchString).toBe('needle');
            expect(controller.params.length).toBe(1);
        });

        it(`should not fetch the filter from the state if not in the filter state`, () => {
            controller.searchState = 'other.state';
            controller.$postLink();

            expect(controller.filter).toBeNull();
            expect(controller.searchString).toBeNull();
            expect(controller.params.length).toBe(0);
        });
    });

    describe('filter() setter', () => {
        it(`should update the bar params and search`, () => {
            let withoutHours = new Date(2000, 1, 1);
            let withHours = new Date(withoutHours.getTime());
            withHours.setHours(12, 30, 15, 10);

            controller.filter = {
                search: 'needle',
                withHours: withHours.toJSON(),
                withoutHours: withoutHours.toJSON(),
                boolean: true,
                negated: false,
                myObjectProp: {myProp: 1}
            };

            let chips = {};
            for (let param of controller.params || [])
                chips[param.key] = param.chip;

            expect(controller.searchString).toBe('needle');
            expect(chips.withHours).toBe('withHours: 2000-02-01 12:30');
            expect(chips.withoutHours).toBe('withoutHours: 2000-02-01');
            expect(chips.boolean).toBe('boolean');
            expect(chips.negated).toBe('not negated');
            expect(chips.myObjectProp).toBe('myObjectProp');
        });
    });

    describe('shownFilter() getter', () => {
        it(`should return the _filter if not null`, () => {
            controller.filter = filter;
            controller.suggestedFilter = {sugestedParam: 'suggestedValue'};

            expect(controller.shownFilter).toEqual(filter);
        });

        it(`should return the suggested filter if filter is null`, () => {
            controller.filter = null;
            controller.suggestedFilter = {sugestedParam: 'suggestedValue'};

            expect(controller.shownFilter).toEqual(controller.suggestedFilter);
        });
    });

    describe('searchString() setter', () => {
        it(`should clear the whole filter when it's null`, () => {
            controller.filter = filter;
            controller.searchString = null;

            expect(controller.searchString).toBeNull();
            expect(controller.params.length).toBe(0);
        });
    });

    describe('onPanelSubmit()', () => {
        it(`should compact and define the filter`, () => {
            controller.$.popover = {hide: jasmine.createSpy('hide')};

            const filter = {
                id: 1,
                thisKeyShouldBePurged: null,
                alsoThis: [],
                andThis: {emptyProp: undefined, nullProp: null},
                dontForgetThis: [null, undefined],
                myObject: {keepThis: true, butNotThis: null},
                myArray: [null, undefined, true]
            };
            controller.onPanelSubmit(filter);

            expect(controller.filter).toEqual({
                id: 1,
                myObject: {keepThis: true},
                myArray: [true]
            });
        });
    });

    describe('onSubmit()', () => {
        it(`should define the filter`, () => {
            controller.filter = filter;
            controller.searchString = 'mySearch';
            controller.onSubmit();

            expect(controller.filter).toEqual({id: 1, search: 'mySearch'});
        });
    });

    describe('removeParam()', () => {
        it(`should remove the parameter from the filter`, () => {
            controller.filter = filter;
            controller.removeParam(0);

            expect(controller.filter).toEqual({search: 'needle'});
        });
    });

    describe('doSearch()', () => {
        it(`should go to the search state and pass the filter as query param`, () => {
            jest.spyOn($state, 'go');
            controller.searchState = 'search.state';
            controller.doSearch(filter);

            let queryParams = {q: JSON.stringify(filter)};

            expect($state.go).toHaveBeenCalledWith('search.state', queryParams, null);
            expect(controller.filter).toEqual(filter);
        });
    });
});