Skip to content

[DI-30013]: automate E2E coverage for CloudPulse Logs service dashboard - #639

Merged
agorthi-akamai merged 25 commits into
ACLPManager:aclp_developfrom
agorthi-akamai:logs-integration-feature_venky_February_26
Mar 3, 2026
Merged

agorthi-akamai merged 25 commits into
ACLPManager:aclp_developfrom
agorthi-akamai:logs-integration-feature_venky_February_26

Conversation

@agorthi-akamai

Copy link
Copy Markdown

Description 📝

Highlight the Pull Request's context and intentions.

Changes 🔄

List any change(s) relevant to the reviewer.

  • ...
  • ...

Scope 🚢

Upon production release, changes in this PR will be visible to:

  • All customers
  • Some customers (e.g. in Beta or Limited Availability)
  • No customers / Not applicable

Target release date 🗓️

Please specify a release date (and environment, if applicable) to guarantee timely review of this PR. If exact date is not known, please approximate and update it as needed.

Preview 📷

Include a screenshot <img src="" /> or video <video src="" /> of the change.

🔒 Use the Mask Sensitive Data setting for security.

💡 For changes requiring multiple steps to validate, prefer a video for clarity.

Before After
📷 📷

How to test 🧪

Prerequisites

(How to setup test environment)

  • ...
  • ...

Reproduction steps

(How to reproduce the issue, if applicable)

  • ...
  • ...

Verification steps

(How to verify changes)

  • ...
  • ...
Author Checklists

As an Author, to speed up the review process, I considered 🤔

Check all that apply

  •  Use React components instead of HTML Tags
  • Proper naming conventions like cameCase for variables & Function & snake_case for constants
  • Use appropriate types & avoid using "any"
  • No type casting & non-null assertions
  • Adding a changeset
  • Providing/Improving test coverage
  • Use sx props to pass styles instead of style prop
  • Add JSDoc comments for interface properties & functions
  • Use strict equality (===) instead of double equal (==)
  • Use of named arguments (interfaces) if function argument list exceeds size 2
  • Destructure the props
  • Keep component size small & move big computing functions to separate utility
  • 📱 Providing mobile support

  • I have read and considered all applicable items listed above.

As an Author, before moving this PR from Draft to Open, I confirmed ✅

  • All tests and CI checks are passing
  • TypeScript compilation succeeded without errors
  • Code passes all linting rules

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds end-to-end test coverage for the CloudPulse Logs service dashboard, enabling monitoring of log delivery status with metrics like success/error upload counts and error rates.

Changes:

  • Added comprehensive E2E tests for Logs dashboard functionality including widget display, filtering, preferences, and user interactions
  • Integrated Logs service type across CloudPulse components with proper mocking and test data
  • Added status code filter support with validation and UI components

Reviewed changes

Copilot reviewed 22 out of 23 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
packages/manager/src/queries/cloudpulse/queries.ts Added deliveryQueries import and logs case for resource resolution
packages/manager/src/mocks/serverHandlers.ts Added mock endpoints for logs service, streams, dashboards, and metric definitions
packages/manager/src/mocks/presets/crud/handlers/cloudpulsedashboards.ts New comprehensive mock handlers file for CloudPulse dashboards (974 lines)
packages/manager/src/mocks/presets/crud/delivery.ts Integrated CloudPulse handlers into delivery CRUD preset
packages/manager/src/features/Delivery/Streams/StreamForm/StreamEdit.tsx Embedded CloudPulseDashboardWithFilters component in stream edit page
packages/manager/src/features/CloudPulse/shared/*.tsx Added logs service support and status_code filter to dashboard components
packages/manager/src/features/CloudPulse/Utils/*.ts Added status code validation, constants, and filter configurations
packages/manager/cypress/e2e/core/cloudpulse/*.spec.ts Three comprehensive test files covering template building, preferences, and widgets
packages/manager/cypress/fixtures/Logs.xlsx Excel fixture for generating JSON test data
packages/api-v4/src/cloudpulse/types.ts Added 'logs' to CloudPulseServiceType union
Comments suppressed due to low confidence (1)

packages/manager/src/features/CloudPulse/Utils/constants.ts:139

  • The PLACEHOLDER_TEXT mapping is missing an entry for STATUS_CODE, even though STATUS_CODE_PLACEHOLDER_TEXT is defined. This will cause the status code input to not have a placeholder text. Add the missing mapping:
[STATUS_CODE]: STATUS_CODE_PLACEHOLDER_TEXT,
export const PLACEHOLDER_TEXT: Record<string, string> = {
  [PORT]: PORTS_PLACEHOLDER_TEXT,
  [INTERFACE_ID]: INTERFACE_IDS_PLACEHOLDER_TEXT,
};

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/manager/src/mocks/presets/crud/handlers/cloudpulsedashboards.ts Outdated
Comment thread packages/manager/src/mocks/presets/crud/handlers/cloudpulsedashboards.ts Outdated
Comment on lines +1 to +3
/**
* @file Integration Tests for CloudPulse Volume(blockstorage) Dashboard.
*/

Copilot AI Feb 26, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The JSDoc comment header is incorrect. It states "Integration Tests for CloudPulse Volume(blockstorage) Dashboard" but this file actually contains tests for the CloudPulse Logs Dashboard. The comment should be updated to reflect the correct service type being tested.

Copilot uses AI. Check for mistakes.
Comment thread packages/manager/cypress/e2e/core/cloudpulse/log-widget-verification.spec.ts Outdated
Comment on lines +399 to +422
export const areValidStatusCodes = (
statusCodes: string
): string | undefined => {
if (statusCodes === '') {
return undefined;
}

if (statusCodes.length > 100) {
return STATUS_CODE_LIMIT_ERROR_MESSAGE;
}
if (statusCodes.startsWith(',')) {
return STATUS_CODE_LEADING_COMMA_ERROR_MESSAGE;
}

if (statusCodes.includes(',,')) {
return STATUS_CODE_CONSECUTIVE_COMMAS_ERROR_MESSAGE;
}

if (!/^[\d,]+$/.test(statusCodes)) {
return STATUS_CODE_ERROR_MESSAGE;
}

return undefined;
};

Copilot AI Feb 26, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The areValidStatusCodes function is missing important validation checks that are present in the similar arePortsValid function:

  1. No validation for leading zeros (status codes like "0200" should be invalid)
  2. No range validation (HTTP status codes should be in the range 100-599)

Consider adding these validations for better data integrity. For example:

  • Check for leading zeros: if (code.startsWith('0') && code !== '0')
  • Validate range: const codeNum = parseInt(code, 10); if (codeNum < 100 || codeNum > 599)

Even though the STATUS_CODE_LEADING_ZERO_ERROR_MESSAGE constant is defined, it's not being used in the validation logic.

Copilot uses AI. Check for mistakes.
agorthi-akamai and others added 6 commits February 26, 2026 18:57
…rvice-preference-verification.spec.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…hboards.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…hboards.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…cation.spec.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@agorthi-akamai

Copy link
Copy Markdown
Author

run_cypress

@agorthi-akamai

Copy link
Copy Markdown
Author

run_cypress

@agorthi-akamai

Copy link
Copy Markdown
Author

run_cypress

@agorthi-akamai

Copy link
Copy Markdown
Author

run_cypress

@agorthi-akamai

Copy link
Copy Markdown
Author

run_cypress

@agorthi-akamai

Copy link
Copy Markdown
Author

run_cypress

@agorthi-akamai

Copy link
Copy Markdown
Author

run_cypress

@agorthi-akamai

Copy link
Copy Markdown
Author

run_cypress

@agorthi-akamai

Copy link
Copy Markdown
Author

@ACLPManager/reviewers : please review this

@agorthi-akamai

Copy link
Copy Markdown
Author

run_cypress

@agorthi-akamai

Copy link
Copy Markdown
Author

run_cypress

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 14 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +855 to +860
export const mockGetStreams = (streams: Stream[]): Cypress.Chainable<null> => {
return cy.intercept(
'GET',
apiMatcher('monitor/streams?page_size=500'),
paginateResponse(streams)
);

Copilot AI Mar 2, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mockGetStreams intercept matches only the exact URL monitor/streams?page_size=500, which is brittle if the app requests streams with default pagination (e.g. page/page_size) or any other query params. Consider matching monitor/streams* (or accepting params and building the matcher accordingly) so stream-related E2E tests don’t silently miss the intercept and hit the network/MSW fallback.

Copilot uses AI. Check for mistakes.
Comment on lines +174 to +178
mockGetCloudPulseMetricDefinitions(serviceType, metricDefinitions);
mockGetCloudPulseDashboards(serviceType, [dashboard]).as('fetchDashboard');
mockGetCloudPulseServices([serviceType]).as('fetchServices');
mockGetCloudPulseDashboard(id, dashboard).as('fetchDashboard');
mockCreateCloudPulseJWEToken(serviceType);

Copilot AI Mar 2, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both mockGetCloudPulseDashboards(...).as('fetchDashboard') and mockGetCloudPulseDashboard(...).as('fetchDashboard') register the same alias. This will cause cy.wait('@fetchDashboard') to resolve against whichever intercept was registered last, and the subsequent assertion treats the response as a paginated list (response.body.data), which will fail if it resolves to the single-dashboard response. Use distinct aliases (e.g. fetchDashboards vs fetchDashboardById) and update the waits/assertions accordingly.

Copilot uses AI. Check for mistakes.
Comment on lines +38 to +43
const initialPreference = {
dashboardId: 11,
groupBy: ['entity_id', 'status_code'],
resources: ['1'],
status_code: '200',
widgets: {

Copilot AI Mar 2, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

initialPreference.dashboardId is hard-coded to 11 even though this spec already pulls the dashboard id from widgetDetails.logs. This creates an easy-to-miss mismatch if widgetDetails.logs.id changes. Use the id constant (and/or derive it from the constructed dashboard) to keep the preference payload aligned with the test’s mocked dashboard.

Copilot uses AI. Check for mistakes.
Comment on lines +367 to 373
it('MetricDefinitionResponse JSON response', () => {
cy.writeFile(METRIC_DEF_PATH, metricDefinitionResponse, { flag: 'w' });
});

// eslint-disable-next-line sonarjs/no-skipped-tests

describe('Dashboard Builder Response', () => {
it('has correct top-level structure', () => {
expect(dashboardResponse.page).to.equal(1);
expect(dashboardResponse.pages).to.equal(1);
expect(dashboardResponse.results).to.equal(1);
expect(dashboardResponse.data).to.have.length(1);
});

it('dashboard has correct fields', () => {
const dashboard = dashboardResponse.data[0];
expect(dashboard).to.have.property('label').and.not.be.empty;
expect(dashboard).to.have.property('type', 'standard');
expect(dashboard).to.have.property('service_type');
expect(dashboard).to.have.property('group_by').and.be.an('array');
expect(dashboard).to.have.property('widgets').and.be.an('array');
});

it('dashboard has correct number of widgets from Excel', () => {
const dashboard = dashboardResponse.data[0];
expect(dashboard.widgets).to.have.length(6); // 8 widgets in Centralized Dashboard sheet
});

it('each widget has required fields', () => {
dashboardResponse.data[0].widgets.forEach((widget) => {
expect(widget).to.have.property('metric').and.not.be.empty;
expect(widget).to.have.property('unit');
expect(widget).to.have.property('label').and.not.be.empty;
expect(widget).to.have.property('color');
expect(widget).to.have.property('size').and.be.a('number');
expect(widget).to.have.property('chart_type');
expect(widget).to.have.property('y_label');
expect(widget).to.have.property('aggregate_function');
});
});


});
// eslint-disable-next-line sonarjs/no-skipped-tests

it.skip('MetricDefinitionResponse JSON response', () => {
cy.writeFile(
'cypress/e2e/core/cloudpulse/api-response/netloadbalancer-metric-definition.json',
metricDefinitionResponse
);
});
// eslint-disable-next-line sonarjs/no-skipped-tests

it.skip('dashboardResponse JSON response', () => {
cy.writeFile(
'cypress/e2e/core/cloudpulse/api-response/netloadbalancer-dashboard-response.json',
dashboardResponse
);
it('dashboardResponse JSON response', () => {
cy.writeFile(DASHBOARD_PATH, dashboardResponse, { flag: 'w' });
});

Copilot AI Mar 2, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This spec no longer asserts anything about the generated responses; it only writes files to the repo workspace during the E2E run. Since cypress/e2e/core/**/*.spec.* runs in CI, this adds side effects (file writes) without validating behavior and can mask regressions. Consider restoring structural/content assertions and moving JSON generation to a separate, manually-run script (or at least skipping these tests in CI).

Copilot uses AI. Check for mistakes.
@agorthi-akamai

Copy link
Copy Markdown
Author

run_cypress

@agorthi-akamai

Copy link
Copy Markdown
Author

run_cypress_metrics

@agorthi-akamai

Copy link
Copy Markdown
Author

run_cypress_metrics

@agorthi-akamai
agorthi-akamai merged commit dbcc1c6 into ACLPManager:aclp_develop Mar 3, 2026
33 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants