fix(studio): price nano compute at the micro rate in restore to new project (#50546)

Restore to new project showed $0 Additional Monthly Compute for nano
projects on paid plans, because the cost estimate hardcoded nano and
pico to $0 regardless of plan. It now prices them at the micro rate on
paid plans, matching how they're billed (and how Disk Management already
displays them).

Fixes FE-4427

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **Bug Fixes**
- Corrected monthly pricing estimates when restoring a project with pico
or nano compute sizes on paid plans.
  - Free plans continue to show no compute charge.
- Pricing for micro and small compute sizes remains calculated using
their expected rates.

- **Tests**
- Added coverage for compute pricing across free and paid plans and
multiple instance sizes.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Ali Waseem authored and GitHub committed 2026-09-18 07:16:18 -06:00
1 parent d72a29852c
commit 45a80b5685
2 files changed
+38 -3

No files matched your search

@@ -0,0 +1,35 @@
import { describe, expect, it } from 'vitest'
import { projectSpecToMonthlyPrice } from './RestoreToNewProject.utils'
import { InfraInstanceSize } from '@/components/interfaces/DiskManagement/DiskManagement.types'
import { DiskType } from '@/components/interfaces/DiskManagement/ui/DiskManagement.constants'
import { PlanId } from '@/data/subscriptions/types'
const getComputePrice = (targetComputeSize: InfraInstanceSize, planId: PlanId) =>
projectSpecToMonthlyPrice({
targetVolumeSizeGb: 8,
targetComputeSize,
planId,
storageType: DiskType.GP3,
}).computePrice
describe('projectSpecToMonthlyPrice', () => {
it('prices nano at the micro rate on paid plans', () => {
expect(getComputePrice('nano', 'pro')).toBe(9.68)
expect(getComputePrice('nano', 'team')).toBe(9.68)
})
it('prices pico at the micro rate on paid plans', () => {
expect(getComputePrice('pico', 'pro')).toBe(9.68)
})
it('prices nano and pico at zero on the free plan', () => {
expect(getComputePrice('nano', 'free')).toBe(0)
expect(getComputePrice('pico', 'free')).toBe(0)
})
it('prices sizes above nano from their own compute rate', () => {
expect(getComputePrice('micro', 'pro')).toBe(9.68)
expect(getComputePrice('small', 'pro')).toBe(14.83)
})
})
@@ -42,7 +42,7 @@ export function projectSpecToMonthlyPrice({
const computePrice = calculateComputeSizePrice({
availableOptions: [
{ identifier: targetComputeSize, price: getComputeHourlyPrice(targetComputeSize) },
{ identifier: targetComputeSize, price: getComputeHourlyPrice(targetComputeSize, planId) },
],
oldComputeSize: 'nano', // not used for r2np
newComputeSize: targetComputeSize,
@@ -55,9 +55,9 @@ export function projectSpecToMonthlyPrice({
}
}
function getComputeHourlyPrice(computeSize: InfraInstanceSize): number {
function getComputeHourlyPrice(computeSize: InfraInstanceSize, planId: PlanId): number {
if (computeSize === 'pico' || computeSize === 'nano') {
return 0
return planId === 'free' ? 0 : instanceSizeSpecs.micro.priceHourly
}
return instanceSizeSpecs[computeSize]?.priceHourly