diff --git a/frontend/src/components/admin/group/GroupRateMultipliersModal.vue b/frontend/src/components/admin/group/GroupRateMultipliersModal.vue index efeb95e0e3..dfcd238f30 100644 --- a/frontend/src/components/admin/group/GroupRateMultipliersModal.vue +++ b/frontend/src/components/admin/group/GroupRateMultipliersModal.vue @@ -426,7 +426,7 @@ const updateLocalRate = (userId: number, value: string) => { return } const num = parseFloat(value) - if (isNaN(num)) return + if (!Number.isFinite(num) || num <= 0) return entry.rate_multiplier = num } diff --git a/frontend/src/components/admin/group/__tests__/GroupRateMultipliersModal.edit.spec.ts b/frontend/src/components/admin/group/__tests__/GroupRateMultipliersModal.edit.spec.ts new file mode 100644 index 0000000000..e1fc6c557c --- /dev/null +++ b/frontend/src/components/admin/group/__tests__/GroupRateMultipliersModal.edit.spec.ts @@ -0,0 +1,52 @@ +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import { enableAutoUnmount, flushPromises, mount } from '@vue/test-utils' +import type { AdminGroup } from '@/types' +import GroupRateMultipliersModal from '../GroupRateMultipliersModal.vue' + +const mocks = vi.hoisted(() => ({ getGroupRateMultipliers: vi.fn(), batchSetGroupRateMultipliers: vi.fn() })) +vi.mock('@/api/admin', () => ({ adminAPI: { groups: mocks } })) +vi.mock('@/stores/app', () => ({ useAppStore: () => ({ showSuccess: vi.fn(), showError: vi.fn() }) })) +vi.mock('vue-i18n', () => ({ useI18n: () => ({ t: (key: string) => key }) })) +enableAutoUnmount(afterEach) +beforeEach(() => { + vi.resetAllMocks() + mocks.getGroupRateMultipliers.mockResolvedValue([ + { user_id: 7, user_email: 'user@example.com', user_name: '', user_status: 'active', rate_multiplier: 2, rpm_override: null } + ]) +}) + +async function openEditor() { + const wrapper = mount(GroupRateMultipliersModal, { + props: { show: false, group: { id: 1, name: 'Group', platform: 'openai', rate_multiplier: 1 } as AdminGroup }, + global: { stubs: { + BaseDialog: { props: ['show'], template: '