import { mount } from '@vue/test-utils' import { afterAll, describe, expect, it, vi } from 'vitest' import { defineComponent, inject, onMounted, ref, type Ref } from 'vue' import HeaderBar from '../HeaderBar.vue' import { registerHeaderMenuKey } from '../consts' describe('HeaderBar', () => { vi.mock('@/utils/functions/throttleDisplayFn/throttleDisplayFn.ts', () => ({ default: (fn: (...args: unknown[]) => void) => fn, })) afterAll(() => { vi.restoreAllMocks() document.body.innerHTML = '' }) it('should render the component', async () => { const wrapper = mount(HeaderBar, { props: { headingLevelTitle: 1, sticky: false, }, attachTo: document.body, }) window.dispatchEvent(new CustomEvent('scroll')) expect(wrapper.html()).toMatchSnapshot() // mock scroll related values vi.spyOn(window, 'scrollY', 'get').mockReturnValue(2000) const header = wrapper.find('.header') vi.spyOn(header.element, 'getBoundingClientRect').mockReturnValue({ top: -2000, } as DOMRect) window.dispatchEvent(new CustomEvent('scroll')) await wrapper.vm.$nextTick() const stickyHeader = wrapper.find('.sticky-header') const stickyHeaderStyle = stickyHeader.attributes('style') expect(stickyHeaderStyle).toContain('position: relative;') expect(stickyHeaderStyle).toContain('top: auto;') wrapper.unmount() }) it('should render all the component slots', async () => { const wrapper = mount(HeaderBar, { attachTo: document.body, slots: { 'default': '
Default slot
', 'prepend': '
Prepend slot
', 'append': '
Append slot
', 'menu': '
Menu slot
', 'logo': '
Logo slot
', 'header-side': '
Header side slot
', 'logo-brand-content': '
Logo brand content slot
', }, }) const text = wrapper.text() expect(text).not.toContain('Default slot') expect(text).toContain('Prepend slot') expect(text).toContain('Append slot') expect(text).toContain('Menu slot') expect(text).toContain('Logo slot') expect(text).toContain('Header side slot') expect(text).not.toContain('Logo brand content slot') wrapper.unmount() }) const TestMenu = defineComponent({ setup() { const menu = ref(false) const registerHeaderMenu = inject<(r: Ref) => void>(registerHeaderMenuKey) onMounted(() => { if (registerHeaderMenu) { registerHeaderMenu(menu) } }) return { menu, } }, template: '', }) it('should render the menu slot', async () => { const wrapper = mount({ components: { HeaderBar, TestMenu, }, template: ` `, }, { attachTo: document.body, }) const text = wrapper.text() expect(text).toContain('Menu') expect(text).toContain('the menu is closed') const button = wrapper.find('button') await button.trigger('click') expect(wrapper.text()).toContain('the menu is open') wrapper.unmount() }) it('should render in sticky mode', async () => { const wrapper = mount(HeaderBar, { props: { headingLevelTitle: 1, sticky: true, }, attachTo: document.body, }) window.dispatchEvent(new CustomEvent('scroll')) // mock scroll related values vi.spyOn(window, 'scrollY', 'get').mockReturnValue(2000) const header = wrapper.find('.header') vi.spyOn(header.element, 'getBoundingClientRect').mockReturnValue({ top: -2000, } as DOMRect) window.dispatchEvent(new CustomEvent('scroll')) await wrapper.vm.$nextTick() const stickyHeader = wrapper.find('.sticky-header') const stickyHeaderStyle = stickyHeader.attributes('style') expect(stickyHeaderStyle).toContain('position: fixed;') expect(stickyHeaderStyle).toContain('top: 0px;') wrapper.unmount() }) it('should only show the header when the user scrolls up', async () => { // @ts-expect-error - Property 'happyDOM' does not exist on type 'Window & typeof globalThis'. window.happyDOM.setInnerWidth(600) const wrapper = mount(HeaderBar, { props: { headingLevelTitle: 1, hideWhenDown: true, }, attachTo: document.body, }) window.dispatchEvent(new CustomEvent('scroll')) const header = wrapper.find('.header') const mockHeaderRect = vi.spyOn(header.element, 'getBoundingClientRect') // mock scroll related values const mockScrollY = vi.spyOn(window, 'scrollY', 'get') const mockScrollTop = vi.spyOn(document.documentElement, 'scrollTop', 'get') mockScrollY.mockReturnValue(2000) mockScrollTop.mockReturnValue(2000) mockHeaderRect.mockReturnValue({ top: -2000, height: 77, } as DOMRect) window.dispatchEvent(new CustomEvent('scroll')) await wrapper.vm.$nextTick() const stickyHeader = wrapper.find('.sticky-header') let stickyHeaderStyle = stickyHeader.attributes('style') // Do not show the header when the user scrolls down expect(stickyHeaderStyle).toContain('position: fixed;') expect(stickyHeaderStyle).toContain('top: 0px;') expect(stickyHeaderStyle).toContain('transform: translateY(-100%);') mockScrollY.mockReturnValue(800) mockScrollTop.mockReturnValue(800) mockHeaderRect.mockReturnValue({ top: -800, height: 77, } as DOMRect) window.dispatchEvent(new CustomEvent('scroll')) await wrapper.vm.$nextTick() stickyHeaderStyle = stickyHeader.attributes('style') // Do show the header when the user scrolls up expect(stickyHeaderStyle).toContain('position: fixed;') expect(stickyHeaderStyle).toContain('top: 0px;') expect(stickyHeaderStyle).toContain('transform: none;') wrapper.unmount() }) })