opsdash-app/opsdash/test/useWidgetLayoutManager.test.ts
2026-04-03 14:01:08 +07:00

183 lines
6.1 KiB
TypeScript

import { describe, it, expect, vi } from 'vitest'
import { nextTick, ref } from 'vue'
import { useWidgetLayoutManager } from '../composables/useWidgetLayoutManager'
describe('useWidgetLayoutManager', () => {
const registry = {
test_widget: {
label: 'Test Widget',
defaultLayout: { width: 'half', height: 'm', order: 10 },
},
}
function makeManager() {
return useWidgetLayoutManager({
storageKey: 'opsdash.widgets.test',
widgetsRegistry: registry,
createDefaultTabs: () => ({
tabs: [{ id: 'tab-1', label: 'Overview', widgets: [] }],
defaultTabId: 'tab-1',
}),
normalizeWidgetTabs: (input, fallback) => (input ? input : fallback),
createDashboardPreset: () => [],
dashboardMode: ref('standard'),
deckEnabled: ref(true),
hasInitialLoad: ref(true),
queueSaveRef: ref(vi.fn()),
})
}
it('persists dirty widgets after initial load completes', async () => {
const queueSave = vi.fn()
const hasInitialLoad = ref(false)
const manager = useWidgetLayoutManager({
storageKey: 'opsdash.widgets.test',
widgetsRegistry: {
test_widget: {
label: 'Test Widget',
defaultLayout: { width: 'half', height: 'm', order: 10 },
},
},
createDefaultTabs: () => ({
tabs: [{ id: 'tab-1', label: 'Overview', widgets: [] }],
defaultTabId: 'tab-1',
}),
normalizeWidgetTabs: (input, fallback) => (input ? input : fallback),
createDashboardPreset: () => [],
dashboardMode: ref('standard'),
deckEnabled: ref(true),
hasInitialLoad,
queueSaveRef: ref(queueSave),
})
manager.addWidget('test_widget')
expect(queueSave).not.toHaveBeenCalled()
hasInitialLoad.value = true
await nextTick()
expect(queueSave).toHaveBeenCalledWith(false)
})
it('adds and renames tabs without mutating other tabs', () => {
const manager = makeManager()
manager.addTab('Reports')
expect(manager.layoutTabs.value).toHaveLength(2)
expect(manager.activeTabId.value).toBe(manager.layoutTabs.value[1].id)
manager.renameTab(manager.layoutTabs.value[1].id, 'Weekly')
expect(manager.layoutTabs.value[1].label).toBe('Weekly')
expect(manager.layoutTabs.value[0].label).toBe('Overview')
})
it('switches active widgets per tab', () => {
const manager = makeManager()
manager.addWidget('test_widget')
const firstTabId = manager.activeTabId.value
const firstTabWidgets = manager.widgets.value
expect(firstTabWidgets).toHaveLength(1)
manager.addTab('Secondary')
expect(manager.widgets.value).toHaveLength(0)
manager.setActiveTab(firstTabId)
expect(manager.widgets.value).toHaveLength(1)
})
it('removes tabs and keeps a valid default', () => {
const manager = makeManager()
manager.addTab('Secondary')
const firstTabId = manager.layoutTabs.value[0].id
const secondTabId = manager.layoutTabs.value[1].id
manager.setDefaultTab(secondTabId)
expect(manager.defaultTabId.value).toBe(secondTabId)
manager.removeTab(secondTabId)
expect(manager.layoutTabs.value).toHaveLength(1)
expect(manager.defaultTabId.value).toBe(firstTabId)
expect(manager.activeTabId.value).toBe(firstTabId)
})
it('moves widgets to another tab and activates the destination tab', () => {
const manager = makeManager()
manager.addWidget('test_widget')
manager.addTab('Secondary')
const sourceTabId = manager.layoutTabs.value[0].id
const targetTabId = manager.layoutTabs.value[1].id
const widgetId = manager.layoutTabs.value[0].widgets[0].id
manager.setActiveTab(sourceTabId)
const moved = manager.moveWidgetToTab(widgetId, targetTabId)
expect(moved).toBe(true)
expect(manager.activeTabId.value).toBe(targetTabId)
expect(manager.layoutTabs.value[0].widgets).toHaveLength(0)
expect(manager.layoutTabs.value[1].widgets).toHaveLength(1)
expect(manager.layoutTabs.value[1].widgets[0].id).toBe(widgetId)
})
it('duplicates widgets into another tab without removing the source widget', () => {
const manager = makeManager()
manager.addWidget('test_widget')
manager.addTab('Secondary')
const sourceTabId = manager.layoutTabs.value[0].id
const targetTabId = manager.layoutTabs.value[1].id
const widgetId = manager.layoutTabs.value[0].widgets[0].id
manager.setActiveTab(sourceTabId)
const duplicateId = manager.duplicateWidgetToTab(widgetId, targetTabId)
expect(duplicateId).toBeTruthy()
expect(manager.layoutTabs.value[0].widgets).toHaveLength(1)
expect(manager.layoutTabs.value[1].widgets).toHaveLength(1)
expect(manager.layoutTabs.value[1].widgets[0].id).not.toBe(widgetId)
expect(manager.layoutTabs.value[1].widgets[0].type).toBe('test_widget')
})
it('hides deck widget types when Deck is disabled', () => {
const deckEnabled = ref(false)
const manager = useWidgetLayoutManager({
storageKey: 'opsdash.widgets.test',
widgetsRegistry: {
deck_cards: {
label: 'Deck cards',
defaultLayout: { width: 'half', height: 'm', order: 10 },
},
deck_stats: {
label: 'Deck stats',
defaultLayout: { width: 'half', height: 'm', order: 20 },
},
},
createDefaultTabs: () => ({
tabs: [{
id: 'tab-1',
label: 'Overview',
widgets: [
{ id: 'deck-cards', type: 'deck_cards', options: {}, layout: { width: 'half', height: 'm', order: 10 }, version: 1 },
{ id: 'deck-stats', type: 'deck_stats', options: {}, layout: { width: 'half', height: 'm', order: 20 }, version: 1 },
],
}],
defaultTabId: 'tab-1',
}),
normalizeWidgetTabs: (input, fallback) => (input ? input : fallback),
createDashboardPreset: () => [],
dashboardMode: ref('standard'),
deckEnabled,
hasInitialLoad: ref(true),
queueSaveRef: ref(vi.fn()),
})
expect(manager.widgets.value).toEqual([])
deckEnabled.value = true
expect(manager.widgets.value.map((widget) => widget.type)).toEqual(['deck_cards', 'deck_stats'])
})
})