Fix tests to support window.matchMedia & add tests for responsiveness
Signed-off-by: Philipp Hugenroth <philipph@spotify.com>
This commit is contained in:
@@ -18,6 +18,8 @@ import { act } from '@testing-library/react';
|
||||
|
||||
type Breakpoint = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
||||
|
||||
const defaultBreakpoint: Breakpoint = 'xl';
|
||||
|
||||
const queryToBreakpoint = {
|
||||
'(min-width:1920px)': 'xl',
|
||||
'(min-width:1280px)': 'lg',
|
||||
@@ -26,14 +28,17 @@ const queryToBreakpoint = {
|
||||
'(min-width:0px)': 'xs',
|
||||
} as Record<string, Breakpoint>;
|
||||
|
||||
function toBreakpoint(query: string) {
|
||||
const breakpoint = queryToBreakpoint[query];
|
||||
if (!breakpoint) {
|
||||
throw new Error(
|
||||
`received unknown media query in breakpoint mock: '${query}'`,
|
||||
);
|
||||
}
|
||||
return breakpoint;
|
||||
/**
|
||||
* Converts media query string to Breakpoint.
|
||||
* Chooses the default breakpoint if no breakpoint is set in the media query.
|
||||
*
|
||||
* @param query media query string
|
||||
* @returns Breakpoint
|
||||
*/
|
||||
function toBreakpoint(query: string): Breakpoint {
|
||||
return queryToBreakpoint[query]
|
||||
? queryToBreakpoint[query]
|
||||
: defaultBreakpoint;
|
||||
}
|
||||
|
||||
type Listener = (event: { matches: boolean }) => void;
|
||||
@@ -41,6 +46,8 @@ type Listener = (event: { matches: boolean }) => void;
|
||||
interface QueryList {
|
||||
addListener(listener: Listener): void;
|
||||
removeListener(listener: Listener): void;
|
||||
addEventListener(listener: Listener): void;
|
||||
removeEventListener(listener: Listener): void;
|
||||
matches: boolean;
|
||||
}
|
||||
|
||||
@@ -50,12 +57,15 @@ interface Query {
|
||||
listeners: Set<Listener>;
|
||||
}
|
||||
|
||||
export default function mockBreakpoint(initialBreakpoint: Breakpoint = 'xl') {
|
||||
export default function mockBreakpoint(
|
||||
initialBreakpoint: Breakpoint = defaultBreakpoint,
|
||||
) {
|
||||
let currentBreakpoint = initialBreakpoint;
|
||||
const queries = Array<Query>();
|
||||
|
||||
const previousMatchMedia: any = (window as any).matchMedia;
|
||||
|
||||
// https://jestjs.io/docs/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom
|
||||
(window as any).matchMedia = (query: string): QueryList => {
|
||||
const listeners = new Set<Listener>();
|
||||
|
||||
@@ -66,6 +76,12 @@ export default function mockBreakpoint(initialBreakpoint: Breakpoint = 'xl') {
|
||||
removeListener(listener) {
|
||||
listeners.delete(listener);
|
||||
},
|
||||
addEventListener(listener) {
|
||||
listeners.add(listener);
|
||||
},
|
||||
removeEventListener(listener) {
|
||||
listeners.delete(listener);
|
||||
},
|
||||
matches: toBreakpoint(query) === currentBreakpoint,
|
||||
};
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import {
|
||||
MockStorageApi,
|
||||
renderWithEffects,
|
||||
wrapInTestApp,
|
||||
mockBreakpoint,
|
||||
} from '@backstage/test-utils';
|
||||
import { fireEvent, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
@@ -111,6 +112,8 @@ describe('CatalogPage', () => {
|
||||
getProfile: () => testProfile,
|
||||
};
|
||||
|
||||
const { set: setBreakpoint } = mockBreakpoint();
|
||||
|
||||
const renderWrapped = (children: React.ReactNode) =>
|
||||
renderWithEffects(
|
||||
wrapInTestApp(
|
||||
@@ -244,4 +247,10 @@ describe('CatalogPage', () => {
|
||||
screen.findByText(/Starred \(1\)/),
|
||||
).resolves.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should wrap filter in accordion on smaller screens', async () => {
|
||||
setBreakpoint('sm');
|
||||
const { findByText } = await renderWrapped(<CatalogPage />);
|
||||
await expect(findByText(/Filters/)).resolves.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -43,28 +43,24 @@ export type CatalogPageProps = {
|
||||
export const CatalogPage = ({
|
||||
columns,
|
||||
actions,
|
||||
initiallySelectedFilter,
|
||||
}: CatalogPageProps) => {
|
||||
return (
|
||||
<CatalogLayout>
|
||||
<Content>
|
||||
<ContentHeader title="Components">
|
||||
<CreateComponentButton />
|
||||
<SupportButton>All your software catalog entities</SupportButton>
|
||||
</ContentHeader>
|
||||
<Grid container spacing={2}>
|
||||
<EntityListProvider>
|
||||
<Grid item xs={12} sm={12} lg={2}>
|
||||
<CatalogFilter
|
||||
initiallySelectedFilter={initiallySelectedFilter}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={12} lg={10}>
|
||||
<CatalogTable columns={columns} actions={actions} />
|
||||
</Grid>
|
||||
</EntityListProvider>
|
||||
</Grid>
|
||||
</Content>
|
||||
</CatalogLayout>
|
||||
);
|
||||
};
|
||||
initiallySelectedFilter = 'owned',
|
||||
}: CatalogPageProps) => (
|
||||
<CatalogLayout>
|
||||
<Content>
|
||||
<ContentHeader title="Components">
|
||||
<CreateComponentButton />
|
||||
<SupportButton>All your software catalog entities</SupportButton>
|
||||
</ContentHeader>
|
||||
<Grid container spacing={2}>
|
||||
<EntityListProvider>
|
||||
<Grid item xs={12} sm={12} lg={2}>
|
||||
<CatalogFilter initiallySelectedFilter={initiallySelectedFilter} />
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={12} lg={10}>
|
||||
<CatalogTable columns={columns} actions={actions} />
|
||||
</Grid>
|
||||
</EntityListProvider>
|
||||
</Grid>
|
||||
</Content>
|
||||
</CatalogLayout>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user