Skip to content

Commit 2e870ad

Browse files
authored
fix: calculation memory on hardware and system monitor (#5922)
1 parent 7dec980 commit 2e870ad

File tree

3 files changed

+181
-7
lines changed

3 files changed

+181
-7
lines changed
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
import { describe, it, expect, beforeEach, vi } from 'vitest'
2+
import { render, screen, waitFor } from '@testing-library/react'
3+
import '@testing-library/jest-dom'
4+
5+
// Mock all the dependencies with minimal implementation
6+
vi.mock('@/containers/SettingsMenu', () => ({
7+
default: () => <div data-testid="settings-menu">Settings Menu</div>,
8+
}))
9+
10+
vi.mock('@/containers/HeaderPage', () => ({
11+
default: ({ children }: { children: React.ReactNode }) => (
12+
<div data-testid="header-page">{children}</div>
13+
),
14+
}))
15+
16+
vi.mock('@/containers/Card', () => ({
17+
Card: ({ title, children }: { title?: string; children: React.ReactNode }) => (
18+
<div data-testid="card">
19+
{title && <div>{title}</div>}
20+
{children}
21+
</div>
22+
),
23+
CardItem: ({ title, actions }: { title?: string; actions?: React.ReactNode }) => (
24+
<div data-testid="card-item">
25+
{title && <div>{title}</div>}
26+
{actions}
27+
</div>
28+
),
29+
}))
30+
31+
vi.mock('@/components/ui/switch', () => ({
32+
Switch: ({ checked }: { checked: boolean }) => (
33+
<input data-testid="switch" type="checkbox" checked={checked} readOnly />
34+
),
35+
}))
36+
37+
vi.mock('@/components/ui/progress', () => ({
38+
Progress: ({ value }: { value: number }) => (
39+
<div data-testid="progress">Progress: {value}%</div>
40+
),
41+
}))
42+
43+
vi.mock('@/i18n/react-i18next-compat', () => ({
44+
useTranslation: () => ({ t: (key: string) => key }),
45+
}))
46+
47+
vi.mock('@/hooks/useHardware', () => ({
48+
useHardware: () => ({
49+
hardwareData: {
50+
os_type: 'windows',
51+
os_name: 'Windows 11',
52+
cpu: { name: 'Intel i7', arch: 'x64', core_count: 8, extensions: ['SSE'] },
53+
total_memory: 16384,
54+
},
55+
systemUsage: { cpu: 50, used_memory: 8192 },
56+
setHardwareData: vi.fn(),
57+
updateSystemUsage: vi.fn(),
58+
pollingPaused: false,
59+
}),
60+
}))
61+
62+
vi.mock('@/hooks/useLlamacppDevices', () => ({
63+
useLlamacppDevices: () => ({
64+
devices: [{ id: 'gpu0', name: 'RTX 3080', mem: 10240, free: 8192 }],
65+
loading: false,
66+
error: null,
67+
activatedDevices: new Set(['gpu0']),
68+
toggleDevice: vi.fn(),
69+
fetchDevices: vi.fn(),
70+
}),
71+
getState: () => ({ setActivatedDevices: vi.fn() }),
72+
}))
73+
74+
vi.mock('@/hooks/useModelProvider', () => ({
75+
useModelProvider: () => ({
76+
providers: [{ provider: 'llamacpp' }],
77+
getProviderByName: vi.fn(() => ({ settings: [{ key: 'device', controller_props: { value: 'gpu0' } }] })),
78+
}),
79+
}))
80+
81+
vi.mock('@/services/hardware', () => ({
82+
getHardwareInfo: vi.fn(() => Promise.resolve({})),
83+
getSystemUsage: vi.fn(() => Promise.resolve({})),
84+
}))
85+
86+
vi.mock('@/services/models', () => ({ stopAllModels: vi.fn() }))
87+
vi.mock('@/lib/utils', () => ({ formatMegaBytes: (mb: number) => `${mb} MB` }))
88+
vi.mock('@/utils/number', () => ({ toNumber: (n: number) => n }))
89+
vi.mock('@tauri-apps/api/webviewWindow', () => ({ WebviewWindow: vi.fn() }))
90+
vi.mock('@/constants/routes', () => ({
91+
route: {
92+
settings: {
93+
hardware: '/settings/hardware'
94+
},
95+
systemMonitor: '/monitor'
96+
}
97+
}))
98+
vi.mock('@/constants/windows', () => ({ windowKey: { systemMonitorWindow: 'monitor' } }))
99+
vi.mock('@tabler/icons-react', () => ({ IconDeviceDesktopAnalytics: () => <div data-testid="icon" /> }))
100+
101+
// Mock the route structure properly
102+
vi.mock('@tanstack/react-router', () => ({
103+
createFileRoute: () => (config: any) => config,
104+
}))
105+
106+
global.IS_MACOS = false
107+
108+
// Import the actual component after all mocks are set up
109+
import { Route } from '../hardware'
110+
111+
describe('Hardware Settings', () => {
112+
beforeEach(() => {
113+
vi.clearAllMocks()
114+
global.IS_MACOS = false
115+
})
116+
117+
it('renders hardware settings page', () => {
118+
const Component = Route.component as React.ComponentType
119+
render(<Component />)
120+
121+
expect(screen.getByTestId('header-page')).toBeInTheDocument()
122+
expect(screen.getByTestId('settings-menu')).toBeInTheDocument()
123+
})
124+
125+
it('displays OS information', async () => {
126+
const Component = Route.component as React.ComponentType
127+
render(<Component />)
128+
129+
await waitFor(() => {
130+
expect(screen.getByText('settings:hardware.os')).toBeInTheDocument()
131+
expect(screen.getByText('windows')).toBeInTheDocument()
132+
})
133+
})
134+
135+
it('displays CPU information', async () => {
136+
const Component = Route.component as React.ComponentType
137+
render(<Component />)
138+
139+
await waitFor(() => {
140+
expect(screen.getByText('settings:hardware.cpu')).toBeInTheDocument()
141+
expect(screen.getByText('Intel i7')).toBeInTheDocument()
142+
})
143+
})
144+
145+
it('displays memory information', async () => {
146+
const Component = Route.component as React.ComponentType
147+
render(<Component />)
148+
149+
await waitFor(() => {
150+
expect(screen.getByText('settings:hardware.memory')).toBeInTheDocument()
151+
})
152+
})
153+
154+
it('displays GPU devices on non-macOS', async () => {
155+
global.IS_MACOS = false
156+
const Component = Route.component as React.ComponentType
157+
render(<Component />)
158+
159+
await waitFor(() => {
160+
expect(screen.getByText('GPUs')).toBeInTheDocument()
161+
expect(screen.getByText('RTX 3080')).toBeInTheDocument()
162+
})
163+
})
164+
165+
it('hides GPU devices on macOS', async () => {
166+
global.IS_MACOS = true
167+
const Component = Route.component as React.ComponentType
168+
render(<Component />)
169+
170+
await waitFor(() => {
171+
expect(screen.queryByText('GPUs')).not.toBeInTheDocument()
172+
})
173+
})
174+
})

web-app/src/routes/settings/hardware.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -296,17 +296,19 @@ function Hardware() {
296296
<Progress
297297
value={
298298
toNumber(
299-
systemUsage.used_memory /
300-
systemUsage.total_memory
299+
(hardwareData.total_memory -
300+
systemUsage.used_memory) /
301+
hardwareData.total_memory
301302
) * 100
302303
}
303304
className="h-2 w-10"
304305
/>
305306
<span className="text-main-view-fg/80">
306307
{(
307308
toNumber(
308-
systemUsage.used_memory /
309-
systemUsage.total_memory
309+
(hardwareData.total_memory -
310+
systemUsage.used_memory) /
311+
hardwareData.total_memory
310312
) * 100
311313
).toFixed(2)}
312314
%

web-app/src/routes/system-monitor.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,9 +179,7 @@ function SystemMonitor() {
179179
{t('system-monitor:usedRam')}
180180
</span>
181181
<span className="text-main-view-fg">
182-
{formatMegaBytes(
183-
hardwareData.total_memory - systemUsage.used_memory
184-
)}
182+
{formatMegaBytes(systemUsage.used_memory)}
185183
</span>
186184
</div>
187185
<div className="mt-4">

0 commit comments

Comments
 (0)