import BmsMenu from '@/components/navigation/BmsMenu.vue';
import { MenuItem } from '@/models/menu.model';
import { mount, MountingOptions, RouterLinkStub } from '@vue/test-utils';
import { nextTick } from 'vue';

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

const intersectionObserverMock = () => ({
  observe: () => null,
});

const menuItems: MenuItem[] = [
  {
    label: 'Item menu 1',
    link: { name: 'link-one' },
    id: 'menu0',
  },
  {
    label: 'Item menu 2',
    link: { name: 'link-two' },
    id: 'menu1',
  },
];

const factory = (options: MountingOptions<any, {}> = {}) => {
  const wrapper = mount(BmsMenu, {
    global: {
      stubs: {
        UiButton: true,
        'router-link': RouterLinkStub,
        teleport: true,
      },
    },
    props: {
      items: menuItems,
    },
    ...options,
  } as any);

  return {
    wrapper,
    toggleMenu: async () => {
      const openMenuButton = wrapper.find('[data-testid="openMenu"]');

      openMenuButton.trigger('click');

      await nextTick();
    },
  };
};

describe('BmsMenu', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    window.IntersectionObserver = vi
      .fn()
      .mockImplementation(intersectionObserverMock);
  });
  it('should toggle menu', async () => {
    const { wrapper, toggleMenu } = factory();

    await toggleMenu();

    expect(wrapper.text()).toContain(menuItems[0].label);

    await toggleMenu();

    expect(wrapper.text()).not.toContain(menuItems[0].label);
  });

  it('should close on X click', async () => {
    const { wrapper, toggleMenu } = factory();

    await toggleMenu();

    wrapper.find('[data-testid="closeMenu"]').trigger('click');

    await nextTick();

    expect(wrapper.text()).not.toContain(menuItems[0].label);
  });

  it('should close on navigation click', async () => {
    const { wrapper, toggleMenu } = factory();

    await toggleMenu();
    wrapper.get('[data-testid="openMenu"]').trigger('click');

    await nextTick();

    expect(wrapper.text()).not.toContain(menuItems[0].label);
  });
});
