forked from
npmx.dev/npmx.dev
[READ-ONLY]
a fast, modern browser for the npm registry
1import { describe, it, expect, vi, beforeEach } from 'vitest'
2import { computed, nextTick, defineComponent } from 'vue'
3import { mount } from '@vue/test-utils'
4import type * as VueUseCore from '@vueuse/core'
5
6const useSupportedMock = vi.hoisted(() => vi.fn())
7const useMutationObserverMock = vi.hoisted(() => vi.fn())
8const useResizeObserverMock = vi.hoisted(() => vi.fn())
9
10let lastMutationObserverInstance: {
11 observe: ReturnType<typeof vi.fn>
12 disconnect: ReturnType<typeof vi.fn>
13 takeRecords: ReturnType<typeof vi.fn>
14} | null = null
15
16const mutationObserverConstructorMock = vi.hoisted(() =>
17 vi.fn(function MutationObserver() {
18 lastMutationObserverInstance = {
19 observe: vi.fn(),
20 disconnect: vi.fn(),
21 takeRecords: vi.fn(),
22 }
23 return lastMutationObserverInstance
24 }),
25)
26
27vi.mock('@vueuse/core', async () => {
28 const actual = await vi.importActual<typeof VueUseCore>('@vueuse/core')
29 return {
30 ...actual,
31 useSupported: useSupportedMock,
32 useMutationObserver: useMutationObserverMock,
33 useResizeObserver: useResizeObserverMock,
34 }
35})
36
37function mockComputedStyle(values: Record<string, string>) {
38 vi.stubGlobal('getComputedStyle', () => {
39 return {
40 getPropertyValue: (name: string) => values[name] ?? '',
41 } as any
42 })
43}
44
45function mountWithSetup(run: () => void) {
46 return mount(
47 defineComponent({
48 name: 'TestHarness',
49 setup() {
50 run()
51 return () => null
52 },
53 }),
54 { attachTo: document.body },
55 )
56}
57
58describe('useCssVariables', () => {
59 beforeEach(() => {
60 vi.clearAllMocks()
61 vi.resetModules()
62 lastMutationObserverInstance = null
63 vi.stubGlobal('MutationObserver', mutationObserverConstructorMock as any)
64 })
65
66 it('does not attach html mutation observer when client is not supported', async () => {
67 const { useCssVariables } = await import('../../../app/composables/useColors')
68
69 useSupportedMock.mockReturnValueOnce(computed(() => false))
70 mockComputedStyle({ '--bg': 'oklch(1 0 0)' })
71
72 const wrapper = mountWithSetup(() => {
73 const { colors } = useCssVariables(['--bg'], { watchHtmlAttributes: true })
74 expect(colors.value.bg).toBe('oklch(1 0 0)')
75 })
76
77 await nextTick()
78
79 expect(useMutationObserverMock).not.toHaveBeenCalled()
80 expect(lastMutationObserverInstance).not.toBeNull()
81 expect(lastMutationObserverInstance!.observe).toHaveBeenCalledTimes(1)
82
83 wrapper.unmount()
84 })
85
86 it('attaches html mutation observer when client is supported', async () => {
87 const { useCssVariables } = await import('../../../app/composables/useColors')
88
89 useSupportedMock.mockReturnValueOnce(computed(() => true))
90 mockComputedStyle({ '--bg': 'oklch(1 0 0)' })
91
92 const wrapper = mountWithSetup(() => {
93 useCssVariables(['--bg'], { watchHtmlAttributes: true })
94 })
95
96 await nextTick()
97
98 expect(lastMutationObserverInstance).not.toBeNull()
99 expect(lastMutationObserverInstance!.observe).toHaveBeenCalledTimes(1)
100
101 wrapper.unmount()
102 })
103})