Skip to content

Commit ce9545b

Browse files
authored
fix(admin): infinite loading when production is missing (#18313)
1 parent 325a63c commit ce9545b

File tree

2 files changed

+40
-7
lines changed

2 files changed

+40
-7
lines changed

src/Designer/frontend/admin/features/apps/pages/apps/components/AppsTable.test.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,17 @@ jest.mock('axios', () => ({
4141
jest.mock('admin/features/apps/hooks/useQueryParamState');
4242

4343
const mockSetRange = jest.fn();
44+
const mockSetEnvironment = jest.fn();
4445

4546
describe('AppsTable', () => {
4647
beforeEach(() => {
4748
jest.mocked(useQueryParamState).mockImplementation((key, defaultValue) => {
4849
if (key === 'range') {
4950
return [1440, mockSetRange];
5051
}
52+
if (key === 'environment') {
53+
return [defaultValue, mockSetEnvironment];
54+
}
5155
return [defaultValue, jest.fn()];
5256
});
5357
});
@@ -169,6 +173,29 @@ describe('AppsTable', () => {
169173
});
170174
});
171175

176+
describe('environment fallback', () => {
177+
beforeEach(() => {
178+
jest.mocked(useQueryParamState).mockImplementation((key, defaultValue) => {
179+
if (key === 'range') return [1440, mockSetRange];
180+
if (key === 'environment') return ['production', mockSetEnvironment];
181+
return [defaultValue, jest.fn()];
182+
});
183+
});
184+
185+
it('should render the first available environment and update selectedEnvironment when it is not available', () => {
186+
const queryClient = createQueryClientMock();
187+
queryClient.setQueryData([QueryKey.PublishedApps, org], {
188+
tt02: [{ app, env: 'tt02', org, version: '1' }],
189+
});
190+
191+
renderAppsTable(queryClient);
192+
193+
expect(screen.getByRole('tab', { name: /tt02/i })).toBeInTheDocument();
194+
expect(screen.queryByLabelText(textMock('general.loading'))).not.toBeInTheDocument();
195+
expect(mockSetEnvironment).toHaveBeenCalledWith('tt02');
196+
});
197+
});
198+
172199
it('should change range when selecting a new range', async () => {
173200
const user = userEvent.setup();
174201

src/Designer/frontend/admin/features/apps/pages/apps/components/AppsTable.tsx

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
StudioTabs,
1111
StudioAlert,
1212
} from '@studio/components';
13-
import React from 'react';
13+
import React, { useEffect } from 'react';
1414
import { useTranslation } from 'react-i18next';
1515
import { Link } from 'react-router-dom';
1616
import { useQueryParamState } from 'admin/features/apps/hooks/useQueryParamState';
@@ -63,19 +63,25 @@ const AppsTableWithData = ({ org, runningApps }: AppsTableWithDataProps) => {
6363

6464
const availableEnvironments = Object.keys(runningApps).toSorted(sortEnvironments);
6565

66+
const activeEnvironment =
67+
selectedEnvironment && availableEnvironments.includes(selectedEnvironment)
68+
? selectedEnvironment
69+
: availableEnvironments[0];
70+
71+
useEffect(() => {
72+
if (activeEnvironment && activeEnvironment !== selectedEnvironment) {
73+
setSelectedEnvironment(activeEnvironment);
74+
}
75+
}, [activeEnvironment, selectedEnvironment, setSelectedEnvironment]);
76+
6677
if (!availableEnvironments.length) {
6778
return (
6879
<StudioAlert data-color='info'>{t('admin.environment.no_results', { orgName })}</StudioAlert>
6980
);
7081
}
7182

72-
if (!selectedEnvironment || !availableEnvironments.includes(selectedEnvironment)) {
73-
setSelectedEnvironment(availableEnvironments[0]);
74-
return <StudioSpinner aria-label={t('general.loading')} />;
75-
}
76-
7783
return (
78-
<StudioTabs value={selectedEnvironment} onChange={setSelectedEnvironment}>
84+
<StudioTabs value={activeEnvironment} onChange={setSelectedEnvironment}>
7985
<StudioTabs.List>
8086
{availableEnvironments.map((environment) => (
8187
<StudioTabs.Tab key={environment} value={environment}>

0 commit comments

Comments
 (0)