Skip to content

Commit

Permalink
Add support for multiple types of entity cost breakdown
Browse files Browse the repository at this point in the history
  • Loading branch information
timbonicus committed Dec 4, 2020
1 parent f3b24a9 commit e3071a0
Show file tree
Hide file tree
Showing 19 changed files with 929 additions and 623 deletions.
7 changes: 7 additions & 0 deletions .changeset/cost-insights-quick-lizards-smash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@backstage/plugin-cost-insights': minor
---

Add support for multiple types of entity cost breakdown.

This change is backwards-incompatible with plugin-cost-insights 0.3.x; the `entities` field on Entity returned in product cost queries changed from `Entity[]` to `Record<string, Entity[]`.
2 changes: 2 additions & 0 deletions plugins/cost-insights/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"dayjs": "^1.9.4",
"history": "^5.0.0",
"moment": "^2.27.0",
"pluralize": "^8.0.0",
"qs": "^6.9.4",
"react": "^16.13.1",
"react-dom": "^16.13.1",
Expand All @@ -54,6 +55,7 @@
"@testing-library/user-event": "^12.0.7",
"@types/jest": "^26.0.7",
"@types/node": "^12.0.0",
"@types/pluralize": "^0.0.29",
"@types/recharts": "^1.8.14",
"@types/regression": "^2.0.0",
"@types/yup": "^0.29.8",
Expand Down
1 change: 1 addition & 0 deletions plugins/cost-insights/src/api/CostInsightsApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ export type CostInsightsApi = {
* @param options Options to use when fetching insights for a particular cloud product and interval timeframe.
*/
getProductInsights(options: ProductInsightsOptions): Promise<Entity>;

/**
* Get current cost alerts for a given group. These show up as Action Items for the group on the
* Cost Insights page. Alerts may include cost-saving recommendations, such as infrastructure
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const MockComputeEngine: Product = {

const MockComputeEngineInsights: Entity = {
id: 'compute-engine',
entities: [],
entities: {},
aggregation: [0, 0],
change: {
ratio: 0,
Expand All @@ -55,7 +55,7 @@ const MockCloudDataflow: Product = {

const MockCloudDataflowInsights: Entity = {
id: MockCloudDataflow.kind,
entities: [],
entities: {},
aggregation: [1_000, 2_000],
change: {
ratio: 1,
Expand All @@ -70,7 +70,7 @@ const MockCloudStorage: Product = {

const MockCloudStorageInsights: Entity = {
id: MockCloudStorage.kind,
entities: [],
entities: {},
aggregation: [2_000, 4_000],
change: {
ratio: 1,
Expand All @@ -85,7 +85,7 @@ const MockBigQuery: Product = {

const MockBigQueryInsights: Entity = {
id: MockBigQuery.kind,
entities: [],
entities: {},
aggregation: [8_000, 16_000],
change: {
ratio: 1,
Expand All @@ -100,7 +100,7 @@ const MockBigTable: Product = {

const MockBigTableInsights: Entity = {
id: MockBigTable.kind,
entities: [],
entities: {},
aggregation: [16_000, 32_000],
change: {
ratio: 1,
Expand All @@ -115,7 +115,7 @@ const MockCloudPubSub: Product = {

const MockCloudPubSubInsights: Entity = {
id: MockCloudPubSub.kind,
entities: [],
entities: {},
aggregation: [32_000, 64_000],
change: {
ratio: 1,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import React from 'react';
import { wrapInTestApp } from '@backstage/test-utils';
import { ProductEntityDialog } from './ProductEntityDialog';
import { render } from '@testing-library/react';
import { Entity } from '../../types';

const atomicEntity: Entity = {
id: null,
aggregation: [0, 0],
change: { ratio: 0, amount: 0 },
entities: {},
};

const singleBreakdownEntity = {
...atomicEntity,
entities: {
SKU: [
{
id: 'sku-1',
aggregation: [0, 0],
change: { ratio: 0, amount: 0 },
entities: {},
},
{
id: 'sku-2',
aggregation: [0, 0],
change: { ratio: 0, amount: 0 },
entities: {},
},
] as Entity[],
},
};

const multiBreakdownEntity = {
...singleBreakdownEntity,
entities: {
...singleBreakdownEntity.entities,
deployment: [
{
id: 'd-1',
aggregation: [0, 0],
change: { ratio: 0, amount: 0 },
entities: {},
},
{
id: 'd-2',
aggregation: [0, 0],
change: { ratio: 0, amount: 0 },
entities: {},
},
] as Entity[],
},
};

describe('<ProductEntityDialog/>', () => {
it('Should error if no sub-entities exist', () => {
expect(() =>
render(
wrapInTestApp(
<ProductEntityDialog
open
entity={atomicEntity}
onClose={jest.fn()}
selectedLabel={null}
setSelectedLabel={jest.fn()}
/>,
),
),
).toThrow();
});

it('Should not show tabs for a single sub-entity type', () => {
const { queryByText } = render(
wrapInTestApp(
<ProductEntityDialog
open
entity={singleBreakdownEntity}
onClose={jest.fn()}
selectedLabel={null}
setSelectedLabel={jest.fn()}
/>,
),
);
expect(queryByText('Breakdown by SKU')).not.toBeInTheDocument();
});

it('Should show tabs when multiple sub-entity types exist', () => {
const { getByText } = render(
wrapInTestApp(
<ProductEntityDialog
open
entity={multiBreakdownEntity}
onClose={jest.fn()}
selectedLabel={null}
setSelectedLabel={jest.fn()}
/>,
),
);
expect(getByText('Breakdown by SKU')).toBeInTheDocument();
expect(getByText('Breakdown by deployment')).toBeInTheDocument();
expect(getByText('sku-1')).toBeInTheDocument();
});

it('Shows the pre-selected tab, if provided', () => {
const { getByText } = render(
wrapInTestApp(
<ProductEntityDialog
open
entity={multiBreakdownEntity}
onClose={jest.fn()}
selectedLabel="deployment"
setSelectedLabel={jest.fn()}
/>,
),
);
expect(getByText('d-1')).toBeInTheDocument();
});
});

0 comments on commit e3071a0

Please sign in to comment.