From 2d255052f029cb0c628e84ad377d187a97dff096 Mon Sep 17 00:00:00 2001 From: Remi Date: Sun, 15 Nov 2020 16:18:13 +0100 Subject: [PATCH 1/4] feat(core): add missing tests --- packages/core/package.json | 3 +- .../AlertDisplay/AlertDisplay.test.tsx | 65 ++++++++ .../EmptyState/EmptyStateImage.test.tsx | 49 ++++++ .../components/EmptyState/EmptyStateImage.tsx | 9 +- .../FeatureCalloutCircular.test.tsx | 154 ++++++++++++++++++ .../FeatureCalloutCircular.tsx | 2 + yarn.lock | 16 +- 7 files changed, 285 insertions(+), 13 deletions(-) create mode 100644 packages/core/src/components/AlertDisplay/AlertDisplay.test.tsx create mode 100644 packages/core/src/components/EmptyState/EmptyStateImage.test.tsx create mode 100644 packages/core/src/components/FeatureDiscovery/FeatureCalloutCircular.test.tsx diff --git a/packages/core/package.json b/packages/core/package.json index 848f0847bd..f7e8c67fe9 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -60,7 +60,8 @@ "react-sparklines": "^1.7.0", "react-syntax-highlighter": "^13.5.1", "react-use": "^15.3.3", - "remark-gfm": "^1.0.0" + "remark-gfm": "^1.0.0", + "zen-observable": "^0.8.15" }, "devDependencies": { "@backstage/cli": "^0.2.0", diff --git a/packages/core/src/components/AlertDisplay/AlertDisplay.test.tsx b/packages/core/src/components/AlertDisplay/AlertDisplay.test.tsx new file mode 100644 index 0000000000..3f85dab9f3 --- /dev/null +++ b/packages/core/src/components/AlertDisplay/AlertDisplay.test.tsx @@ -0,0 +1,65 @@ +/* + * 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 { AlertDisplay } from './AlertDisplay'; +import { + ApiProvider, + ApiRegistry, + alertApiRef, + AlertApiForwarder, +} from '@backstage/core-api'; +import Observable from 'zen-observable'; +import { renderInTestApp } from '@backstage/test-utils'; + +const TEST_MESSAGE = 'TEST_MESSAGE'; + +describe('', () => { + it('renders without exploding', async () => { + const apiRegistry = ApiRegistry.from([ + [alertApiRef, new AlertApiForwarder()], + ]); + + const { queryByText } = await renderInTestApp( + + + , + ); + expect(queryByText(TEST_MESSAGE)).not.toBeInTheDocument(); + }); + + it('renders with message', async () => { + const apiRegistry = ApiRegistry.from([ + [ + alertApiRef, + { + post() {}, + alert$() { + return Observable.of({ message: TEST_MESSAGE }); + }, + }, + ], + ]); + + const { queryByText } = await renderInTestApp( + + + , + ); + + expect(queryByText(TEST_MESSAGE)).toBeInTheDocument(); + }); +}); diff --git a/packages/core/src/components/EmptyState/EmptyStateImage.test.tsx b/packages/core/src/components/EmptyState/EmptyStateImage.test.tsx new file mode 100644 index 0000000000..942f533dac --- /dev/null +++ b/packages/core/src/components/EmptyState/EmptyStateImage.test.tsx @@ -0,0 +1,49 @@ +/* + * 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 { renderWithEffects, wrapInTestApp } from '@backstage/test-utils'; +import { EmptyStateImage } from './EmptyStateImage'; + +describe('', () => { + it('render EmptyStateImage component with missing field', async () => { + const rendered = await renderWithEffects( + wrapInTestApp(), + ); + expect(rendered.getByTestId('missingAnnotation')).toBeInTheDocument(); + }); + + it('render EmptyStateImage component with missing info', async () => { + const rendered = await renderWithEffects( + wrapInTestApp(), + ); + expect(rendered.getByTestId('noInformation')).toBeInTheDocument(); + }); + + it('render EmptyStateImage component with missing content', async () => { + const rendered = await renderWithEffects( + wrapInTestApp(), + ); + expect(rendered.getByTestId('createComponent')).toBeInTheDocument(); + }); + + it('render EmptyStateImage component with missing data', async () => { + const rendered = await renderWithEffects( + wrapInTestApp(), + ); + expect(rendered.getByTestId('noBuild')).toBeInTheDocument(); + }); +}); diff --git a/packages/core/src/components/EmptyState/EmptyStateImage.tsx b/packages/core/src/components/EmptyState/EmptyStateImage.tsx index d52a0f7dcf..c7a61f7190 100644 --- a/packages/core/src/components/EmptyState/EmptyStateImage.tsx +++ b/packages/core/src/components/EmptyState/EmptyStateImage.tsx @@ -54,6 +54,7 @@ export const EmptyStateImage = ({ missing }: Props) => { src={noInformation} alt="no Information" className={classes.generalImg} + data-testid="noInformation" /> ); case 'content': @@ -62,11 +63,17 @@ export const EmptyStateImage = ({ missing }: Props) => { src={createComponent} alt="create Component" className={classes.generalImg} + data-testid="createComponent" /> ); case 'data': return ( - no Build + no Build ); default: return null; diff --git a/packages/core/src/components/FeatureDiscovery/FeatureCalloutCircular.test.tsx b/packages/core/src/components/FeatureDiscovery/FeatureCalloutCircular.test.tsx new file mode 100644 index 0000000000..5c7f17ba9f --- /dev/null +++ b/packages/core/src/components/FeatureDiscovery/FeatureCalloutCircular.test.tsx @@ -0,0 +1,154 @@ +/* + * 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 { act, fireEvent } from '@testing-library/react'; +import { renderInTestApp } from '@backstage/test-utils'; +import { FeatureCalloutCircular } from './FeatureCalloutCircular'; + +const INITIAL_BOUNDING_RECT: DOMRect = { + width: 100, + height: 100, + x: 0, + y: 0, + bottom: 0, + left: 0, + right: 0, + top: 0, + toJSON: () => {}, +}; + +const UPDATED_BOUNDING_RECT: DOMRect = { + width: 200, + height: 200, + x: 50, + y: 50, + bottom: 0, + left: 0, + right: 0, + top: 0, + toJSON: () => {}, +}; + +beforeEach(() => { + Element.prototype.getBoundingClientRect = jest.fn( + () => INITIAL_BOUNDING_RECT, + ); +}); + +describe('', () => { + it('renders without exploding', async () => { + const rendered = await renderInTestApp( + , + ); + rendered.getByText('description'); + rendered.getByText('title'); + }); + + it('renders with correct style', async () => { + const { getByTestId } = await renderInTestApp( + , + ); + const dot = await getByTestId('dot'); + const text = await getByTestId('text'); + + expect(dot).toBeInTheDocument(); + expect(text).toBeInTheDocument(); + + // Dot style + expect(dot.style.left).toBe('-800px'); + expect(dot.style.top).toBe('-800px'); + expect(dot.style.width).toBe('1700px'); + expect(dot.style.height).toBe('1700px'); + + // Text style + expect(text.style.left).toBe('-400px'); + expect(text.style.top).toBe('120px'); + expect(text.style.width).toBe('450px'); + }); + + it('update when the user scrolls', async () => { + const { getByTestId } = await renderInTestApp( + , + ); + const dot = await getByTestId('dot'); + const text = await getByTestId('text'); + + act(() => { + Element.prototype.getBoundingClientRect = jest.fn( + () => UPDATED_BOUNDING_RECT, + ); + + // Trigger the window resize event. + fireEvent(window, new Event('resize')); + }); + + // Dot style + expect(dot.style.left).toBe('-750px'); + expect(dot.style.top).toBe('-750px'); + expect(dot.style.width).toBe('1800px'); + expect(dot.style.height).toBe('1800px'); + + // Text style + expect(text.style.left).toBe('-300px'); + expect(text.style.top).toBe('270px'); + expect(text.style.width).toBe('450px'); + }); + + it('update when the user resizes the window', async () => { + const { getByTestId } = await renderInTestApp( + , + ); + const dot = await getByTestId('dot'); + const text = await getByTestId('text'); + + act(() => { + Element.prototype.getBoundingClientRect = jest.fn( + () => UPDATED_BOUNDING_RECT, + ); + + // Trigger the window resize event. + fireEvent(window, new Event('scroll')); + }); + + // Dot style + expect(dot.style.left).toBe('-750px'); + expect(dot.style.top).toBe('-750px'); + expect(dot.style.width).toBe('1800px'); + expect(dot.style.height).toBe('1800px'); + + // Text style + expect(text.style.left).toBe('-300px'); + expect(text.style.top).toBe('270px'); + expect(text.style.width).toBe('450px'); + }); +}); diff --git a/packages/core/src/components/FeatureDiscovery/FeatureCalloutCircular.tsx b/packages/core/src/components/FeatureDiscovery/FeatureCalloutCircular.tsx index 38e422dbcc..9dc0d25681 100644 --- a/packages/core/src/components/FeatureDiscovery/FeatureCalloutCircular.tsx +++ b/packages/core/src/components/FeatureDiscovery/FeatureCalloutCircular.tsx @@ -160,6 +160,7 @@ export const FeatureCalloutCircular: FC = ({ <>
= ({
Date: Sun, 15 Nov 2020 16:18:38 +0100 Subject: [PATCH 2/4] fix(core): LinearGauge tooltip + test --- .../ProgressBars/LinearGauge.test.tsx | 37 +++++++++++++++++++ .../components/ProgressBars/LinearGauge.tsx | 14 ++++--- 2 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 packages/core/src/components/ProgressBars/LinearGauge.test.tsx diff --git a/packages/core/src/components/ProgressBars/LinearGauge.test.tsx b/packages/core/src/components/ProgressBars/LinearGauge.test.tsx new file mode 100644 index 0000000000..fc04b642fb --- /dev/null +++ b/packages/core/src/components/ProgressBars/LinearGauge.test.tsx @@ -0,0 +1,37 @@ +/* + * 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 { renderInTestApp } from '@backstage/test-utils'; + +import { LinearGauge } from './LinearGauge'; + +describe('', () => { + it('renders without exploding', async () => { + const { getByTitle } = await renderInTestApp(); + expect(getByTitle('50%')).toBeInTheDocument(); + }); + + it('renders progress and title', async () => { + const { container } = await renderInTestApp(); + expect(container).toBeEmptyDOMElement(); + }); + + it('renders with 100 as max value', async () => { + const { getByTitle } = await renderInTestApp(); + expect(getByTitle('100%')).toBeInTheDocument(); + }); +}); diff --git a/packages/core/src/components/ProgressBars/LinearGauge.tsx b/packages/core/src/components/ProgressBars/LinearGauge.tsx index 2b8e77838d..a6aea59f19 100644 --- a/packages/core/src/components/ProgressBars/LinearGauge.tsx +++ b/packages/core/src/components/ProgressBars/LinearGauge.tsx @@ -40,12 +40,14 @@ export const LinearGauge: FC = ({ value }) => { const strokeColor = getProgressColor(theme.palette, percent, false, 100); return ( - + + + ); }; From 538328e0834d776a79738d816e0a871fd9ddc87f Mon Sep 17 00:00:00 2001 From: Remi Date: Mon, 16 Nov 2020 13:58:37 +0100 Subject: [PATCH 3/4] fix(core): regenerate yarn.lock file --- yarn.lock | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/yarn.lock b/yarn.lock index 9d4984e152..10e70f52fb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1290,34 +1290,40 @@ to-fast-properties "^2.0.0" "@backstage/core@^0.2.0": - version "0.2.0" - resolved "https://registry.npmjs.org/@backstage/core/-/core-0.2.0.tgz#543246b2d87563c9aa4d9fb96e40fdfc7e827520" - integrity sha512-75m2u3FoUngBOvt9l65xZcYTzzB+49OXpY1A9VNFUR1+jMs3cL/0HDfByQV2H0xXaHzMngQ8C5u/sWhkQsij1w== + version "0.3.0" dependencies: "@backstage/config" "^0.1.1" - "@backstage/core-api" "^0.2.0" - "@backstage/theme" "^0.2.0" + "@backstage/core-api" "^0.2.1" + "@backstage/theme" "^0.2.1" "@material-ui/core" "^4.11.0" "@material-ui/icons" "^4.9.1" "@material-ui/lab" "4.0.0-alpha.45" + "@types/dagre" "^0.7.44" "@types/react" "^16.9" "@types/react-sparklines" "^1.7.0" classnames "^2.2.6" clsx "^1.1.0" + d3-selection "^2.0.0" + d3-shape "^2.0.0" + d3-zoom "^2.0.0" + dagre "^0.8.5" immer "^7.0.9" lodash "^4.17.15" material-table "^1.69.1" prop-types "^15.7.2" + qs "^6.9.4" rc-progress "^3.0.0" react "^16.12.0" react-dom "^16.12.0" react-helmet "6.1.0" react-hook-form "^6.6.0" + react-markdown "^5.0.2" react-router "6.0.0-beta.0" react-router-dom "6.0.0-beta.0" react-sparklines "^1.7.0" react-syntax-highlighter "^13.5.1" react-use "^15.3.3" + remark-gfm "^1.0.0" "@bcoe/v8-coverage@^0.2.3": version "0.2.3" From ba985b1357610282ce41926d001f47d2208ca3a9 Mon Sep 17 00:00:00 2001 From: Remi Date: Mon, 16 Nov 2020 16:18:50 +0100 Subject: [PATCH 4/4] feat(core): remove data-testid --- .../components/EmptyState/EmptyState.test.tsx | 2 +- .../EmptyState/EmptyStateImage.test.tsx | 16 ++++++++-------- .../components/EmptyState/EmptyStateImage.tsx | 10 +--------- .../FeatureCalloutCircular.test.tsx | 2 +- 4 files changed, 11 insertions(+), 19 deletions(-) diff --git a/packages/core/src/components/EmptyState/EmptyState.test.tsx b/packages/core/src/components/EmptyState/EmptyState.test.tsx index c5bc7a9876..32e71f044d 100644 --- a/packages/core/src/components/EmptyState/EmptyState.test.tsx +++ b/packages/core/src/components/EmptyState/EmptyState.test.tsx @@ -34,6 +34,6 @@ describe('', () => { rendered.getByText('Your plugin is missing an annotation'), ).toBeInTheDocument(); expect(rendered.getByLabelText('button')).toBeInTheDocument(); - expect(rendered.getByTestId('missingAnnotation')).toBeInTheDocument(); + expect(rendered.getByAltText('annotation is missing')).toBeInTheDocument(); }); }); diff --git a/packages/core/src/components/EmptyState/EmptyStateImage.test.tsx b/packages/core/src/components/EmptyState/EmptyStateImage.test.tsx index 942f533dac..258eee943d 100644 --- a/packages/core/src/components/EmptyState/EmptyStateImage.test.tsx +++ b/packages/core/src/components/EmptyState/EmptyStateImage.test.tsx @@ -20,30 +20,30 @@ import { EmptyStateImage } from './EmptyStateImage'; describe('', () => { it('render EmptyStateImage component with missing field', async () => { - const rendered = await renderWithEffects( + const { getByAltText } = await renderWithEffects( wrapInTestApp(), ); - expect(rendered.getByTestId('missingAnnotation')).toBeInTheDocument(); + expect(getByAltText('annotation is missing')).toBeInTheDocument(); }); it('render EmptyStateImage component with missing info', async () => { - const rendered = await renderWithEffects( + const { getByAltText } = await renderWithEffects( wrapInTestApp(), ); - expect(rendered.getByTestId('noInformation')).toBeInTheDocument(); + expect(getByAltText('no Information')).toBeInTheDocument(); }); it('render EmptyStateImage component with missing content', async () => { - const rendered = await renderWithEffects( + const { getByAltText } = await renderWithEffects( wrapInTestApp(), ); - expect(rendered.getByTestId('createComponent')).toBeInTheDocument(); + expect(getByAltText('create Component')).toBeInTheDocument(); }); it('render EmptyStateImage component with missing data', async () => { - const rendered = await renderWithEffects( + const { getByAltText } = await renderWithEffects( wrapInTestApp(), ); - expect(rendered.getByTestId('noBuild')).toBeInTheDocument(); + expect(getByAltText('no Build')).toBeInTheDocument(); }); }); diff --git a/packages/core/src/components/EmptyState/EmptyStateImage.tsx b/packages/core/src/components/EmptyState/EmptyStateImage.tsx index c7a61f7190..1973ff9a23 100644 --- a/packages/core/src/components/EmptyState/EmptyStateImage.tsx +++ b/packages/core/src/components/EmptyState/EmptyStateImage.tsx @@ -45,7 +45,6 @@ export const EmptyStateImage = ({ missing }: Props) => { src={missingAnnotation} className={classes.generalImg} alt="annotation is missing" - data-testid="missingAnnotation" /> ); case 'info': @@ -54,7 +53,6 @@ export const EmptyStateImage = ({ missing }: Props) => { src={noInformation} alt="no Information" className={classes.generalImg} - data-testid="noInformation" /> ); case 'content': @@ -63,17 +61,11 @@ export const EmptyStateImage = ({ missing }: Props) => { src={createComponent} alt="create Component" className={classes.generalImg} - data-testid="createComponent" /> ); case 'data': return ( - no Build + no Build ); default: return null; diff --git a/packages/core/src/components/FeatureDiscovery/FeatureCalloutCircular.test.tsx b/packages/core/src/components/FeatureDiscovery/FeatureCalloutCircular.test.tsx index 5c7f17ba9f..83a31f198d 100644 --- a/packages/core/src/components/FeatureDiscovery/FeatureCalloutCircular.test.tsx +++ b/packages/core/src/components/FeatureDiscovery/FeatureCalloutCircular.test.tsx @@ -136,7 +136,7 @@ describe('', () => { () => UPDATED_BOUNDING_RECT, ); - // Trigger the window resize event. + // Trigger the window scroll event. fireEvent(window, new Event('scroll')); });