import { describe, it, expect, vi, beforeEach } from 'vitest'; import { mount } from '@vue/test-utils'; import { nextTick } from 'vue'; import DevIndexOverlay from '../../resources/js/components/DevIndexOverlay.vue'; import { useDevIndices } from '../../resources/js/composables/useDevIndices'; describe('DevIndexOverlay', () => { beforeEach(() => useDevIndices().reset()); it('hidden when no current target', () => { mount(DevIndexOverlay, { attachTo: document.body }); expect(document.querySelector('.dx-badge')).toBeNull(); }); it('shows badge with id + tag when target is set', async () => { const el = document.createElement('button'); el.setAttribute('data-dx', '1030'); el.textContent = 'Создать'; document.body.appendChild(el); const dx = useDevIndices(); dx.setTarget(el); mount(DevIndexOverlay, { attachTo: document.body }); await nextTick(); const badge = document.querySelector('.dx-badge'); expect(badge).not.toBeNull(); expect(badge!.textContent).toContain('1030'); expect(badge!.textContent!.toLowerCase()).toContain('button'); document.body.removeChild(el); }); it('Esc clears the target', async () => { const el = document.createElement('div'); el.setAttribute('data-dx', '5'); document.body.appendChild(el); const dx = useDevIndices(); dx.setTarget(el); mount(DevIndexOverlay, { attachTo: document.body }); await nextTick(); document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape' })); await nextTick(); expect(dx.currentId.value).toBeNull(); document.body.removeChild(el); }); it('clicking the badge copies "#" to clipboard', async () => { const writeText = vi.fn().mockResolvedValue(undefined); Object.defineProperty(navigator, 'clipboard', { value: { writeText }, configurable: true, }); const el = document.createElement('button'); el.setAttribute('data-dx', '1030'); document.body.appendChild(el); useDevIndices().setTarget(el); mount(DevIndexOverlay, { attachTo: document.body }); await nextTick(); const badge = document.querySelector('.dx-badge') as HTMLElement; expect(badge).not.toBeNull(); badge.click(); await nextTick(); expect(writeText).toHaveBeenCalledWith('#1030'); document.body.removeChild(el); }); }); describe('DevIndexOverlay — Alt-keys + overlay-mode', () => { beforeEach(() => useDevIndices().reset()); it('Alt+ArrowUp walks to parent', async () => { const grand = document.createElement('div'); grand.setAttribute('data-dx', '100'); const child = document.createElement('button'); child.setAttribute('data-dx', '200'); grand.appendChild(child); document.body.appendChild(grand); const dx = useDevIndices(); dx.setTarget(child); mount(DevIndexOverlay, { attachTo: document.body }); await nextTick(); document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowUp', altKey: true })); await nextTick(); expect(dx.currentId.value).toBe(100); document.body.removeChild(grand); }); it('Alt+ArrowDown walks to first descendant', async () => { const parent = document.createElement('div'); parent.setAttribute('data-dx', '1'); const child = document.createElement('span'); child.setAttribute('data-dx', '2'); parent.appendChild(child); document.body.appendChild(parent); const dx = useDevIndices(); dx.setTarget(parent); mount(DevIndexOverlay, { attachTo: document.body }); await nextTick(); document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown', altKey: true })); await nextTick(); expect(dx.currentId.value).toBe(2); document.body.removeChild(parent); }); it('Alt+Shift+I toggles overlay-mode', async () => { mount(DevIndexOverlay, { attachTo: document.body }); await nextTick(); const dx = useDevIndices(); expect(dx.overlayMode.value).toBe(false); document.dispatchEvent(new KeyboardEvent('keydown', { key: 'I', altKey: true, shiftKey: true })); await nextTick(); expect(dx.overlayMode.value).toBe(true); document.dispatchEvent(new KeyboardEvent('keydown', { key: 'I', altKey: true, shiftKey: true })); await nextTick(); expect(dx.overlayMode.value).toBe(false); }); it('overlay-mode renders mini-badges on all [data-dx] elements', async () => { const a = document.createElement('div'); a.setAttribute('data-dx', '1'); const b = document.createElement('div'); b.setAttribute('data-dx', '2'); document.body.append(a, b); mount(DevIndexOverlay, { attachTo: document.body }); useDevIndices().toggleOverlay(); await nextTick(); const minis = document.querySelectorAll('.dx-mini'); expect(minis.length).toBeGreaterThanOrEqual(2); document.body.removeChild(a); document.body.removeChild(b); }); });