Files
vps-tracker/apps/api/src/services/userapi/sync.test.ts
T
DenozordecandCursor 6c5eb04fae
Docker / build (push) Has been cancelled
fix(userapi): подтягивать стоимость VPS Macloud/VDSina из тарифных планов
При синке UserAPI цена и период берутся по server-plan.id из индекса тарифов, а не остаются нулевыми.

Co-authored-by: Cursor <[email protected]>
2026-06-29 02:23:34 +07:00

171 lines
4.6 KiB
TypeScript

import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { closeDb, getSqlite } from '@cfdm/db'
import { resetTestDb } from '@cfdm/db/test-setup'
import { providerAccountsRepository } from '@cfdm/db/repositories/provider-accounts'
import { syncFromUserApi } from './sync.js'
import type { UserApiSyncAccount } from './context.js'
vi.mock('./operations.js', () => ({
fetchServersWithDetails: vi.fn(),
fetchBalance: vi.fn(),
fetchTariffList: vi.fn(),
fetchPlanCostIndex: vi.fn(),
fetchOperations: vi.fn(),
}))
import {
fetchBalance,
fetchOperations,
fetchPlanCostIndex,
fetchServersWithDetails,
fetchTariffList,
} from './operations.js'
function makeAccount(apiType: 'macloud' | 'vdsina'): UserApiSyncAccount {
return {
id: `acc-${apiType}`,
providerId: `prov-${apiType}`,
name: `${apiType} Account`,
panelUrl: '',
currency: 'RUB',
billingMode: 'daily',
notes: '',
apiType,
apiBaseUrl:
apiType === 'macloud'
? 'https://userapi.macloud.ru/v1'
: 'https://userapi.vdsina.com/v1',
apiCredentials: 'secret-token',
apiToken: 'secret-token',
balanceApi: null,
balanceCurrency: null,
balanceUpdatedAt: null,
enoughmoneyto: '',
balanceAlertBelow: null,
}
}
describe('syncFromUserApi', () => {
beforeEach(() => {
resetTestDb()
vi.mocked(fetchServersWithDetails).mockResolvedValue([
{
id: 100,
name: 'Server #100',
status: 'active',
end: '2029-01-01',
ip: { ip: '1.2.3.4', type: '4' },
template: { name: 'Debian 12' },
datacenter: { id: 1, name: 'DC1', country: 'ru' },
'server-plan': { id: 13, name: '2 RAM / 1 CPU / 40 NVMe' },
data: { cpu: { value: 1 }, ram: { value: 2 }, disk: { value: 40 } },
},
])
vi.mocked(fetchBalance).mockResolvedValue({
balance: 500,
currency: 'RUB',
enoughmoneyto: '2029-12-01',
})
vi.mocked(fetchTariffList).mockResolvedValue([
{
externalId: '13',
datacenterKey: '11',
datacenterName: 'Cloud',
name: '2 RAM / 1 CPU / 40 NVMe',
desc: '',
vcpu: 1,
ramGb: 2,
diskGb: 40,
diskType: 'NVMe',
virtualization: 'KVM',
channel: '',
location: 'Cloud',
country: '',
cpuModel: '',
orderAvailable: true,
price: '1.55 ₽/день',
},
])
vi.mocked(fetchPlanCostIndex).mockResolvedValue(
new Map([
[
'13',
{
id: 13,
name: '2 RAM / 1 CPU / 40 NVMe',
cost: 1.55,
period: 'day',
},
],
]),
)
vi.mocked(fetchOperations).mockResolvedValue([
{
id: 999,
purse: 'real',
type: 1,
status: 1,
summ: '200',
created: '2025-03-01 10:00:00',
comment: 'Top up',
},
])
})
afterEach(() => {
closeDb()
})
it('syncs macloud account with correct id prefix', async () => {
getSqlite()
.prepare(
`INSERT INTO providers (id, name, apiType, apiBaseUrl) VALUES ('prov-macloud', 'Macloud', 'macloud', 'https://userapi.macloud.ru/v1')`,
)
.run()
providerAccountsRepository.create({
id: 'acc-macloud',
providerId: 'prov-macloud',
name: 'Macloud',
apiCredentials: 'secret-token',
})
const result = await syncFromUserApi(makeAccount('macloud'))
expect(result.vpsCount).toBe(1)
expect(result.paymentsCount).toBe(1)
expect(result.tariffsCount).toBe(1)
expect(result.balance?.balance).toBe(500)
const vps = getSqlite().prepare('SELECT id, notes, dailyRate, tariffType FROM vps WHERE id = ?').get('vps-macloud-acc-macloud-100') as {
id: string
notes: string
dailyRate: number
tariffType: string
}
expect(vps.notes).toContain('macloud-100')
expect(vps.dailyRate).toBe(1.55)
expect(vps.tariffType).toBe('daily')
})
it('syncs vdsina account with vdsina id prefix', async () => {
getSqlite()
.prepare(
`INSERT INTO providers (id, name, apiType, apiBaseUrl) VALUES ('prov-vdsina', 'VDSina', 'vdsina', 'https://userapi.vdsina.com/v1')`,
)
.run()
providerAccountsRepository.create({
id: 'acc-vdsina',
providerId: 'prov-vdsina',
name: 'VDSina',
apiCredentials: 'secret-token',
})
const result = await syncFromUserApi(makeAccount('vdsina'))
expect(result.vpsCount).toBe(1)
const vps = getSqlite().prepare('SELECT id FROM vps WHERE id = ?').get('vps-vdsina-acc-vdsina-100')
expect(vps).toBeTruthy()
})
})