Skip to content

Commit 4faad5b

Browse files
committed
fix(ui): Consistently use min-width media queries
Because we were using a mix of `max-width` and `min-width` media queries at the specific pixel size of the query one would apply but not the other, in some cases causing the layout to completely break.
1 parent f259f3d commit 4faad5b

File tree

8 files changed

+46
-45
lines changed

8 files changed

+46
-45
lines changed

static/app/components/profiling/flamegraph/flamegraph.spec.tsx

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -92,20 +92,6 @@ const flamechart = {
9292
version: '1',
9393
};
9494

95-
Object.defineProperty(window, 'matchMedia', {
96-
writable: true,
97-
value: jest.fn().mockImplementation(query => ({
98-
matches: false,
99-
media: query,
100-
onchange: null,
101-
addListener: jest.fn(), // Deprecated
102-
removeListener: jest.fn(), // Deprecated
103-
addEventListener: jest.fn(),
104-
removeEventListener: jest.fn(),
105-
dispatchEvent: jest.fn(),
106-
})),
107-
});
108-
10995
describe('Flamegraph', () => {
11096
beforeEach(() => {
11197
const project = ProjectFixture({slug: 'foo-project'});

static/app/views/issueList/actions/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ function IssueListActions({
179179
const theme = useTheme();
180180

181181
const disableActions = useMedia(
182-
`(max-width: ${isSavedSearchesOpen ? theme.breakpoints.xl : theme.breakpoints.md})`
182+
`(width < ${isSavedSearchesOpen ? theme.breakpoints.xl : theme.breakpoints.md})`
183183
);
184184

185185
const numIssues = selectedIdsSet.size;

static/app/views/issueList/groupListBody.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@ function GroupList({
100100
false
101101
);
102102
const topIssue = groupIds[0];
103-
const canSelect = !useMedia(
104-
`(max-width: ${isSavedSearchesOpen ? theme.breakpoints.xl : theme.breakpoints.md})`
103+
const canSelect = useMedia(
104+
`(min-width: ${isSavedSearchesOpen ? theme.breakpoints.xl : theme.breakpoints.md})`
105105
);
106106

107107
const columns: GroupListColumn[] = [

static/app/views/nav/context.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export function NavContextProvider({children}: {children: React.ReactNode}) {
5656
useState<PrimaryNavGroup | null>(null);
5757

5858
const theme = useTheme();
59-
const isMobile = useMedia(`(max-width: ${theme.breakpoints.md})`);
59+
const isMobile = useMedia(`(width < ${theme.breakpoints.md})`);
6060

6161
const startInteraction = useCallback(() => {
6262
isInteractingRef.current = true;

static/app/views/nav/index.spec.tsx

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
waitFor,
1111
within,
1212
} from 'sentry-test/reactTestingLibrary';
13+
import {mockMatchMedia} from 'sentry-test/utils';
1314

1415
import ConfigStore from 'sentry/stores/configStore';
1516
import {trackAnalytics} from 'sentry/utils/analytics';
@@ -336,23 +337,12 @@ describe('Nav', () => {
336337
});
337338

338339
describe('mobile navigation', () => {
339-
const initialMatchMedia = window.matchMedia;
340340
beforeEach(() => {
341-
// Need useMedia() to return true for isMobile query
342-
window.matchMedia = jest.fn().mockImplementation(query => ({
343-
matches: true,
344-
media: query,
345-
onchange: null,
346-
addListener: jest.fn(),
347-
removeListener: jest.fn(),
348-
addEventListener: jest.fn(),
349-
removeEventListener: jest.fn(),
350-
dispatchEvent: jest.fn(),
351-
}));
341+
mockMatchMedia(true);
352342
});
353343

354344
afterEach(() => {
355-
window.matchMedia = initialMatchMedia;
345+
jest.restoreAllMocks();
356346
});
357347

358348
it('renders mobile navigation on small screen sizes', async () => {

static/app/views/profiling/profileSummary/profileSummaryPage.spec.tsx

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,24 +4,11 @@ import {OrganizationFixture} from 'sentry-fixture/organization';
44
import {ProjectFixture} from 'sentry-fixture/project';
55

66
import {render, screen} from 'sentry-test/reactTestingLibrary';
7+
import {mockMatchMedia} from 'sentry-test/utils';
78

89
import OrganizationStore from 'sentry/stores/organizationStore';
910
import ProfileSummaryPage from 'sentry/views/profiling/profileSummary';
1011

11-
Object.defineProperty(window, 'matchMedia', {
12-
writable: true,
13-
value: jest.fn().mockImplementation(query => ({
14-
matches: false,
15-
media: query,
16-
onchange: null,
17-
addListener: jest.fn(), // Deprecated
18-
removeListener: jest.fn(), // Deprecated
19-
addEventListener: jest.fn(),
20-
removeEventListener: jest.fn(),
21-
dispatchEvent: jest.fn(),
22-
})),
23-
});
24-
2512
window.ResizeObserver =
2613
window.ResizeObserver ||
2714
jest.fn().mockImplementation(() => ({
@@ -31,6 +18,14 @@ window.ResizeObserver =
3118
}));
3219

3320
describe('ProfileSummaryPage', () => {
21+
beforeEach(() => {
22+
mockMatchMedia(true);
23+
});
24+
25+
afterEach(() => {
26+
jest.restoreAllMocks();
27+
});
28+
3429
it('renders new page', async () => {
3530
const organization = OrganizationFixture({features: []});
3631
OrganizationStore.onUpdate(organization);

tests/js/sentry-test/utils.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,19 @@ export function setWindowLocation(url: string) {
5151
// global jsdom is coming from `@sentry/jest-environment`
5252
(global as any).jsdom.reconfigure({url});
5353
}
54+
55+
/**
56+
* Mocks window.matchMedia to always return the provided `matches`.
57+
*/
58+
export function mockMatchMedia(matches: boolean) {
59+
jest.spyOn(window, 'matchMedia').mockImplementation(() => ({
60+
matches,
61+
media: '',
62+
onchange: null,
63+
addListener: jest.fn(),
64+
removeListener: jest.fn(),
65+
addEventListener: jest.fn(),
66+
removeEventListener: jest.fn(),
67+
dispatchEvent: jest.fn(),
68+
}));
69+
}

tests/js/setup.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,20 @@ Object.defineProperty(window, 'getComputedStyle', {
238238
writable: true,
239239
});
240240

241+
Object.defineProperty(window, 'matchMedia', {
242+
writable: true,
243+
value: (query: string) => ({
244+
matches: false,
245+
media: query,
246+
onchange: null,
247+
addListener: jest.fn(), // Deprecated
248+
removeListener: jest.fn(), // Deprecated
249+
addEventListener: jest.fn(),
250+
removeEventListener: jest.fn(),
251+
dispatchEvent: jest.fn(),
252+
}),
253+
});
254+
241255
window.IntersectionObserver = class IntersectionObserver {
242256
root = null;
243257
rootMargin = '';

0 commit comments

Comments
 (0)