diff --git a/static/gsApp/views/subscriptionPage/usageOverview.spec.tsx b/static/gsApp/views/subscriptionPage/usageOverview.spec.tsx index da79d9db4e6795..5fd55d07d4ae68 100644 --- a/static/gsApp/views/subscriptionPage/usageOverview.spec.tsx +++ b/static/gsApp/views/subscriptionPage/usageOverview.spec.tsx @@ -49,10 +49,8 @@ describe('UsageOverview', () => { /> ); expect(screen.getByRole('columnheader', {name: 'Product'})).toBeInTheDocument(); - expect(screen.getByRole('columnheader', {name: 'Current usage'})).toBeInTheDocument(); - expect( - screen.getByRole('columnheader', {name: 'Reserved usage'}) - ).toBeInTheDocument(); + expect(screen.getByRole('columnheader', {name: 'Total usage'})).toBeInTheDocument(); + expect(screen.getByRole('columnheader', {name: 'Reserved'})).toBeInTheDocument(); expect( screen.getByRole('columnheader', {name: 'Reserved spend'}) ).toBeInTheDocument(); @@ -76,10 +74,8 @@ describe('UsageOverview', () => { /> ); expect(screen.getByRole('columnheader', {name: 'Product'})).toBeInTheDocument(); - expect(screen.getByRole('columnheader', {name: 'Current usage'})).toBeInTheDocument(); - expect( - screen.getByRole('columnheader', {name: 'Reserved usage'}) - ).toBeInTheDocument(); + expect(screen.getByRole('columnheader', {name: 'Total usage'})).toBeInTheDocument(); + expect(screen.getByRole('columnheader', {name: 'Reserved'})).toBeInTheDocument(); expect(screen.queryByText('Reserved spend')).not.toBeInTheDocument(); expect(screen.queryByText('Pay-as-you-go spend')).not.toBeInTheDocument(); expect( @@ -120,6 +116,7 @@ describe('UsageOverview', () => { subscription.categories.attachments = { ...subscription.categories.attachments!, reserved: 25, // 25 GB + prepaid: 25, // 25 GB free: 0, usage: GIGABYTE / 2, }; @@ -145,21 +142,21 @@ describe('UsageOverview', () => { expect(screen.queryByText('Trial available')).not.toBeInTheDocument(); // Replays product trial active - expect(screen.getByText('20 days left')).toBeInTheDocument(); + expect(screen.getByRole('cell', {name: '20 days left'})).toBeInTheDocument(); // Errors usage and gifted units - expect(screen.getByText('6,000 / 51,000')).toBeInTheDocument(); - expect(screen.getByText('$10.00')).toBeInTheDocument(); - expect(screen.getByText('12%')).toBeInTheDocument(); + expect(screen.getByRole('cell', {name: '6,000'})).toBeInTheDocument(); + expect(screen.getByRole('cell', {name: '$10.00'})).toBeInTheDocument(); + expect(screen.getByRole('cell', {name: '12% of 51,000'})).toBeInTheDocument(); // Attachments usage should be in the correct unit + above platform volume - expect(screen.getByText('500 MB / 25 GB')).toBeInTheDocument(); - expect(screen.getByText('50%')).toBeInTheDocument(); - expect(screen.getByText('$6.00')).toBeInTheDocument(); + expect(screen.getByRole('cell', {name: '500 MB'})).toBeInTheDocument(); + expect(screen.getByRole('cell', {name: '2% of 25 GB'})).toBeInTheDocument(); + expect(screen.getByRole('cell', {name: '$6.00'})).toBeInTheDocument(); // Reserved spans above platform volume - expect(screen.getByText('0 / 20,000,000')).toBeInTheDocument(); - expect(screen.getByText('$32.00')).toBeInTheDocument(); + expect(screen.getAllByRole('cell', {name: '0'}).length).toBeGreaterThan(0); + expect(screen.getByRole('cell', {name: '$32.00'})).toBeInTheDocument(); }); it('renders table based on add-on state', () => { diff --git a/static/gsApp/views/subscriptionPage/usageOverview.tsx b/static/gsApp/views/subscriptionPage/usageOverview.tsx index 5880363ae9652c..a59a01f983a2c8 100644 --- a/static/gsApp/views/subscriptionPage/usageOverview.tsx +++ b/static/gsApp/views/subscriptionPage/usageOverview.tsx @@ -226,8 +226,8 @@ function UsageOverviewTable({subscription, organization, usageData}: UsageOvervi ); return [ {key: 'product', name: t('Product'), width: 250}, - {key: 'currentUsage', name: t('Current usage'), width: 200}, - {key: 'reservedUsage', name: t('Reserved usage'), width: 200}, + {key: 'totalUsage', name: t('Total usage'), width: 200}, + {key: 'reservedUsage', name: t('Reserved'), width: 300}, {key: 'reservedSpend', name: t('Reserved spend'), width: isXlScreen ? 200 : 150}, { key: 'budgetSpend', @@ -265,22 +265,22 @@ function UsageOverviewTable({subscription, organization, usageData}: UsageOvervi // TODO(isabella): refactor this to have better types const productData: Array<{ budgetSpend: number; - currentUsage: number; hasAccess: boolean; isClickable: boolean; isPaygOnly: boolean; isUnlimited: boolean; product: string; + totalUsage: number; addOnCategory?: AddOnCategory; ariaLabel?: string; dataCategory?: DataCategory; free?: number; isChildProduct?: boolean; isOpen?: boolean; + percentUsed?: number; productTrialCategory?: DataCategory; reserved?: number; reservedSpend?: number; - reservedUsage?: number; softCapType?: 'ON_DEMAND' | 'TRUE_FORWARD'; toggleKey?: DataCategory | AddOnCategory; }> = useMemo(() => { @@ -342,8 +342,8 @@ function UsageOverviewTable({subscription, organization, usageData}: UsageOvervi isUnlimited: !!activeProductTrial || reserved === UNLIMITED_RESERVED, softCapType: softCapType ?? undefined, product: productName, - currentUsage: total, - reservedUsage: percentUsed, + totalUsage: total, + percentUsed, reservedSpend: recurringReservedSpend, budgetSpend: paygTotal, productTrialCategory: category, @@ -431,7 +431,7 @@ function UsageOverviewTable({subscription, organization, usageData}: UsageOvervi isUnlimited: !!activeProductTrial, softCapType: softCapType ?? undefined, budgetSpend: childPaygTotal, - currentUsage: (childSpend ?? 0) + childPaygTotal, + totalUsage: (childSpend ?? 0) + childPaygTotal, product: childProductName, isClickable: categoryInfo?.tallyType === 'usage', }; @@ -450,8 +450,8 @@ function UsageOverviewTable({subscription, organization, usageData}: UsageOvervi isUnlimited: !!activeProductTrial, productTrialCategory: addOnDataCategories[0] as DataCategory, product: addOnName, - currentUsage: (reservedBudget?.totalReservedSpend ?? 0) + paygTotal, - reservedUsage: percentUsed, + totalUsage: (reservedBudget?.totalReservedSpend ?? 0) + paygTotal, + percentUsed, reservedSpend: recurringReservedSpend, budgetSpend: paygTotal, isClickable: hasAccess, @@ -482,7 +482,7 @@ function UsageOverviewTable({subscription, organization, usageData}: UsageOvervi }, renderBodyCell: (column, row) => { const { - currentUsage, + totalUsage, hasAccess, isPaygOnly, isUnlimited, @@ -493,7 +493,7 @@ function UsageOverviewTable({subscription, organization, usageData}: UsageOvervi isChildProduct, isOpen, reserved, - reservedUsage, + percentUsed, softCapType, toggleKey, productTrialCategory, @@ -543,60 +543,19 @@ function UsageOverviewTable({subscription, organization, usageData}: UsageOvervi ); } - case 'currentUsage': { + case 'totalUsage': { const formattedTotal = addOnCategory - ? displayPriceWithCents({cents: currentUsage}) + ? displayPriceWithCents({cents: totalUsage}) : dataCategory - ? formatUsageWithUnits(currentUsage, dataCategory, { + ? formatUsageWithUnits(totalUsage, dataCategory, { useUnitScaling: true, }) - : currentUsage; - const formattedReserved = addOnCategory - ? displayPriceWithCents({cents: reserved ?? 0}) - : dataCategory - ? formatReservedWithUnits(reserved ?? 0, dataCategory, { - useUnitScaling: true, - }) - : (reserved ?? 0); - const formattedFree = addOnCategory - ? displayPriceWithCents({cents: free ?? 0}) - : dataCategory - ? formatReservedWithUnits(free ?? 0, dataCategory, { - useUnitScaling: true, - }) - : (free ?? 0); - const formattedReservedTotal = addOnCategory - ? displayPriceWithCents({cents: (reserved ?? 0) + (free ?? 0)}) - : dataCategory - ? formatReservedWithUnits((reserved ?? 0) + (free ?? 0), dataCategory, { - useUnitScaling: true, - }) - : (reserved ?? 0) + (free ?? 0); - const formattedCurrentUsage = - isPaygOnly || isChildProduct - ? formattedTotal - : `${formattedTotal} / ${formattedReservedTotal}`; + : totalUsage; return ( - {isUnlimited ? UNLIMITED : formattedCurrentUsage}{' '} - {!(isPaygOnly || isChildProduct) && ( - - )} + {isUnlimited ? UNLIMITED : formattedTotal}{' '} ); @@ -620,12 +579,58 @@ function UsageOverviewTable({subscription, organization, usageData}: UsageOvervi return {UNLIMITED}; } - const percentUsed = reservedUsage; if (defined(percentUsed)) { + const formattedReserved = addOnCategory + ? displayPriceWithCents({cents: reserved ?? 0}) + : dataCategory + ? formatReservedWithUnits(reserved ?? 0, dataCategory, { + useUnitScaling: true, + }) + : (reserved ?? 0); + const formattedFree = addOnCategory + ? displayPriceWithCents({cents: free ?? 0}) + : dataCategory + ? formatReservedWithUnits(free ?? 0, dataCategory, { + useUnitScaling: true, + }) + : (free ?? 0); + const formattedReservedTotal = addOnCategory + ? displayPriceWithCents({cents: (reserved ?? 0) + (free ?? 0)}) + : dataCategory + ? formatReservedWithUnits( + (reserved ?? 0) + (free ?? 0), + dataCategory, + { + useUnitScaling: true, + } + ) + : (reserved ?? 0) + (free ?? 0); + return ( - {percentUsed.toFixed(0) + '%'} + + {tct('[percent]% of [formattedReservedTotal]', { + percent: percentUsed.toFixed(0), + formattedReservedTotal, + })} + + { + + } ); }