Skip to content

Commit 8ff173e

Browse files
committed
fix: fix: handle incorrect response for operations
1 parent ca71780 commit 8ff173e

File tree

4 files changed

+68
-6
lines changed

4 files changed

+68
-6
lines changed

src/containers/Operations/Operations.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
import React from 'react';
22

3-
import {AccessDenied} from '../../components/Errors/403';
4-
import {ResponseError} from '../../components/Errors/ResponseError';
3+
import {PageError} from '../../components/Errors/PageError/PageError';
54
import {ResizeableDataTable} from '../../components/ResizeableDataTable/ResizeableDataTable';
65
import {TableSkeleton} from '../../components/TableSkeleton/TableSkeleton';
76
import {TableWithControlsLayout} from '../../components/TableWithControlsLayout/TableWithControlsLayout';
87
import {DEFAULT_TABLE_SETTINGS} from '../../utils/constants';
9-
import {isAccessError} from '../../utils/response';
108

119
import {OperationsControls} from './OperationsControls';
1210
import {getColumns} from './columns';
@@ -41,8 +39,8 @@ export function Operations({database, scrollContainerRef}: OperationsProps) {
4139
};
4240
}, []);
4341

44-
if (isAccessError(error)) {
45-
return <AccessDenied position="left" />;
42+
if (error) {
43+
return <PageError error={error} position="left" />;
4644
}
4745

4846
return (
@@ -58,7 +56,6 @@ export function Operations({database, scrollContainerRef}: OperationsProps) {
5856
handleSearchChange={handleSearchChange}
5957
/>
6058
</TableWithControlsLayout.Controls>
61-
{error ? <ResponseError error={error} /> : null}
6259
<TableWithControlsLayout.Table loading={isLoading} className={b('table')}>
6360
{operations.length > 0 || isLoading ? (
6461
<ResizeableDataTable

tests/suites/tenant/diagnostics/tabs/OperationsModel.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ export class OperationsTable extends BaseModel {
1515
private scrollContainer: Locator;
1616
private accessDeniedState: Locator;
1717
private accessDeniedTitle: Locator;
18+
private pageErrorState: Locator;
19+
private pageErrorTitle: Locator;
20+
private pageErrorDescription: Locator;
1821

1922
constructor(page: Page) {
2023
super(page, page.locator('.kv-tenant-diagnostics'));
@@ -27,6 +30,10 @@ export class OperationsTable extends BaseModel {
2730
// AccessDenied component is rendered at the root level of Operations component
2831
this.accessDeniedState = page.locator('.kv-tenant-diagnostics .empty-state');
2932
this.accessDeniedTitle = this.accessDeniedState.locator('.empty-state__title');
33+
// PageError component also uses empty-state but with error illustration
34+
this.pageErrorState = page.locator('.kv-tenant-diagnostics .empty-state');
35+
this.pageErrorTitle = this.pageErrorState.locator('.empty-state__title');
36+
this.pageErrorDescription = this.pageErrorState.locator('.empty-state__description .error');
3037
}
3138

3239
async waitForTableVisible() {
@@ -194,4 +201,22 @@ export class OperationsTable extends BaseModel {
194201
// Now get the actual new count
195202
return await this.getOperationsCount();
196203
}
204+
205+
async isPageErrorVisible(): Promise<boolean> {
206+
try {
207+
await this.pageErrorState.waitFor({state: 'visible', timeout: VISIBILITY_TIMEOUT});
208+
// Check if it has error description to distinguish from access denied
209+
return await this.pageErrorDescription.isVisible();
210+
} catch {
211+
return false;
212+
}
213+
}
214+
215+
async getPageErrorTitle(): Promise<string> {
216+
return await this.pageErrorTitle.innerText();
217+
}
218+
219+
async getPageErrorDescription(): Promise<string> {
220+
return await this.pageErrorDescription.innerText();
221+
}
197222
}

tests/suites/tenant/diagnostics/tabs/operations.test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {Diagnostics, DiagnosticsTab} from '../Diagnostics';
77
import {
88
setupEmptyOperationsMock,
99
setupOperation403Mock,
10+
setupOperationNetworkErrorMock,
1011
setupOperationsMock,
1112
} from './operationsMocks';
1213

@@ -160,6 +161,37 @@ test.describe('Operations Tab - Infinite Query', () => {
160161
expect(accessDeniedTitle).toBe('Access denied');
161162
});
162163

164+
test('shows error state when operations request returns network error', async ({page}) => {
165+
// Setup network error mock (simulates CORS blocking)
166+
await setupOperationNetworkErrorMock(page);
167+
168+
const pageQueryParams = {
169+
schema: tenantName,
170+
database: tenantName,
171+
tenantPage: 'diagnostics',
172+
};
173+
174+
const tenantPageInstance = new TenantPage(page);
175+
await tenantPageInstance.goto(pageQueryParams);
176+
177+
const diagnostics = new Diagnostics(page);
178+
await diagnostics.clickTab(DiagnosticsTab.Operations);
179+
// Wait a bit for potential loading
180+
await page.waitForTimeout(2000);
181+
182+
// Wait for error state to be visible
183+
const isPageErrorVisible = await diagnostics.operations.isPageErrorVisible();
184+
expect(isPageErrorVisible).toBe(true);
185+
186+
// Verify the error title
187+
const errorTitle = await diagnostics.operations.getPageErrorTitle();
188+
expect(errorTitle).toBe('Error');
189+
190+
// Verify the error description shows network error
191+
const errorDescription = await diagnostics.operations.getPageErrorDescription();
192+
expect(errorDescription.toLowerCase()).toContain('network');
193+
});
194+
163195
test('loads all operations when scrolling to the bottom multiple times', async ({page}) => {
164196
// Setup mocks with 80 operations (4 pages of 20)
165197
await setupOperationsMock(page, {totalOperations: 80});

tests/suites/tenant/diagnostics/tabs/operationsMocks.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,3 +245,11 @@ export const setupAllOperationMocks = async (page: Page, options?: {totalOperati
245245
await setupOperationsMock(page, options);
246246
await setupOperationMutationMocks(page);
247247
};
248+
249+
export const setupOperationNetworkErrorMock = async (page: Page) => {
250+
await page.route(`${backend}/operation/list*`, async (route) => {
251+
// Simulate a network error by aborting the request
252+
// This mimics what happens when CORS blocks a request
253+
await route.abort('failed');
254+
});
255+
};

0 commit comments

Comments
 (0)