import { useRoute } from 'vue-router';
import {
  reflectFiltersToPath,
  reflectSearchToPath,
  useSearch,
} from './search.composable';
import { defineComponent, nextTick } from 'vue';
import { mount } from '@vue/test-utils';
import { Filter } from '@/models';

vi.mock('vue-router', () => ({
  useRoute: vi.fn(),
}));

const factory = (props?: any) => {
  return mount(
    defineComponent({
      props: {
        persistent: Boolean || undefined,
        defaultFilters: Object as any,
        defaultFiltersOpened: Boolean || undefined,
      },
      setup(props) {
        return useSearch(
          props.persistent,
          props.defaultFilters || undefined,
          props.defaultFiltersOpened || undefined,
        );
      },
      template: '<div/>',
    }),
    { props: props },
  );
};

let saveUserPrefSpy: any;
let getUserPrefSpy: any;

vi.mock('@/composables/userPref.composable', () => ({
  useUserPref: () => ({
    saveUserPref: saveUserPrefSpy,
    getUserPref: getUserPrefSpy,
  }),
}));

const mockItems = [
  {
    id: 0,
    title: 'little-slug-0',
    checked: true,
    choice: 'choice0',
    level1: { level2: { level3: 'unevaleur' } },
  },
  {
    id: 1,
    title: 'little-slug-1',
    checked: false,
    choice: 'choice1',
    level1: { level2: { level3: 'uneautrevaleur' } },
  },
  {
    id: 2,
    title: 'little-slug-1',
    checked: false,
    level1: { level2: null },
  },
];

describe('search and filter composable', () => {
  let previous: any;
  beforeEach(() => {
    vi.resetAllMocks();
    (useRoute as any).mockImplementation(() => ({ path: 'path' }));
    saveUserPrefSpy = vi.fn().mockImplementation(() => {});
    getUserPrefSpy = vi.fn().mockReturnValue(undefined);
    previous = global.window.location;
    //@ts-ignore
    delete global.window.location;
  });
  afterEach(() => {
    global.window.location = previous;
  });

  describe('search composable', () => {
    describe('reflectSearchToPath', () => {
      test('should add search value in path when it is modified', () => {
        global.window.location = {
          ...previous,
          protocol: 'https:',
          host: 'localhost/',
          pathname: 'path',
          search: '',
        };
        const replaceStateSpy = vi
          .spyOn(global.window.history, 'replaceState')
          .mockImplementation(() => {});
        reflectSearchToPath('toto', 'bms-ui-filter-search');
        const expectedUrl = 'https://localhost/path?bms-ui-filter-search=toto';
        expect(replaceStateSpy).toBeCalledWith(
          { path: expectedUrl },
          '',
          expectedUrl,
        );
      });
      test('should modify search value in path when it is modified', () => {
        global.window.location = {
          ...previous,
          protocol: 'https:',
          host: 'localhost/',
          pathname: 'path',
          search: '?bms-ui-filter-search=toto',
        };
        const replaceStateSpy = vi
          .spyOn(global.window.history, 'replaceState')
          .mockImplementation(() => {});
        reflectSearchToPath('titi', 'bms-ui-filter-search');
        const expectedUrl = 'https://localhost/path?bms-ui-filter-search=titi';
        expect(replaceStateSpy).toBeCalledWith(
          { path: expectedUrl },
          '',
          expectedUrl,
        );
      });
      test('should delete search value in path when it is deleted', () => {
        global.window.location = {
          ...previous,
          protocol: 'https:',
          host: 'localhost/',
          pathname: 'path',
          search: '?bms-ui-filter-search=toto',
        };
        const replaceStateSpy = vi
          .spyOn(global.window.history, 'replaceState')
          .mockImplementation(() => {});
        reflectSearchToPath('', 'bms-ui-filter-search');
        const expectedUrl = 'https://localhost/path';
        expect(replaceStateSpy).toBeCalledWith(
          { path: expectedUrl },
          '',
          expectedUrl,
        );
      });
    });
    describe('initSearch', () => {
      beforeEach(() => {
        vi.spyOn(global.window.history, 'replaceState').mockImplementation(
          () => {},
        );
      });
      it('should not update search if nothing in path or localStorage', async () => {
        global.window.location = {
          ...previous,
          protocol: 'https:',
          host: 'localhost/',
          pathname: 'path',
        };
        const wrapper = factory({ persistent: true });
        await nextTick();
        expect(wrapper.vm.search).toEqual('');
      });
      it('should update search if in path', async () => {
        global.window.location = {
          ...previous,
          protocol: 'https:',
          host: 'localhost/',
          pathname: 'path',
          search: '?bms-ui-filter-search=toto',
        };
        const wrapper = factory({ persistent: true });
        await nextTick();
        expect(wrapper.vm.search).toEqual('toto');
      });
      it('should update search if not in path but in localStorage', async () => {
        global.window.location = {
          ...previous,
          protocol: 'https:',
          host: 'localhost/',
          pathname: 'path',
        };
        getUserPrefSpy = vi.fn().mockReturnValue('tutu');
        const wrapper = factory({ persistent: true });
        await nextTick();
        expect(wrapper.vm.search).toEqual('tutu');
      });
    });
    describe('search change', async () => {
      test('should update path and localStorage', async () => {
        global.window.location = {
          ...previous,
          protocol: 'https:',
          host: 'localhost/',
          pathname: 'path',
          search: '',
        };
        const replaceStateSpy = vi
          .spyOn(global.window.history, 'replaceState')
          .mockImplementation(() => {});
        const wrapper = factory({ persistent: true });
        await nextTick();
        wrapper.vm.search = 'tutu';
        await nextTick();
        const expectedUrl = 'https://localhost/path?bms-ui-filter-search=tutu';
        expect(replaceStateSpy).toBeCalledWith(
          { path: expectedUrl },
          '',
          expectedUrl,
        );
        expect(saveUserPrefSpy).toHaveBeenCalledTimes(1);
      });
    });
  });

  describe('filter composable', () => {
    it('can toggle filters', () => {
      const wrapper = factory();
      expect(wrapper.vm.isFilterVisible).toBeFalsy();
      wrapper.vm.toggleFilters();
      expect(wrapper.vm.isFilterVisible).toBeTruthy();
    });

    it('doesnt filter if no filter values', () => {
      global.window.location = {
        ...previous,
        protocol: 'https:',
        host: 'localhost/',
        pathname: 'path',
      };
      const wrapper = factory();
      wrapper.vm.filters = [
        {
          label: 'toto',
          key: 'choice',
          type: 'input',
        },
      ];
      expect(wrapper.vm.filterItems(mockItems)).toStrictEqual(mockItems);
    });

    it('can filter columns via boolean filter', () => {
      global.window.location = {
        ...previous,
        protocol: 'https:',
        host: 'localhost/',
        pathname: 'path',
      };
      const wrapper = factory();
      wrapper.vm.filters = [
        {
          label: 'toto',
          key: 'checked',
          type: 'boolean',
          value: 'true',
        },
      ];
      expect(wrapper.vm.filterItems(mockItems)).toStrictEqual([mockItems[0]]);
      wrapper.vm.filters = [
        {
          label: 'toto',
          key: 'checked',
          type: 'boolean',
          value: 'false',
        },
      ];
      expect(wrapper.vm.filterItems(mockItems)).toStrictEqual([
        mockItems[1],
        mockItems[2],
      ]);
    });

    it('can filter string column via select', () => {
      global.window.location = {
        ...previous,
        protocol: 'https:',
        host: 'localhost/',
        pathname: 'path',
      };

      const wrapper = factory();
      wrapper.vm.filters = [
        {
          label: 'toto',
          key: 'choice',
          type: 'select',
          value: 'choice0',
        },
      ];
      expect(wrapper.vm.filterItems(mockItems).map((i) => i.id)).toStrictEqual([
        0,
      ]);
    });

    it('can filter string column via input', () => {
      global.window.location = {
        ...previous,
        protocol: 'https:',
        host: 'localhost/',
        pathname: 'path',
      };

      const wrapper = factory();
      wrapper.vm.filters = [
        {
          label: 'toto',
          key: 'choice',
          type: 'input',
          value: 'CHOICE0',
        },
      ];
      expect(wrapper.vm.filterItems(mockItems).map((i) => i.id)).toStrictEqual([
        0,
      ]);
    });

    it('can filter string in complex object column via input', () => {
      global.window.location = {
        ...previous,
        protocol: 'https:',
        host: 'localhost/',
        pathname: 'path',
      };

      const wrapper = factory();
      wrapper.vm.filters = [
        {
          label: 'level3',
          key: 'level1.level2.level3',
          type: 'input',
          value: 'valeur',
        },
      ];
      expect(wrapper.vm.filterItems(mockItems).map((i) => i.id)).toStrictEqual([
        0, 1,
      ]);
    });

    describe('reflectFiltersToPath', () => {
      test('should add search value in path when it is modified', () => {
        global.window.location = {
          ...previous,
          protocol: 'https:',
          host: 'localhost/',
          pathname: 'path',
        };
        const replaceStateSpy = vi
          .spyOn(global.window.history, 'replaceState')
          .mockImplementation(() => {});
        reflectFiltersToPath([
          {
            label: 'input',
            key: 'choice',
            type: 'input',
            value: 'choice0',
          },
          {
            label: 'boolean',
            key: 'checked',
            type: 'boolean',
            value: 'false',
          },
          {
            label: 'select',
            key: 'select',
            type: 'select',
            selectOptions: [{ label: 'label', value: 'val1' }],
            value: 'val1',
          },
        ]);
        const expectedUrl =
          'https://localhost/path?bms-ui-filter-choice=choice0&bms-ui-filter-checked=false&bms-ui-filter-select=val1';
        expect(replaceStateSpy).toBeCalledWith(
          { path: expectedUrl },
          '',
          expectedUrl,
        );
      });
      test('should modify filter value in path when it is modified', () => {
        global.window.location = {
          ...previous,
          protocol: 'https:',
          host: 'localhost/',
          pathname: 'path',
          search:
            '?bms-ui-filter-choice=choice0&bms-ui-filter-checked=false&bms-ui-filter-select=val1',
        };
        const replaceStateSpy = vi
          .spyOn(global.window.history, 'replaceState')
          .mockImplementation(() => {});
        reflectFiltersToPath([
          {
            label: 'input',
            key: 'choice',
            type: 'input',
            value: 'choice1',
          },
          {
            label: 'boolean',
            key: 'checked',
            type: 'boolean',
            value: 'false',
          },
          {
            label: 'select',
            key: 'select',
            type: 'select',
            selectOptions: [{ label: 'label', value: 'val1' }],
            value: 'val1',
          },
        ]);
        const expectedUrl =
          'https://localhost/path?bms-ui-filter-choice=choice1&bms-ui-filter-checked=false&bms-ui-filter-select=val1';
        expect(replaceStateSpy).toBeCalledWith(
          { path: expectedUrl },
          '',
          expectedUrl,
        );
      });
      test('should delete filter value in path when it is deleted', () => {
        global.window.location = {
          ...previous,
          protocol: 'https:',
          host: 'localhost/',
          pathname: 'path',
          search:
            '?bms-ui-filter-choice=choice0&bms-ui-filter-checked=false&bms-ui-filter-select=val1',
        };
        const replaceStateSpy = vi
          .spyOn(global.window.history, 'replaceState')
          .mockImplementation(() => {});
        reflectFiltersToPath([
          {
            label: 'input',
            key: 'choice',
            type: 'input',
            value: '',
          },
          {
            label: 'boolean',
            key: 'checked',
            type: 'boolean',
            value: 'false',
          },
          {
            label: 'select',
            key: 'select',
            type: 'select',
            selectOptions: [{ label: 'label', value: 'val1' }],
            value: 'val1',
          },
        ]);
        const expectedUrl =
          'https://localhost/path?bms-ui-filter-checked=false&bms-ui-filter-select=val1';
        expect(replaceStateSpy).toBeCalledWith(
          { path: expectedUrl },
          '',
          expectedUrl,
        );
      });
    });

    describe('initFilters', () => {
      test('should not init filter values if no reflect', async () => {
        const wrapper = factory({
          persistent: false,
          defaultFilters: [
            {
              label: 'input',
              key: 'choice',
              type: 'input',
            },
            {
              label: 'boolean',
              key: 'checked',
              type: 'boolean',
            },
            {
              label: 'select',
              key: 'select',
              type: 'select',
              selectOptions: [{ label: 'label', value: 'val1' }],
            },
          ],
          defaultFiltersOpened: false,
        });
        await nextTick();
        expect(wrapper.vm.filters).toStrictEqual([
          {
            label: 'input',
            key: 'choice',
            type: 'input',
            value: null,
          },
          {
            label: 'boolean',
            key: 'checked',
            type: 'boolean',
            value: null,
          },
          {
            label: 'select',
            key: 'select',
            type: 'select',
            selectOptions: [{ label: 'label', value: 'val1' }],
            value: null,
          },
        ]);
      });
      test('should set filter value with path value', async () => {
        global.window.location = {
          ...previous,
          protocol: 'https:',
          host: 'localhost/',
          pathname: 'path',
          search:
            '?bms-ui-filter-choice=choice0&bms-ui-filter-checked=false&bms-ui-filter-select=val1',
        };
        const replaceStateSpy = vi
          .spyOn(global.window.history, 'replaceState')
          .mockImplementation(() => {});

        const wrapper = factory({
          persistent: true,
          defaultFilters: [
            {
              label: 'input',
              key: 'choice',
              type: 'input',
            },
            {
              label: 'boolean',
              key: 'checked',
              type: 'boolean',
            },
            {
              label: 'select',
              key: 'select',
              type: 'select',
              selectOptions: [{ label: 'label', value: 'val1' }],
            },
          ],
        });
        await nextTick();

        expect(wrapper.vm.filters).toStrictEqual([
          {
            label: 'input',
            key: 'choice',
            type: 'input',
            value: 'choice0',
          },
          {
            label: 'boolean',
            key: 'checked',
            type: 'boolean',
            value: false,
          },
          {
            label: 'select',
            key: 'select',
            type: 'select',
            selectOptions: [{ label: 'label', value: 'val1' }],
            value: 'val1',
          },
        ]);
      });
      test('should get info from localStorage if no value in path', async () => {
        global.window.location = {
          ...previous,
          protocol: 'https:',
          host: 'localhost/',
          pathname: 'path',
        };
        const replaceStateSpy = vi
          .spyOn(global.window.history, 'replaceState')
          .mockImplementation(() => {});
        getUserPrefSpy = vi.fn().mockImplementation((...params: any[]) => {
          if (params[0] === 'bms-ui-filter-choice') {
            return 'tutu';
          }
          return undefined;
        });

        const wrapper = factory({
          persistent: true,
          defaultFilters: [
            {
              label: 'input',
              key: 'choice',
              type: 'input',
            },
            {
              label: 'boolean',
              key: 'checked',
              type: 'boolean',
            },
            {
              label: 'select',
              key: 'select',
              type: 'select',
              selectOptions: [{ label: 'label', value: 'val1' }],
            },
          ],
        });
        await nextTick();
        expect(wrapper.vm.filters).toStrictEqual([
          {
            label: 'input',
            key: 'choice',
            type: 'input',
            value: 'tutu',
          },
          {
            label: 'boolean',
            key: 'checked',
            type: 'boolean',
            value: null,
          },
          {
            label: 'select',
            key: 'select',
            type: 'select',
            selectOptions: [{ label: 'label', value: 'val1' }],
            value: null,
          },
        ]);
      });
    });

    describe('filters change', async () => {
      test('should update path and localStorage', async () => {
        global.window.location = {
          ...previous,
          protocol: 'https:',
          host: 'localhost/',
          pathname: 'path',
        };
        const replaceStateSpy = vi
          .spyOn(global.window.history, 'replaceState')
          .mockImplementation(() => {});
        const wrapper = factory({
          persistent: true,
          defaultFilters: [
            {
              label: 'input',
              key: 'choice',
              type: 'input',
            },
            {
              label: 'boolean',
              key: 'checked',
              type: 'boolean',
            },
            {
              label: 'select',
              key: 'select',
              type: 'select',
              selectOptions: [{ label: 'label', value: 'val1' }],
            },
          ],
        });
        await nextTick();
        expect(saveUserPrefSpy).toHaveBeenCalledTimes(3);
        wrapper.vm.filters = [
          {
            label: 'input',
            key: 'choice',
            type: 'input',
            value: 'tutu',
          },
          {
            label: 'boolean',
            key: 'checked',
            type: 'boolean',
            value: false,
          },
          {
            label: 'select',
            key: 'select',
            type: 'select',
            selectOptions: [{ label: 'label', value: 'val1' }],
            value: 'val1',
          },
        ];
        await nextTick();
        const expectedUrl =
          'https://localhost/path?bms-ui-filter-choice=tutu&bms-ui-filter-checked=false&bms-ui-filter-select=val1';
        expect(replaceStateSpy).toBeCalledWith(
          { path: expectedUrl },
          '',
          expectedUrl,
        );
        expect(saveUserPrefSpy).toHaveBeenCalledTimes(6);
      });
    });

    describe('isSavedFilterActive', () => {
      test('should return false if value are not the same', async () => {
        global.window.location = {
          ...previous,
          protocol: 'https:',
          host: 'localhost/',
          pathname: 'path',
        };
        const replaceStateSpy = vi
          .spyOn(global.window.history, 'replaceState')
          .mockImplementation(() => {});

        const wrapper = factory({
          defaultFilters: [
            {
              label: 'input',
              key: 'choice',
              type: 'input',
            },
            {
              label: 'boolean',
              key: 'checked',
              type: 'boolean',
            },
            {
              label: 'select',
              key: 'select',
              type: 'select',
              selectOptions: [{ label: 'label', value: 'val1' }],
            },
          ],
        });
        await nextTick();
        wrapper.vm.filters = [
          {
            label: 'input',
            key: 'choice',
            type: 'input',
            value: 'tutu',
          },
          {
            label: 'boolean',
            key: 'checked',
            type: 'boolean',
            value: false,
          },
          {
            label: 'select',
            key: 'select',
            type: 'select',
            selectOptions: [{ label: 'label', value: 'val1' }],
            value: 'val1',
          },
        ];
        await nextTick();
        expect(
          wrapper.vm.isSavedFilterActive({
            id: 'saved',
            name: 'saved filter',
            route: 'route',
            filters: [
              {
                target: 'choice',
                value: 'tata',
              },
              {
                target: 'checked',
                value: false,
              },
              {
                target: 'select',
                value: 'val1',
              },
            ],
          }),
        ).toEqual(false);
      });
      test('should return true if value are the same', async () => {
        global.window.location = {
          ...previous,
          protocol: 'https:',
          host: 'localhost/',
          pathname: 'path',
        };
        const replaceStateSpy = vi
          .spyOn(global.window.history, 'replaceState')
          .mockImplementation(() => {});

        const wrapper = factory({
          defaultFilters: [
            {
              label: 'input',
              key: 'choice',
              type: 'input',
            },
            {
              label: 'boolean',
              key: 'checked',
              type: 'boolean',
            },
            {
              label: 'select',
              key: 'select',
              type: 'select',
              selectOptions: [{ label: 'label', value: 'val1' }],
            },
          ],
        });
        await nextTick();
        wrapper.vm.filters = [
          {
            label: 'input',
            key: 'choice',
            type: 'input',
            value: 'tutu',
          },
          {
            label: 'boolean',
            key: 'checked',
            type: 'boolean',
            value: false,
          },
          {
            label: 'select',
            key: 'select',
            type: 'select',
            selectOptions: [{ label: 'label', value: 'val1' }],
            value: 'val1',
          },
        ];
        await nextTick();
        expect(
          wrapper.vm.isSavedFilterActive({
            id: 'saved',
            name: 'saved filter',
            route: 'route',
            filters: [
              {
                target: 'choice',
                value: 'tutu',
              },
              {
                target: 'checked',
                value: false,
              },
              {
                target: 'select',
                value: 'val1',
              },
            ],
          }),
        ).toEqual(true);
      });
      test('should return true if value are similar with nullable', async () => {
        global.window.location = {
          ...previous,
          protocol: 'https:',
          host: 'localhost/',
          pathname: 'path',
        };
        const replaceStateSpy = vi
          .spyOn(global.window.history, 'replaceState')
          .mockImplementation(() => {});

        const wrapper = factory({
          defaultFilters: [
            {
              label: 'input',
              key: 'choice',
              type: 'input',
            },
            {
              label: 'boolean',
              key: 'checked',
              type: 'boolean',
            },
            {
              label: 'select',
              key: 'select',
              type: 'select',
              selectOptions: [{ label: 'label', value: 'val1' }],
            },
          ],
        });
        await nextTick();
        wrapper.vm.filters = [
          {
            label: 'input',
            key: 'choice',
            type: 'input',
            value: '',
          },
          {
            label: 'boolean',
            key: 'checked',
            type: 'boolean',
            value: false,
          },
          {
            label: 'select',
            key: 'select',
            type: 'select',
            selectOptions: [{ label: 'label', value: 'val1' }],
            value: '',
          },
        ];
        await nextTick();
        expect(
          wrapper.vm.isSavedFilterActive({
            id: 'saved',
            name: 'saved filter',
            route: 'route',
            filters: [
              {
                target: 'choice',
                value: null,
              },
              {
                target: 'checked',
                value: false,
              },
              {
                target: 'select',
                value: null,
              },
            ],
          }),
        ).toEqual(true);
      });
      test('should return true if value are similar with nullable 2', async () => {
        global.window.location = {
          ...previous,
          protocol: 'https:',
          host: 'localhost/',
          pathname: 'path',
        };
        const replaceStateSpy = vi
          .spyOn(global.window.history, 'replaceState')
          .mockImplementation(() => {});

        const wrapper = factory({
          defaultFilters: [
            {
              label: 'input',
              key: 'choice',
              type: 'input',
            },
            {
              label: 'boolean',
              key: 'checked',
              type: 'boolean',
            },
            {
              label: 'select',
              key: 'select',
              type: 'select',
              selectOptions: [{ label: 'label', value: 'val1' }],
            },
          ],
        });
        await nextTick();
        wrapper.vm.filters = [
          {
            label: 'input',
            key: 'choice',
            type: 'input',
            value: null,
          },
          {
            label: 'boolean',
            key: 'checked',
            type: 'boolean',
            value: false,
          },
          {
            label: 'select',
            key: 'select',
            type: 'select',
            selectOptions: [{ label: 'label', value: 'val1' }],
            value: null,
          },
        ];
        await nextTick();
        expect(
          wrapper.vm.isSavedFilterActive({
            id: 'saved',
            name: 'saved filter',
            route: 'route',
            filters: [
              {
                target: 'choice',
                value: '',
              },
              {
                target: 'checked',
                value: false,
              },
              {
                target: 'select',
                value: '',
              },
            ],
          }),
        ).toEqual(true);
      });
    });

    describe('resetFilters', () => {
      test('should reset all filters', async () => {
        global.window.location = {
          ...previous,
          protocol: 'https:',
          host: 'localhost/',
          pathname: 'path',
        };
        const replaceStateSpy = vi
          .spyOn(global.window.history, 'replaceState')
          .mockImplementation(() => {});

        const wrapper = factory({
          defaultFilters: [
            {
              label: 'input',
              key: 'choice',
              type: 'input',
            },
            {
              label: 'boolean',
              key: 'checked',
              type: 'boolean',
            },
            {
              label: 'between',
              key: 'date',
              type: 'betweenDate',
            },
            {
              label: 'select',
              key: 'select',
              type: 'select',
              selectOptions: [{ label: 'label', value: 'val1' }],
            },
          ],
        });
        await nextTick();
        wrapper.vm.filters = [
          {
            label: 'input',
            key: 'choice',
            type: 'input',
            value: 'toto',
          },
          {
            label: 'boolean',
            key: 'checked',
            type: 'boolean',
            value: false,
          },
          {
            label: 'between',
            key: 'date',
            type: 'betweenDate',
            valueFrom: '2009/06/21',
            valueTo: '2009/12/31',
          },
          {
            label: 'select',
            key: 'select',
            type: 'select',
            selectOptions: [{ label: 'label', value: 'val1' }],
            value: 'val1',
          },
        ];
        await nextTick();
        wrapper.vm.resetFilters();
        await nextTick();
        expect(wrapper.vm.filters).toEqual([
          {
            label: 'input',
            key: 'choice',
            type: 'input',
            value: null,
          },
          {
            label: 'boolean',
            key: 'checked',
            type: 'boolean',
            value: null,
          },
          {
            label: 'between',
            key: 'date',
            type: 'betweenDate',
            valueFrom: null,
            valueTo: null,
          },
          {
            label: 'select',
            key: 'select',
            type: 'select',
            selectOptions: [{ label: 'label', value: 'val1' }],
            value: null,
          },
        ]);
      });
    });

    describe('selectSavedFilter', () => {
      test('should apply a savedFilter', async () => {
        global.window.location = {
          ...previous,
          protocol: 'https:',
          host: 'localhost/',
          pathname: 'path',
        };
        const replaceStateSpy = vi
          .spyOn(global.window.history, 'replaceState')
          .mockImplementation(() => {});

        const wrapper = factory({
          defaultFilters: [
            {
              label: 'input',
              key: 'choice',
              type: 'input',
            },
            {
              label: 'boolean',
              key: 'checked',
              type: 'boolean',
            },
            {
              label: 'select',
              key: 'select',
              type: 'select',
              selectOptions: [{ label: 'label', value: 'val1' }],
            },
          ],
        });
        await nextTick();
        wrapper.vm.filters = [
          {
            label: 'input',
            key: 'choice',
            type: 'input',
            value: null,
          },
          {
            label: 'boolean',
            key: 'checked',
            type: 'boolean',
            value: false,
          },
          {
            label: 'select',
            key: 'select',
            type: 'select',
            selectOptions: [{ label: 'label', value: 'val1' }],
            value: null,
          },
        ];
        await nextTick();
        wrapper.vm.selectSavedFilter({
          id: 'saved',
          name: 'saved filter',
          route: 'route',
          filters: [
            {
              target: 'choice',
              value: 'toto',
            },
            {
              target: 'checked',
              value: true,
            },
            {
              target: 'select',
              value: 'val1',
            },
          ],
        });
        await nextTick();
        expect(wrapper.vm.filters).toEqual([
          {
            label: 'input',
            key: 'choice',
            type: 'input',
            value: 'toto',
          },
          {
            label: 'boolean',
            key: 'checked',
            type: 'boolean',
            value: true,
          },
          {
            label: 'select',
            key: 'select',
            type: 'select',
            selectOptions: [{ label: 'label', value: 'val1' }],
            value: 'val1',
          },
        ]);
      });
      test('should reset filters if the saved filter is already selected', async () => {
        global.window.location = {
          ...previous,
          protocol: 'https:',
          host: 'localhost/',
          pathname: 'path',
        };
        const replaceStateSpy = vi
          .spyOn(global.window.history, 'replaceState')
          .mockImplementation(() => {});

        const wrapper = factory({
          defaultFilters: [
            {
              label: 'input',
              key: 'choice',
              type: 'input',
            },
            {
              label: 'boolean',
              key: 'checked',
              type: 'boolean',
            },
            {
              label: 'select',
              key: 'select',
              type: 'select',
              selectOptions: [{ label: 'label', value: 'val1' }],
            },
          ],
        });
        await nextTick();
        wrapper.vm.filters = [
          {
            label: 'input',
            key: 'choice',
            type: 'input',
            value: 'toto',
          },
          {
            label: 'boolean',
            key: 'checked',
            type: 'boolean',
            value: true,
          },
          {
            label: 'select',
            key: 'select',
            type: 'select',
            selectOptions: [{ label: 'label', value: 'val1' }],
            value: 'val1',
          },
        ];
        await nextTick();
        wrapper.vm.selectSavedFilter({
          id: 'saved',
          name: 'saved filter',
          route: 'route',
          filters: [
            {
              target: 'choice',
              value: 'toto',
            },
            {
              target: 'checked',
              value: true,
            },
            {
              target: 'select',
              value: 'val1',
            },
          ],
        });
        await nextTick();
        expect(wrapper.vm.filters).toEqual([
          {
            label: 'input',
            key: 'choice',
            type: 'input',
            value: null,
          },
          {
            label: 'boolean',
            key: 'checked',
            type: 'boolean',
            value: null,
          },
          {
            label: 'select',
            key: 'select',
            type: 'select',
            selectOptions: [{ label: 'label', value: 'val1' }],
            value: null,
          },
        ]);
      });
    });

    describe('updateFiltersFromProps', () => {
      test('should update select options', () => {
        const wrapper = factory();
        const filter: Filter = {
          key: 'filter0',
          label: 'Zéro',
          type: 'select',
          selectOptions: [{ label: 'option1', value: '1' }],
          value: 1,
        };

        wrapper.vm.filters = [filter];
        wrapper.vm.updateFiltersFromProps([{ ...filter, selectOptions: [] }]);
        expect(wrapper.vm.filters).toStrictEqual([
          { ...filter, selectOptions: [], value: null },
        ]);
      });

      test('should not change filter other than options', () => {
        const wrapper = factory();
        const filter: Filter = {
          key: 'filter0',
          label: 'Zéro',
          type: 'select',
          selectOptions: [{ label: 'option1', value: '1' }],
        };

        wrapper.vm.filters = [filter];
        wrapper.vm.updateFiltersFromProps([
          {
            key: 'filter0',
            label: 'new label',
            type: 'input',
            selectOptions: [{ label: 'option1', value: '1' }],
          },
        ]);
        expect(wrapper.vm.filters).toStrictEqual([filter]);
      });
      test('should keep value if is in new options', () => {
        const wrapper = factory();
        const filter: Filter = {
          key: 'filter0',
          label: 'Zéro',
          type: 'select',
          selectOptions: [
            { label: 'option1', value: '1' },
            { label: 'option2', value: '2' },
          ],
        };

        wrapper.vm.filters = [filter];
        wrapper.vm.updateFiltersFromProps([
          {
            key: 'filter0',
            label: 'Zéro',
            type: 'select',
            selectOptions: [
              { label: 'option1', value: '1' },
              { label: 'option3', value: '3' },
            ],
          },
        ]);
        expect(wrapper.vm.filters).toStrictEqual([
          {
            ...filter,
            selectOptions: [
              { label: 'option1', value: '1' },
              { label: 'option3', value: '3' },
            ],
          },
        ]);
      });
    });
  });
});
