opsdash-app/opsdash/test/timeSummaryWidget.test.ts
blade34242 414646dae4
All checks were successful
Nextcloud Server Tests / version-consistency (push) Successful in 33s
Nextcloud Server Tests / matrix-config (push) Successful in 30s
Nextcloud Server Tests / Nextcloud stable31 / PHP 8.2 (stable31, 8.2) (push) Successful in 15m57s
Nextcloud Server Tests / Nextcloud stable31 / PHP 8.3 (stable31, 8.3) (push) Successful in 16m29s
Nextcloud Server Tests / Nextcloud stable32 / PHP 8.2 (stable32, 8.2) (push) Successful in 19m9s
Nextcloud Server Tests / Nextcloud stable32 / PHP 8.3 (stable32, 8.3) (push) Successful in 19m4s
Nextcloud Server Tests / Nextcloud stable33 / PHP 8.2 (stable33, 8.2) (push) Successful in 16m11s
Nextcloud Server Tests / Nextcloud stable33 / PHP 8.3 (stable33, 8.3) (push) Successful in 16m38s
Nextcloud Server Tests / Nextcloud stable34 / PHP 8.2 (stable34, 8.2) (push) Successful in 16m43s
Nextcloud Server Tests / Nextcloud stable34 / PHP 8.3 (stable34, 8.3) (push) Successful in 16m24s
Release 0.8.3 time summary polish
2026-07-12 08:35:46 +07:00

195 lines
6.8 KiB
TypeScript

import { describe, it, expect } from 'vitest'
import { createDefaultTargetsConfig } from '../src/services/targets'
import { widgetsRegistry } from '../src/services/widgetsRegistry'
describe('time summary split widgets', () => {
it('overview widget applies toggle overrides and respects active day mode from options', () => {
const entry = widgetsRegistry.time_summary_overview
const baseCfg = createDefaultTargetsConfig()
const def: any = {
options: {
showTotal: false,
showWeekend: false,
showBalance: false,
showToday: false,
showActivity: false,
showHistoryCoreMetrics: false,
mode: 'all',
},
}
const ctx: any = {
summary: { rangeLabel: 'Week', totalHours: 10 },
activeDayMode: 'active',
groups: [{ id: 'work', label: 'Work', todayHours: 2, color: '#123456' }],
targetsConfig: baseCfg,
}
const props = entry.buildProps(def, ctx) as any
expect(props.mode).toBe('all')
expect(props.config.showTotal).toBe(false)
expect(props.config.showWeekend).toBe(false)
expect(props.config.showBalance).toBe(true)
expect(props.showOverview).toBe(true)
expect(props.showLookback).toBe(false)
expect(props.showToday).toBe(false)
expect(props.showActivity).toBe(false)
expect(props.showDelta).toBe(false)
expect(props.showHistoryCoreMetrics).toBe(false)
expect(props.summary.totalHours).toBe(10)
expect(props.todayGroups?.[0]?.todayHours).toBe(2)
expect(props.showHeader).toBe(true)
expect(Array.isArray(props.history)).toBe(true)
expect(props.history).toHaveLength(0)
})
it('limits overview mini chart to the current widget week only', () => {
const entry = widgetsRegistry.time_summary_overview
const baseCfg = createDefaultTargetsConfig()
const def: any = { options: {} }
const ctx: any = {
summary: { rangeLabel: 'Week', totalHours: 10 },
rangeMode: 'week',
from: '2026-07-05',
to: '2026-07-11',
byDay: [
{ date: '2026-07-04', total_hours: 99, events_count: 9 },
{ date: '2026-07-05', total_hours: 1, events_count: 1 },
{ date: '2026-07-07', total_hours: 3, events_count: 2 },
{ date: '2026-07-12', total_hours: 99, events_count: 9 },
],
targetsConfig: baseCfg,
}
const props = entry.buildProps(def, ctx) as any
expect(props.weekDays.map((day: any) => day.date)).toEqual([
'2026-07-05',
'2026-07-06',
'2026-07-07',
'2026-07-08',
'2026-07-09',
'2026-07-10',
'2026-07-11',
])
expect(props.weekDays.map((day: any) => day.hours)).toEqual([1, 0, 3, 0, 0, 0, 0])
expect(props.weekDays[0].label).toBe('Sun')
})
it('builds category today lanes from calendar groups and today hour maps', () => {
const entry = widgetsRegistry.time_summary_overview
const baseCfg = createDefaultTargetsConfig()
const props = entry.buildProps({ options: {} } as any, {
summary: { rangeLabel: 'Week', totalHours: 10 },
rangeMode: 'week',
from: '2026-07-05',
to: '2026-07-11',
onboardingStrategy: 'full_granular',
targetsConfig: baseCfg,
calendarGroups: [
{ id: 'work', label: 'Work' },
{ id: 'sport', label: 'Sport', todayHours: 1.5 },
],
categoryTodayHours: {
work: 3.25,
sport: 1,
},
categoryColorMap: {
work: '#2563eb',
sport: '#10b981',
},
} as any) as any
expect(props.displayMode).toBe('category_and_calendar_goals')
expect(props.categoryTodayItems).toEqual([
{ id: 'work', label: 'Work', todayHours: 3.25, color: '#2563eb', isUnassigned: false },
{ id: 'sport', label: 'Sport', todayHours: 1.5, color: '#10b981', isUnassigned: false },
])
})
it('does not build the overview mini week chart in month mode', () => {
const entry = widgetsRegistry.time_summary_overview
const baseCfg = createDefaultTargetsConfig()
const props = entry.buildProps({ options: {} } as any, {
summary: { rangeLabel: 'Month', totalHours: 10 },
rangeMode: 'month',
from: '2026-07-01',
to: '2026-07-31',
byDay: [{ date: '2026-07-01', total_hours: 1 }],
targetsConfig: baseCfg,
} as any) as any
expect(props.weekDays).toEqual([])
})
it('lookback widget enables history and hides overview rows', () => {
const entry = widgetsRegistry.time_summary_lookback
const baseCfg = createDefaultTargetsConfig()
const def: any = {
options: {
historyView: 'pills',
showDelta: false,
},
}
const ctx: any = {
summary: { rangeLabel: 'Month', totalHours: 5, todayHours: 1 },
activeDayMode: 'active',
groups: [{ id: 'sport', label: 'Sport', todayHours: 0 }],
targetsConfig: baseCfg,
lookbackWeeks: 4,
charts: {
perDaySeriesByOffset: [
{ offset: 1, from: '2025-12-01', to: '2025-12-07', labels: ['2025-12-01'], series: [{ id: 'cal-1', name: 'A', data: [2] }] },
],
hodByOffset: [{ offset: 1, dows: ['Mon'], matrix: [[2]] }],
summaryByOffset: [{ offset: 1, events: 1 }],
},
calendarCategoryMap: { 'cal-1': 'work' },
calendarGroups: [{ id: 'work', label: 'Work' }],
categoryColorMap: { work: '#2563EB' },
}
const props = entry.buildProps(def, ctx) as any
expect(props.mode).toBe('active')
expect(props.showOverview).toBe(false)
expect(props.showLookback).toBe(true)
expect(props.showToday).toBe(false)
expect(props.showActivity).toBe(false)
expect(props.showDelta).toBe(false)
expect(props.historyView).toBe('accordion')
expect(props.history.length).toBe(1)
expect(baseCfg.timeSummary.showTotal).toBe(true)
expect(baseCfg.timeSummary.showWeekend).toBe(true)
expect(props.showHistoryCoreMetrics).toBe(true)
expect(props.showHeader).toBe(true)
})
it('maps legacy list history layout to timeline', () => {
const entry = widgetsRegistry.time_summary_lookback
const baseCfg = createDefaultTargetsConfig()
const def: any = { options: { historyView: 'list' } }
const ctx: any = {
summary: { rangeLabel: 'Week', totalHours: 10 },
activeDayMode: 'active',
targetsConfig: baseCfg,
lookbackWeeks: 1,
}
const props = entry.buildProps(def, ctx) as any
expect(props.historyView).toBe('timeline')
})
it('passes showHeader when explicitly disabled on lookback widget', () => {
const entry = widgetsRegistry.time_summary_lookback
const baseCfg = createDefaultTargetsConfig()
const def: any = { options: { showHeader: false } }
const ctx: any = {
summary: { rangeLabel: 'Week', totalHours: 10 },
activeDayMode: 'active',
targetsConfig: baseCfg,
lookbackWeeks: 1,
}
const props = entry.buildProps(def, ctx) as any
expect(props.showHeader).toBe(false)
})
})