Warning panel uses darkmode properly

Updates related tests

Signed-off-by: Nicolas Torres <nicolast@backbase.com>
This commit is contained in:
Nicolas Torres
2021-07-27 11:19:30 +02:00
parent c23f526a8e
commit 5948fd8fce
4 changed files with 100 additions and 57 deletions
@@ -17,22 +17,39 @@
import React from 'react';
import { fireEvent, screen } from '@testing-library/react';
import { renderInTestApp } from '@backstage/test-utils';
import { Typography } from '@material-ui/core';
import { ThemeProvider, Typography } from '@material-ui/core';
import { WarningPanel } from './WarningPanel';
import { WarningPanel, WarningProps } from './WarningPanel';
import { lightTheme } from '@backstage/theme';
const propsTitle = { title: 'Mock title' };
const propsTitleMessage = { title: 'Mock title', message: 'Some more info' };
const propsMessage = { message: 'Some more info' };
const propsTitle: WarningProps = { title: 'Mock title' };
const propsTitleMessage: WarningProps = {
title: 'Mock title',
message: 'Some more info',
};
const propsMessage: WarningProps = { message: 'Some more info' };
const propsErrorMessage: WarningProps = {
severity: 'error',
title: 'Mock title',
message: 'Some more info',
};
describe('<WarningPanel />', () => {
it('renders without exploding', async () => {
await renderInTestApp(<WarningPanel {...propsTitleMessage} />);
await renderInTestApp(
<ThemeProvider theme={lightTheme}>
<WarningPanel {...propsTitleMessage} />
</ThemeProvider>,
);
expect(screen.getByText('Warning: Mock title')).toBeInTheDocument();
});
it('renders title', async () => {
await renderInTestApp(<WarningPanel {...propsTitleMessage} />);
await renderInTestApp(
<ThemeProvider theme={lightTheme}>
<WarningPanel {...propsTitleMessage} />
</ThemeProvider>,
);
const expandIcon = await screen.getByText('Warning: Mock title');
fireEvent.click(expandIcon);
expect(screen.getByText('Warning: Mock title')).toBeInTheDocument();
@@ -41,27 +58,43 @@ describe('<WarningPanel />', () => {
it('renders title and children', async () => {
await renderInTestApp(
<WarningPanel {...propsTitle}>
<Typography>Java stacktrace</Typography>
</WarningPanel>,
<ThemeProvider theme={lightTheme}>
<WarningPanel {...propsTitle}>
<Typography>Java stacktrace</Typography>
</WarningPanel>
</ThemeProvider>,
);
expect(screen.getByText('Java stacktrace')).toBeInTheDocument();
});
it('renders message', async () => {
await renderInTestApp(<WarningPanel {...propsMessage} />);
await renderInTestApp(
<ThemeProvider theme={lightTheme}>
<WarningPanel {...propsMessage} />
</ThemeProvider>,
);
expect(screen.getByText('Warning')).toBeInTheDocument();
expect(screen.getByText('Some more info')).toBeInTheDocument();
});
it('renders title, message, and children', async () => {
await renderInTestApp(
<WarningPanel {...propsTitleMessage}>
<Typography>Java stacktrace</Typography>
</WarningPanel>,
<ThemeProvider theme={lightTheme}>
<WarningPanel {...propsTitleMessage}>
<Typography>Java stacktrace</Typography>
</WarningPanel>
</ThemeProvider>,
);
expect(screen.getByText('Warning: Mock title')).toBeInTheDocument();
expect(screen.getByText('Some more info')).toBeInTheDocument();
expect(screen.getByText('Java stacktrace')).toBeInTheDocument();
});
it('renders message using severity', async () => {
await renderInTestApp(
<ThemeProvider theme={lightTheme}>
<WarningPanel {...propsErrorMessage} />
</ThemeProvider>,
);
expect(screen.getByText('Error: Mock title')).toBeInTheDocument();
});
});
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { BackstageTheme } from '@backstage/theme';
import {
Accordion,
@@ -22,60 +21,61 @@ import {
Grid,
makeStyles,
Typography,
darken,
lighten,
} from '@material-ui/core';
import ErrorOutline from '@material-ui/icons/ErrorOutline';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import React from 'react';
const getWarningTextColor = (
severity: Props['severity'],
severity: NonNullable<WarningProps['severity']>,
theme: BackstageTheme,
) => {
switch (severity) {
case 'error':
return theme.palette.errorText;
case 'info':
return theme.palette.infoText;
default:
return theme.palette.warningText;
}
const getColor = theme.palette.type === 'light' ? darken : lighten;
return getColor(theme.palette[severity].light, 0.6);
};
const getWarningBackgroundColor = (
severity: Props['severity'],
severity: NonNullable<WarningProps['severity']>,
theme: BackstageTheme,
) => {
switch (severity) {
case 'error':
return theme.palette.errorBackground;
case 'info':
return theme.palette.infoBackground;
default:
return theme.palette.warningBackground;
}
const getBackgroundColor = theme.palette.type === 'light' ? lighten : darken;
return getBackgroundColor(theme.palette[severity].light, 0.9);
};
const useErrorOutlineStyles = makeStyles<BackstageTheme>(theme => ({
root: {
marginRight: theme.spacing(1),
fill: ({ severity }: Props) => getWarningTextColor(severity, theme),
fill: ({ severity }: WarningProps) =>
getWarningTextColor(
severity as NonNullable<WarningProps['severity']>,
theme,
),
},
}));
const ErrorOutlineStyled = ({ severity }: Pick<Props, 'severity'>) => {
const ErrorOutlineStyled = ({ severity }: Pick<WarningProps, 'severity'>) => {
const classes = useErrorOutlineStyles({ severity });
return <ErrorOutline classes={classes} />;
};
const ExpandMoreIconStyled = ({ severity }: Pick<Props, 'severity'>) => {
const ExpandMoreIconStyled = ({ severity }: Pick<WarningProps, 'severity'>) => {
const classes = useErrorOutlineStyles({ severity });
return <ExpandMoreIcon classes={classes} />;
};
const useStyles = makeStyles<BackstageTheme>(theme => ({
panel: {
backgroundColor: ({ severity }: Props) =>
getWarningBackgroundColor(severity, theme),
color: ({ severity }: Props) => getWarningTextColor(severity, theme),
backgroundColor: ({ severity }: WarningProps) =>
getWarningBackgroundColor(
severity as NonNullable<WarningProps['severity']>,
theme,
),
color: ({ severity }: WarningProps) =>
getWarningTextColor(
severity as NonNullable<WarningProps['severity']>,
theme,
),
verticalAlign: 'middle',
},
summary: {
@@ -83,15 +83,26 @@ const useStyles = makeStyles<BackstageTheme>(theme => ({
flexDirection: 'row',
},
summaryText: {
color: ({ severity }: Props) => getWarningTextColor(severity, theme),
color: ({ severity }: WarningProps) =>
getWarningTextColor(
severity as NonNullable<WarningProps['severity']>,
theme,
),
fontWeight: 'bold',
},
message: {
width: '100%',
display: 'block',
color: ({ severity }: Props) => getWarningTextColor(severity, theme),
backgroundColor: ({ severity }: Props) =>
getWarningBackgroundColor(severity, theme),
color: ({ severity }: WarningProps) =>
getWarningTextColor(
severity as NonNullable<WarningProps['severity']>,
theme,
),
backgroundColor: ({ severity }: WarningProps) =>
getWarningBackgroundColor(
severity as NonNullable<WarningProps['severity']>,
theme,
),
},
details: {
width: '100%',
@@ -104,7 +115,7 @@ const useStyles = makeStyles<BackstageTheme>(theme => ({
},
}));
type Props = {
export type WarningProps = {
title?: string;
severity?: 'warning' | 'error' | 'info';
message?: React.ReactNode;
@@ -126,15 +137,14 @@ const capitalize = (s: string) => {
* @param {Object} [children] Objects to provide context, such as a stack trace or detailed error reporting.
* Will be available inside an unfolded accordion.
*/
export const WarningPanel = (props: Props) => {
const classes = useStyles(props);
const {
severity = 'warning',
title,
message,
children,
defaultExpanded,
} = props;
export const WarningPanel = ({
severity = 'warning',
title,
message,
children,
defaultExpanded,
}: WarningProps) => {
const classes = useStyles({ severity });
// If no severity or title provided, the heading will read simply "Warning"
const subTitle = capitalize(severity) + (title ? `: ${title}` : '');
@@ -100,7 +100,7 @@ describe('<GroupsExplorerContent />', () => {
const catalogError = new Error('Network timeout');
catalogApi.getEntities.mockRejectedValueOnce(catalogError);
const { getByText } = await renderInTestApp(
const { getAllByText } = await renderInTestApp(
<Wrapper>
<GroupsExplorerContent />
</Wrapper>,
@@ -108,7 +108,7 @@ describe('<GroupsExplorerContent />', () => {
);
await waitFor(() =>
expect(getByText(/Warning: Network timeout/)).toBeInTheDocument(),
expect(getAllByText(/Error: Network timeout/).length).not.toBe(0),
);
});
});
@@ -74,7 +74,7 @@ describe('<FossaCard />', () => {
fossaApi.getFindingSummary.mockRejectedValue(new Error('My Error'));
const { getByText } = await renderInTestApp(
const { getAllByText } = await renderInTestApp(
<Wrapper>
<EntityProvider entity={entity}>
<FossaCard />
@@ -82,7 +82,7 @@ describe('<FossaCard />', () => {
</Wrapper>,
);
expect(getByText(/Warning: My Error/i)).toBeInTheDocument();
expect(getAllByText(/Error: My Error/i).length).not.toBe(0);
});
it('shows empty', async () => {