Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/components/common/DeviceInfo.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<div class="grid grid-cols-2 gap-2">
<div v-if="props.device" class="grid grid-cols-2 gap-2">
<template v-for="col in deviceColumns" :key="col.field">
<div class="font-medium">
{{ col.header }}
Expand All @@ -9,14 +9,17 @@
</div>
</template>
</div>
<div v-else class="text-red-500">
{{ $t('g.deviceNotAvailable') }}

Check failure on line 13 in src/components/common/DeviceInfo.vue

View workflow job for this annotation

GitHub Actions / test

tests-ui/tests/components/common/DeviceInfo.test.ts > DeviceInfo > SystemStatsPanel integration scenarios - FIXED > should gracefully handle when SystemStats API returns malformed data

TypeError: _ctx.$t is not a function ❯ Proxy._sfc_render src/components/common/DeviceInfo.vue:13:8 ❯ renderComponentRoot node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:6445:16 ❯ ReactiveEffect.componentUpdateFn [as fn] node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5262:46 ❯ ReactiveEffect.run node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19 ❯ setupRenderEffect node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5397:5 ❯ mountComponent node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5172:7 ❯ processComponent node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9 ❯ patch node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11 ❯ ReactiveEffect.componentUpdateFn [as fn] node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5269:11 ❯ ReactiveEffect.run node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19

Check failure on line 13 in src/components/common/DeviceInfo.vue

View workflow job for this annotation

GitHub Actions / test

tests-ui/tests/components/common/DeviceInfo.test.ts > DeviceInfo > SystemStatsPanel integration scenarios - FIXED > should gracefully handle when devices array is empty and accessing devices[0]

TypeError: _ctx.$t is not a function ❯ Proxy._sfc_render src/components/common/DeviceInfo.vue:13:8 ❯ renderComponentRoot node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:6445:16 ❯ ReactiveEffect.componentUpdateFn [as fn] node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5262:46 ❯ ReactiveEffect.run node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19 ❯ setupRenderEffect node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5397:5 ❯ mountComponent node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5172:7 ❯ processComponent node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9 ❯ patch node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11 ❯ ReactiveEffect.componentUpdateFn [as fn] node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5269:11 ❯ ReactiveEffect.run node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19

Check failure on line 13 in src/components/common/DeviceInfo.vue

View workflow job for this annotation

GitHub Actions / test

tests-ui/tests/components/common/DeviceInfo.test.ts > DeviceInfo > SystemStatsPanel integration scenarios - FIXED > should gracefully handle when devices array is empty and accessing devices[0]

TypeError: _ctx.$t is not a function ❯ Proxy._sfc_render src/components/common/DeviceInfo.vue:13:8 ❯ renderComponentRoot node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:6445:16 ❯ ReactiveEffect.componentUpdateFn [as fn] node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5262:46 ❯ ReactiveEffect.run node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19 ❯ setupRenderEffect node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5397:5 ❯ mountComponent node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5172:7 ❯ processComponent node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9 ❯ patch node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11 ❯ ReactiveEffect.componentUpdateFn [as fn] node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5269:11 ❯ ReactiveEffect.run node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19

Check failure on line 13 in src/components/common/DeviceInfo.vue

View workflow job for this annotation

GitHub Actions / test

tests-ui/tests/components/common/DeviceInfo.test.ts > DeviceInfo > SystemStatsPanel integration scenarios - FIXED > should gracefully handle when devices array is empty and accessing devices[0]

TypeError: _ctx.$t is not a function ❯ Proxy._sfc_render src/components/common/DeviceInfo.vue:13:8 ❯ renderComponentRoot node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:6445:16 ❯ ReactiveEffect.componentUpdateFn [as fn] node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5262:46 ❯ ReactiveEffect.run node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19 ❯ setupRenderEffect node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5397:5 ❯ mountComponent node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5172:7 ❯ processComponent node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9 ❯ patch node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11 ❯ ReactiveEffect.componentUpdateFn [as fn] node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5269:11 ❯ ReactiveEffect.run node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19

Check failure on line 13 in src/components/common/DeviceInfo.vue

View workflow job for this annotation

GitHub Actions / test

tests-ui/tests/components/common/DeviceInfo.test.ts > DeviceInfo > Sentry Issue CLOUD-FRONTEND-STAGING-13: undefined device prop - FIXED > should gracefully handle undefined device properties instead of throwing

TypeError: _ctx.$t is not a function ❯ Proxy._sfc_render src/components/common/DeviceInfo.vue:13:8 ❯ renderComponentRoot node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:6445:16 ❯ ReactiveEffect.componentUpdateFn [as fn] node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5262:46 ❯ ReactiveEffect.run node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19 ❯ setupRenderEffect node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5397:5 ❯ mountComponent node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5172:7 ❯ processComponent node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9 ❯ patch node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11 ❯ ReactiveEffect.componentUpdateFn [as fn] node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5269:11 ❯ ReactiveEffect.run node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19

Check failure on line 13 in src/components/common/DeviceInfo.vue

View workflow job for this annotation

GitHub Actions / test

tests-ui/tests/components/common/DeviceInfo.test.ts > DeviceInfo > Sentry Issue CLOUD-FRONTEND-STAGING-13: undefined device prop - FIXED > should gracefully handle undefined device properties instead of throwing

TypeError: _ctx.$t is not a function ❯ Proxy._sfc_render src/components/common/DeviceInfo.vue:13:8 ❯ renderComponentRoot node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:6445:16 ❯ ReactiveEffect.componentUpdateFn [as fn] node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5262:46 ❯ ReactiveEffect.run node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19 ❯ setupRenderEffect node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5397:5 ❯ mountComponent node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5172:7 ❯ processComponent node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9 ❯ patch node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11 ❯ ReactiveEffect.componentUpdateFn [as fn] node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5269:11 ❯ ReactiveEffect.run node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19

Check failure on line 13 in src/components/common/DeviceInfo.vue

View workflow job for this annotation

GitHub Actions / test

tests-ui/tests/components/common/DeviceInfo.test.ts > DeviceInfo > Sentry Issue CLOUD-FRONTEND-STAGING-13: undefined device prop - FIXED > should gracefully handle undefined device properties instead of throwing

TypeError: _ctx.$t is not a function ❯ Proxy._sfc_render src/components/common/DeviceInfo.vue:13:8 ❯ renderComponentRoot node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:6445:16 ❯ ReactiveEffect.componentUpdateFn [as fn] node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5262:46 ❯ ReactiveEffect.run node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19 ❯ setupRenderEffect node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5397:5 ❯ mountComponent node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5172:7 ❯ processComponent node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9 ❯ patch node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11 ❯ ReactiveEffect.componentUpdateFn [as fn] node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5269:11 ❯ ReactiveEffect.run node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19

Check failure on line 13 in src/components/common/DeviceInfo.vue

View workflow job for this annotation

GitHub Actions / test

tests-ui/tests/components/common/DeviceInfo.test.ts > DeviceInfo > Sentry Issue CLOUD-FRONTEND-STAGING-13: undefined device prop - FIXED > should gracefully handle undefined device prop instead of throwing

TypeError: _ctx.$t is not a function ❯ Proxy._sfc_render src/components/common/DeviceInfo.vue:13:8 ❯ renderComponentRoot node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:6445:16 ❯ ReactiveEffect.componentUpdateFn [as fn] node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5262:46 ❯ ReactiveEffect.run node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19 ❯ setupRenderEffect node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5397:5 ❯ mountComponent node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5172:7 ❯ processComponent node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9 ❯ patch node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11 ❯ ReactiveEffect.componentUpdateFn [as fn] node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5269:11 ❯ ReactiveEffect.run node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19

Check failure on line 13 in src/components/common/DeviceInfo.vue

View workflow job for this annotation

GitHub Actions / test

tests-ui/tests/components/common/DeviceInfo.test.ts > DeviceInfo > Sentry Issue CLOUD-FRONTEND-STAGING-13: undefined device prop - FIXED > should gracefully handle undefined device prop instead of throwing

TypeError: _ctx.$t is not a function ❯ Proxy._sfc_render src/components/common/DeviceInfo.vue:13:8 ❯ renderComponentRoot node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:6445:16 ❯ ReactiveEffect.componentUpdateFn [as fn] node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5262:46 ❯ ReactiveEffect.run node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19 ❯ setupRenderEffect node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5397:5 ❯ mountComponent node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5172:7 ❯ processComponent node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9 ❯ patch node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11 ❯ ReactiveEffect.componentUpdateFn [as fn] node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5269:11 ❯ ReactiveEffect.run node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19

Check failure on line 13 in src/components/common/DeviceInfo.vue

View workflow job for this annotation

GitHub Actions / test

tests-ui/tests/components/common/DeviceInfo.test.ts > DeviceInfo > Sentry Issue CLOUD-FRONTEND-STAGING-13: undefined device prop - FIXED > should gracefully handle undefined device prop instead of throwing

TypeError: _ctx.$t is not a function ❯ Proxy._sfc_render src/components/common/DeviceInfo.vue:13:8 ❯ renderComponentRoot node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:6445:16 ❯ ReactiveEffect.componentUpdateFn [as fn] node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5262:46 ❯ ReactiveEffect.run node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19 ❯ setupRenderEffect node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5397:5 ❯ mountComponent node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5172:7 ❯ processComponent node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5125:9 ❯ patch node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:4654:11 ❯ ReactiveEffect.componentUpdateFn [as fn] node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:5269:11 ❯ ReactiveEffect.run node_modules/.pnpm/@VUE[email protected]/node_modules/@vue/reactivity/dist/reactivity.cjs.js:229:19
</div>
</template>

<script setup lang="ts">
import type { DeviceStats } from '@/schemas/apiSchema'
import { formatSize } from '@/utils/formatUtil'

const props = defineProps<{
device: DeviceStats
device: DeviceStats | undefined
}>()

const deviceColumns: { field: keyof DeviceStats; header: string }[] = [
Expand All @@ -29,6 +32,10 @@
]

const formatValue = (value: any, field: string) => {
if (value === undefined || value === null) {
return 'N/A'
}

if (
['vram_total', 'vram_free', 'torch_vram_total', 'torch_vram_free'].includes(
field
Expand Down
40 changes: 28 additions & 12 deletions src/components/common/SystemStatsPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,22 @@
<h2 class="text-2xl font-semibold mb-4">
{{ $t('g.devices') }}
</h2>
<TabView v-if="props.stats.devices.length > 1">
<TabPanel
v-for="device in props.stats.devices"
:key="device.index"
:header="device.name"
:value="device.index"
>
<DeviceInfo :device="device" />
</TabPanel>
</TabView>
<DeviceInfo v-else :device="props.stats.devices[0]" />
<div v-if="props.stats.devices && props.stats.devices.length > 0">
<TabView v-if="props.stats.devices.length > 1">
<TabPanel
v-for="device in props.stats.devices"
:key="device.index"
:header="device.name"
:value="device.index"
>
<DeviceInfo :device="device" />
</TabPanel>
</TabView>
<DeviceInfo v-else :device="props.stats.devices[0]" />
</div>
<div v-else class="text-yellow-600">
{{ $t('g.noDevicesDetected') }}
</div>
</div>
</div>
</template>
Expand All @@ -39,7 +44,7 @@
import Divider from 'primevue/divider'
import TabPanel from 'primevue/tabpanel'
import TabView from 'primevue/tabview'
import { computed } from 'vue'
import { computed, watchEffect } from 'vue'

import DeviceInfo from '@/components/common/DeviceInfo.vue'
import type { SystemStats } from '@/schemas/apiSchema'
Expand Down Expand Up @@ -71,4 +76,15 @@ const formatValue = (value: any, field: string) => {
}
return value
}

// Monitor for missing devices scenario for debugging
watchEffect(() => {
if (!props.stats?.devices || props.stats.devices.length === 0) {
console.warn('[SystemStatsPanel] No devices available in SystemStats:', {
hasDevices: !!props.stats?.devices,
deviceCount: props.stats?.devices?.length || 0,
statsStructure: props.stats ? Object.keys(props.stats) : null
})
}
})
</script>
2 changes: 2 additions & 0 deletions src/locales/en/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
"insert": "Insert",
"systemInfo": "System Info",
"devices": "Devices",
"deviceNotAvailable": "Device information is not available.",
"noDevicesDetected": "No devices detected. This may occur if no GPU devices are available or device enumeration failed.",
"about": "About",
"add": "Add",
"confirm": "Confirm",
Expand Down
167 changes: 167 additions & 0 deletions tests-ui/tests/components/common/DeviceInfo.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import { mount } from '@vue/test-utils'
import { describe, expect, it } from 'vitest'

import DeviceInfo from '@/components/common/DeviceInfo.vue'
import type { DeviceStats } from '@/schemas/apiSchema'

describe('DeviceInfo', () => {
const validDevice: DeviceStats = {
name: 'NVIDIA GeForce RTX 4090',
type: 'cuda',
index: 0,
vram_total: 24564224000,
vram_free: 20564224000,
torch_vram_total: 24564224000,
torch_vram_free: 20564224000
}

const createWrapper = (device: DeviceStats | undefined) => {
return mount(DeviceInfo, {
props: { device } as any
})
}

describe('Normal operation', () => {
it('should render device information correctly with valid device', () => {
const wrapper = createWrapper(validDevice)

expect(wrapper.text()).toContain('NVIDIA GeForce RTX 4090')
expect(wrapper.text()).toContain('cuda')
expect(wrapper.text()).toContain('22.88 GB') // vram_total formatted
expect(wrapper.text()).toContain('19.15 GB') // vram_free formatted
})

it('should display all device columns', () => {
const wrapper = createWrapper(validDevice)
const headers = wrapper.findAll('.font-medium')

expect(headers).toHaveLength(6)
expect(headers[0].text()).toBe('Name')
expect(headers[1].text()).toBe('Type')
expect(headers[2].text()).toBe('VRAM Total')
expect(headers[3].text()).toBe('VRAM Free')
expect(headers[4].text()).toBe('Torch VRAM Total')
expect(headers[5].text()).toBe('Torch VRAM Free')
})
})

describe('Sentry Issue CLOUD-FRONTEND-STAGING-13: undefined device prop - FIXED', () => {
it('should gracefully handle undefined device prop instead of throwing', () => {
// Previously this threw TypeError, now it should render error message
const wrapper = createWrapper(undefined as any)
expect(wrapper.text()).toContain('g.deviceNotAvailable')
expect(wrapper.find('.text-red-500').exists()).toBe(true)
})

it('should gracefully handle undefined device properties instead of throwing', () => {
// Previously threw TypeError: Cannot read properties of undefined (reading 'name')
// Now should render fallback message
const wrapper = mount(DeviceInfo, {
props: { device: undefined as any }
})

expect(wrapper.html()).toContain('g.deviceNotAvailable')
expect(() => wrapper.html()).not.toThrow()
})

it('should fail when formatValue tries to access undefined device fields', () => {
// Simulate the exact scenario from the stack trace
const mockDeviceColumns = [
{ field: 'name', header: 'Name' },
{ field: 'type', header: 'Type' },
{ field: 'vram_total', header: 'VRAM Total' }
]

expect(() => {
const undefinedDevice = undefined as any
mockDeviceColumns.forEach((col) => {
// This simulates: formatValue(props.device[col.field], col.field)
// where props.device is undefined
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
undefinedDevice[col.field] // This should throw
})
}).toThrow(TypeError)
})
})

describe('Edge cases that could lead to undefined device - FIXED', () => {
it('should gracefully handle device with missing required fields', () => {
const incompleteDevice = {
name: 'Test Device'
// Missing required fields: type, index, vram_total, etc.
} as any

const wrapper = createWrapper(incompleteDevice)
expect(wrapper.exists()).toBe(true)
expect(wrapper.text()).toContain('Test Device')
expect(wrapper.text()).toContain('N/A') // Missing fields show as N/A
})

it('should handle device with null values gracefully', () => {
const deviceWithNulls = {
name: null,
type: null,
index: 0,
vram_total: null,
vram_free: null,
torch_vram_total: null,
torch_vram_free: null
} as any

const wrapper = createWrapper(deviceWithNulls)
expect(wrapper.exists()).toBe(true)
expect(wrapper.text()).toContain('N/A') // Null values show as N/A
})
})

describe('SystemStatsPanel integration scenarios - FIXED', () => {
it('should gracefully handle when devices array is empty and accessing devices[0]', () => {
// This simulates the scenario where props.stats.devices[0] is undefined
// because the devices array is empty
const emptyDevicesArray: DeviceStats[] = []

const deviceFromEmptyArray = emptyDevicesArray[0] // undefined
const wrapper = createWrapper(deviceFromEmptyArray)

expect(wrapper.text()).toContain('g.deviceNotAvailable')
expect(() => createWrapper(deviceFromEmptyArray)).not.toThrow()
})

it('should gracefully handle when SystemStats API returns malformed data', () => {
// Simulate API returning data that doesn't match expected schema
const malformedApiResponse = {
system: {
/* valid system data */
},
devices: null // This should be an array but API returned null
}

const deviceFromMalformedData = malformedApiResponse.devices?.[0]
const wrapper = createWrapper(deviceFromMalformedData)

expect(wrapper.text()).toContain('g.deviceNotAvailable')
expect(() => createWrapper(deviceFromMalformedData)).not.toThrow()
})
})

describe('formatValue function edge cases - FIXED', () => {
it('should gracefully handle undefined values in VRAM fields', () => {
const deviceWithUndefinedVram = {
name: 'Test Device',
type: 'cuda',
index: 0,
vram_total: undefined,
vram_free: undefined,
torch_vram_total: undefined,
torch_vram_free: undefined
} as any

// Previously would fail, now should show N/A for undefined VRAM values
const wrapper = createWrapper(deviceWithUndefinedVram)
expect(wrapper.exists()).toBe(true)
expect(wrapper.text()).toContain('Test Device')
expect(wrapper.text()).toContain('cuda')
expect(wrapper.text()).toContain('N/A') // Undefined VRAM values show as N/A
})
})
})
Loading