From 2ae75e61968ee26a1f11f337da396cb93d159e5d Mon Sep 17 00:00:00 2001 From: Vikrant Gupta <54737045+Vikrant2520@users.noreply.github.com> Date: Tue, 14 Nov 2023 18:06:17 +0530 Subject: [PATCH] feat: happy flow for services from list view to all the three details tab rendering the correct tables (#3942) * feat: complete services flow * feat: complete all the three tab flows * feat: address review comments --- .../MetricsApplication/Tabs/DBCall.tsx | 4 +- .../MetricsApplication/Tabs/External.tsx | 8 +- .../Tabs/Overview/ApDex/index.tsx | 2 +- .../Tabs/Overview/ServiceOverview.tsx | 2 +- .../Tabs/Overview/TopLevelOperations.tsx | 2 +- .../tests/service/servicesLanding.spec.ts | 112 ++++++++++++++---- frontend/tests/service/utils.ts | 6 + 7 files changed, 105 insertions(+), 31 deletions(-) create mode 100644 frontend/tests/service/utils.ts diff --git a/frontend/src/container/MetricsApplication/Tabs/DBCall.tsx b/frontend/src/container/MetricsApplication/Tabs/DBCall.tsx index 68b5b797d5..7b92dca752 100644 --- a/frontend/src/container/MetricsApplication/Tabs/DBCall.tsx +++ b/frontend/src/container/MetricsApplication/Tabs/DBCall.tsx @@ -104,7 +104,7 @@ function DBCall(): JSX.Element { > View Traces - + - + View Traces - + - + View Traces - + - + + View Traces - + + {topLevelOperationsIsError ? ( {axios.isAxiosError(topLevelOperationsError) diff --git a/frontend/tests/service/servicesLanding.spec.ts b/frontend/tests/service/servicesLanding.spec.ts index 88896a7a78..69797e0ede 100644 --- a/frontend/tests/service/servicesLanding.spec.ts +++ b/frontend/tests/service/servicesLanding.spec.ts @@ -3,10 +3,11 @@ import ROUTES from 'constants/routes'; import servicesSuccessResponse from '../fixtures/api/services/200.json'; import { loginApi } from '../fixtures/common'; +import { SERVICE_TABLE_HEADERS } from './utils'; let page: Page; -test.describe('Service Page', () => { +test.describe('Service flow', () => { test.beforeEach(async ({ baseURL, browser }) => { const context = await browser.newContext({ storageState: 'tests/auth.json' }); const newPage = await context.newPage(); @@ -18,7 +19,7 @@ test.describe('Service Page', () => { page = newPage; }); - test('Services Empty Page', async ({ baseURL }) => { + test('Services empty page', async ({ baseURL }) => { // visit services page await page.goto(`${baseURL}${ROUTES.APPLICATION}`); @@ -33,13 +34,16 @@ test.describe('Service Page', () => { await expect(page.getByText('No data')).toBeVisible(); }); - test('Services Table Rendered with correct data', async ({ baseURL }) => { + test('Services table and service details page rendered with correct data', async ({ + baseURL, + }) => { // visit services page await page.goto(`${baseURL}${ROUTES.APPLICATION}`); // assert the URL of the services page await expect(page).toHaveURL(`${baseURL}${ROUTES.APPLICATION}`); + // mock the services list call to return non-empty data await page.route(`**/services`, (route) => route.fulfill({ status: 200, @@ -55,28 +59,92 @@ test.describe('Service Page', () => { await expect(breadcrumbServicesText).toEqual('Services'); // expect the services headers to be loaded correctly - const p99Latency = await page - .locator( - `th[aria-label*="this column's title is P99 latency (in ms)"] .ant-table-column-title`, - ) - .textContent(); + const p99Latency = page.locator( + `th:has-text("${SERVICE_TABLE_HEADERS.P99LATENCY}")`, + ); - await expect(p99Latency).toEqual('P99 latency (in ms)'); - const errorRate = await page - .locator( - `th[aria-label*="this column's title is Error Rate (% of total)"] .ant-table-column-title`, - ) - .textContent(); + await expect(p99Latency).toBeVisible(); + const errorRate = await page.locator( + `th:has-text("${SERVICE_TABLE_HEADERS.ERROR_RATE}")`, + ); - await expect(errorRate).toEqual('Error Rate (% of total)'); - const operationsPerSecond = await page - .locator( - `th[aria-label="this column's title is Operations Per Second,this column is sortable"] .ant-table-column-title`, - ) - .textContent(); + await expect(errorRate).toBeVisible(); + const operationsPerSecond = await page.locator( + `th:has-text("${SERVICE_TABLE_HEADERS.OPS_PER_SECOND}")`, + ); + + await expect(operationsPerSecond).toBeVisible(); - await expect(operationsPerSecond).toEqual('Operations Per Second'); // expect services to be listed in the table - await page.locator('a[href="/services/redis"]').isVisible(); + const redisService = await page + .locator('a[href="/services/redis"]') + .isVisible(); + + expect(redisService).toBeTruthy(); + + // route to a service details page + await page.locator('a[href="/services/redis"]').click(); + + // wait for the network calls to be settled + await page.waitForLoadState('networkidle'); + + // render the overview tab + await page.getByRole('tab', { name: 'Overview' }).click(); + + // check the presence of different graphs on the overview tab + const latencyGraph = await page + .locator('[data-testid="service_latency"]') + .isVisible(); + + expect(latencyGraph).toBeTruthy(); + + const rateOps = await page + .locator('[data-testid="operations_per_sec"]') + .isVisible(); + + expect(rateOps).toBeTruthy(); + + const errorPercentage = await page + .locator('[data-testid="error_percentage_%"]') + .isVisible(); + + expect(errorPercentage).toBeTruthy(); + + // navigate to the DB call metrics and validate the tables + await page.getByRole('tab', { name: 'DB Call Metrics' }).click(); + + const databaseCallRps = await page + .locator('[data-testid="database_call_rps"]') + .isVisible(); + expect(databaseCallRps).toBeTruthy(); + + const databaseCallsAvgDuration = await page + .locator('[data-testid="database_call_avg_duration"]') + .isVisible(); + expect(databaseCallsAvgDuration).toBeTruthy(); + + // navigate to external metrics and validate the tables + + await page.getByRole('tab', { name: 'External Metrics' }).click(); + + const externalCallErrorPerc = await page + .locator('[data-testid="external_call_error_percentage"]') + .isVisible(); + expect(externalCallErrorPerc).toBeTruthy(); + + const externalCallDuration = await page + .locator('[data-testid="external_call_duration"]') + .isVisible(); + expect(externalCallDuration).toBeTruthy(); + + const externalCallRps = await page + .locator('[data-testid="external_call_rps_by_address"]') + .isVisible(); + expect(externalCallRps).toBeTruthy(); + + const externalCallDurationByAddress = await page + .locator('[data-testid="external_call_duration_by_address"]') + .isVisible(); + expect(externalCallDurationByAddress).toBeTruthy(); }); }); diff --git a/frontend/tests/service/utils.ts b/frontend/tests/service/utils.ts new file mode 100644 index 0000000000..644a532d15 --- /dev/null +++ b/frontend/tests/service/utils.ts @@ -0,0 +1,6 @@ +export const SERVICE_TABLE_HEADERS = { + APPLICATION: 'Applicaton', + P99LATENCY: 'P99 latency (in ms)', + ERROR_RATE: 'Error Rate (% of total)', + OPS_PER_SECOND: 'Operations Per Second', +};