Files
shopdb-flask/frontend/src/components/emptyTablePanel.spec.js
benjamin.baker f77a288bdc Show empty-state text on empty table panels
A table panel with no rows rendered its column headers over an empty body. On a live PC Details page that made Network Interfaces and Listening Ports look like cards that had failed to load, when the real answer was that the agent had not reported any yet. List panels already honoured panel.empty; table panels did not.

Also records the simulation-suite requirement uncovered when rolling containers: the pytest suite builds its schema from the models, so an unapplied migration is invisible to it while every query against the affected table 500s in the running image.
2026-09-05 07:22:58 -04:00

52 lines
2.0 KiB
JavaScript

import { describe, it, expect } from 'vitest'
import { readFileSync } from 'fs'
import { resolve } from 'path'
// A `table` panel with no rows used to render a bare header row over an empty
// body, which reads as a broken card rather than as an answer. `list` had
// honoured panel.empty for a long time; `table` had not, for no reason anybody
// wrote down. Found on a live page where Network Interfaces and Listening
// Ports both showed column headers and nothing else.
//
// Asserted against the SOURCE because the condition lives in the template, not
// in an exported helper - the same reason panelGroups.spec.js reads source.
const source = readFileSync(
resolve(__dirname, 'PluginAssetPanels.vue'), 'utf8',
)
function tableBlock() {
const start = source.indexOf("panel.render === 'table'")
expect(start).toBeGreaterThan(-1)
// Up to the next render branch, so we only look at the table path.
const end = source.indexOf("panel.render === 'badge'", start)
expect(end).toBeGreaterThan(start)
return source.slice(start, end)
}
describe('an empty table panel', () => {
it('does not render the table element when there are no rows', () => {
expect(tableBlock()).toMatch(/<table[^>]*v-if="rows\(panel\)\.length"/)
})
it('falls back to the panel-declared empty message', () => {
expect(tableBlock()).toContain('panel.empty')
})
it('keeps a default message for a panel that declares none', () => {
// An empty card with no words in it is indistinguishable from a card that
// failed to load.
expect(tableBlock()).toMatch(/panel\.empty \|\| '[^']+'/)
})
})
describe('an empty table SECTION inside a tabs panel', () => {
it('also suppresses its header row', () => {
// The section path was added with the Storage merge and had the same bug.
const start = source.indexOf("panel.render === 'tabs'")
const end = source.indexOf("panel.render === 'keyvalue'", start)
const block = source.slice(start, end)
expect(block).toMatch(/<table\s+v-if="\(\(tabSections\(panel\)/)
})
})