Skip to content

CONSOLE-4447: Migrate knative-plugin modals to PatternFly 6#16065

Open
rhamilto wants to merge 1 commit intoopenshift:mainfrom
rhamilto:CONSOLE-4447-knative
Open

CONSOLE-4447: Migrate knative-plugin modals to PatternFly 6#16065
rhamilto wants to merge 1 commit intoopenshift:mainfrom
rhamilto:CONSOLE-4447-knative

Conversation

@rhamilto
Copy link
Member

@rhamilto rhamilto commented Feb 25, 2026

Summary

Migrate knative-plugin modals from deprecated factory components to PatternFly 6 Modal components.

This PR migrates 7 modals:

  • SinkSourceModal
  • PubSubModal
  • SinkPubsubModal
  • DeleteRevisionModal
  • SinkUriModal
  • TestFunctionModal
  • TrafficSplittingModal

Note: This PR includes changes from #16015, so it should merge first.

Changes

  • Replace ModalWrapper with PatternFly 6 Modal in controller components
  • Replace ModalTitle with ModalHeader (with labelId and data-test-id="modal-title")
  • Move Form inside ModalBody for consistency
  • Replace ModalSubmitFooter with ModalFooter or ModalFooterWithAlerts
  • Add form attribute to submit buttons to connect to form id
  • Add data-test-id="modal-cancel-action" to cancel buttons for integration tests
  • Update unit tests to mock PatternFly 6 components
  • Fix bug in TestFunction: service.data.metadataservice.metadata

Pattern

All modals now follow consistent pattern:

  • Modal wrapper in Controller component with variant="small"
  • ModalHeader with accessibility labelId and data-test-id="modal-title"
  • Form inside ModalBody with unique id and className="pf-v6-u-mr-md"
  • Submit button with type="submit" and form attribute
  • Cancel button with variant="link" and data-test-id="modal-cancel-action"

Test plan

  • Unit tests passing for all modified modal components
  • Integration tests passing with updated test IDs
  • Build passing
  • Visual/functional testing of each modal

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • Refactor

    • Updated modal dialogs to use PatternFly components for improved consistency and visual organization.
    • Reorganized modal layouts with clearer separation of headers, body content, and footer actions.
    • Improved form submission handling with explicit form-to-button associations.
  • Tests

    • Updated test infrastructure to align with new modal component structure.

@openshift-ci openshift-ci bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Feb 25, 2026
@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Feb 25, 2026
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Feb 25, 2026

@rhamilto: This pull request references CONSOLE-4447 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Summary

Migrate knative-plugin modals from deprecated factory components to PatternFly 6 Modal components.

This PR migrates 7 modals:

  • SinkSourceModal
  • PubSubModal
  • SinkPubsubModal
  • DeleteRevisionModal
  • SinkUriModal
  • TestFunctionModal
  • TrafficSplittingModal

Changes

  • Replace ModalWrapper with PatternFly 6 Modal in controller components
  • Replace ModalTitle with ModalHeader (with labelId and data-test-id="modal-title")
  • Move Form inside ModalBody for consistency
  • Replace ModalSubmitFooter with ModalFooter or ModalFooterWithAlerts
  • Add form attribute to submit buttons to connect to form id
  • Add data-test-id="modal-cancel-action" to cancel buttons for integration tests
  • Update unit tests to mock PatternFly 6 components
  • Fix bug in TestFunction: service.data.metadataservice.metadata

Pattern

All modals now follow consistent pattern:

  • Modal wrapper in Controller component with variant="small"
  • ModalHeader with accessibility labelId and data-test-id="modal-title"
  • Form inside ModalBody with unique id and className="pf-v6-u-mr-md"
  • Submit button with type="submit" and form attribute
  • Cancel button with variant="link" and data-test-id="modal-cancel-action"

Test plan

  • Unit tests passing for all modified modal components
  • Integration tests passing with updated test IDs
  • Build passing
  • Visual/functional testing of each modal

🤖 Generated with Claude Code

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci openshift-ci bot requested review from jhadvig and spadgett February 25, 2026 20:39
@openshift-ci openshift-ci bot added the component/core Related to console core functionality label Feb 25, 2026
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Feb 25, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: rhamilto

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci bot added component/knative Related to knative-plugin approved Indicates a PR has been approved by an approver from all required OWNERS files. component/metal3 Related to metal3-plugin component/olm Related to OLM component/shared Related to console-shared labels Feb 25, 2026
@rhamilto
Copy link
Member Author

/retest

3 similar comments
@rhamilto
Copy link
Member Author

/retest

@rhamilto
Copy link
Member Author

/retest

@rhamilto
Copy link
Member Author

/retest

@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Feb 27, 2026

@rhamilto: This pull request references CONSOLE-4447 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Summary

Migrate knative-plugin modals from deprecated factory components to PatternFly 6 Modal components.

This PR migrates 7 modals:

  • SinkSourceModal
  • PubSubModal
  • SinkPubsubModal
  • DeleteRevisionModal
  • SinkUriModal
  • TestFunctionModal
  • TrafficSplittingModal

Note: This PR includes changes from #16015, so it should merge first.

Changes

  • Replace ModalWrapper with PatternFly 6 Modal in controller components
  • Replace ModalTitle with ModalHeader (with labelId and data-test-id="modal-title")
  • Move Form inside ModalBody for consistency
  • Replace ModalSubmitFooter with ModalFooter or ModalFooterWithAlerts
  • Add form attribute to submit buttons to connect to form id
  • Add data-test-id="modal-cancel-action" to cancel buttons for integration tests
  • Update unit tests to mock PatternFly 6 components
  • Fix bug in TestFunction: service.data.metadataservice.metadata

Pattern

All modals now follow consistent pattern:

  • Modal wrapper in Controller component with variant="small"
  • ModalHeader with accessibility labelId and data-test-id="modal-title"
  • Form inside ModalBody with unique id and className="pf-v6-u-mr-md"
  • Submit button with type="submit" and form attribute
  • Cancel button with variant="link" and data-test-id="modal-cancel-action"

Test plan

  • Unit tests passing for all modified modal components
  • Integration tests passing with updated test IDs
  • Build passing
  • Visual/functional testing of each modal

🤖 Generated with Claude Code

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@rhamilto
Copy link
Member Author

/retest

2 similar comments
@rhamilto
Copy link
Member Author

rhamilto commented Mar 2, 2026

/retest

@rhamilto
Copy link
Member Author

rhamilto commented Mar 2, 2026

/retest

@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Mar 3, 2026

@rhamilto: This pull request references CONSOLE-4447 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Summary

Migrate knative-plugin modals from deprecated factory components to PatternFly 6 Modal components.

Note: This PR includes changes from #16015, so it should merge first.

This PR migrates 7 modals:

  • SinkSourceModal
  • PubSubModal
  • SinkPubsubModal
  • DeleteRevisionModal
  • SinkUriModal
  • TestFunctionModal
  • TrafficSplittingModal

Note: This PR includes changes from #16015, so it should merge first.

Changes

  • Replace ModalWrapper with PatternFly 6 Modal in controller components
  • Replace ModalTitle with ModalHeader (with labelId and data-test-id="modal-title")
  • Move Form inside ModalBody for consistency
  • Replace ModalSubmitFooter with ModalFooter or ModalFooterWithAlerts
  • Add form attribute to submit buttons to connect to form id
  • Add data-test-id="modal-cancel-action" to cancel buttons for integration tests
  • Update unit tests to mock PatternFly 6 components
  • Fix bug in TestFunction: service.data.metadataservice.metadata

Pattern

All modals now follow consistent pattern:

  • Modal wrapper in Controller component with variant="small"
  • ModalHeader with accessibility labelId and data-test-id="modal-title"
  • Form inside ModalBody with unique id and className="pf-v6-u-mr-md"
  • Submit button with type="submit" and form attribute
  • Cancel button with variant="link" and data-test-id="modal-cancel-action"

Test plan

  • Unit tests passing for all modified modal components
  • Integration tests passing with updated test IDs
  • Build passing
  • Visual/functional testing of each modal

🤖 Generated with Claude Code

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@rhamilto rhamilto force-pushed the CONSOLE-4447-knative branch from e8d2b1c to 158afe6 Compare March 3, 2026 16:33
@rhamilto
Copy link
Member Author

rhamilto commented Mar 3, 2026

/retest

6 similar comments
@rhamilto
Copy link
Member Author

rhamilto commented Mar 3, 2026

/retest

@rhamilto
Copy link
Member Author

rhamilto commented Mar 4, 2026

/retest

@rhamilto
Copy link
Member Author

rhamilto commented Mar 4, 2026

/retest

@rhamilto
Copy link
Member Author

rhamilto commented Mar 5, 2026

/retest

@rhamilto
Copy link
Member Author

rhamilto commented Mar 5, 2026

/retest

@rhamilto
Copy link
Member Author

rhamilto commented Mar 5, 2026

/retest

@rhamilto
Copy link
Member Author

rhamilto commented Mar 6, 2026

/retest

@rhamilto rhamilto force-pushed the CONSOLE-4447-knative branch from 158afe6 to d5d0e63 Compare March 6, 2026 16:21
@openshift-ci openshift-ci bot added the component/topology Related to topology label Mar 6, 2026
@rhamilto
Copy link
Member Author

rhamilto commented Mar 6, 2026

/retest

3 similar comments
@rhamilto
Copy link
Member Author

rhamilto commented Mar 7, 2026

/retest

@rhamilto
Copy link
Member Author

rhamilto commented Mar 7, 2026

/retest

@rhamilto
Copy link
Member Author

rhamilto commented Mar 7, 2026

/retest

@rhamilto rhamilto force-pushed the CONSOLE-4447-knative branch from d5d0e63 to 1e2584c Compare March 8, 2026 13:52
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Mar 8, 2026

@rhamilto: This pull request references CONSOLE-4447 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Summary

Migrate knative-plugin modals from deprecated factory components to PatternFly 6 Modal components.

This PR migrates 7 modals:

  • SinkSourceModal
  • PubSubModal
  • SinkPubsubModal
  • DeleteRevisionModal
  • SinkUriModal
  • TestFunctionModal
  • TrafficSplittingModal

Note: This PR includes changes from #16015, so it should merge first.

Changes

  • Replace ModalWrapper with PatternFly 6 Modal in controller components
  • Replace ModalTitle with ModalHeader (with labelId and data-test-id="modal-title")
  • Move Form inside ModalBody for consistency
  • Replace ModalSubmitFooter with ModalFooter or ModalFooterWithAlerts
  • Add form attribute to submit buttons to connect to form id
  • Add data-test-id="modal-cancel-action" to cancel buttons for integration tests
  • Update unit tests to mock PatternFly 6 components
  • Fix bug in TestFunction: service.data.metadataservice.metadata

Pattern

All modals now follow consistent pattern:

  • Modal wrapper in Controller component with variant="small"
  • ModalHeader with accessibility labelId and data-test-id="modal-title"
  • Form inside ModalBody with unique id and className="pf-v6-u-mr-md"
  • Submit button with type="submit" and form attribute
  • Cancel button with variant="link" and data-test-id="modal-cancel-action"

Test plan

  • Unit tests passing for all modified modal components
  • Integration tests passing with updated test IDs
  • Build passing
  • Visual/functional testing of each modal

🤖 Generated with Claude Code

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@rhamilto rhamilto changed the title [WIP] CONSOLE-4447: Migrate knative-plugin modals to PatternFly 6 CONSOLE-4447: Migrate knative-plugin modals to PatternFly 6 Mar 8, 2026
@openshift-ci openshift-ci bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Mar 8, 2026
@rhamilto
Copy link
Member Author

rhamilto commented Mar 8, 2026

/assign @yapei
/assign @sg00dwin

@rhamilto
Copy link
Member Author

rhamilto commented Mar 8, 2026

Tech debt
/label docs-approved
/label px-approved

@openshift-ci openshift-ci bot added docs-approved Signifies that Docs has signed off on this PR px-approved Signifies that Product Support has signed off on this PR labels Mar 8, 2026
@rhamilto
Copy link
Member Author

rhamilto commented Mar 8, 2026

/retest

2 similar comments
@rhamilto
Copy link
Member Author

rhamilto commented Mar 8, 2026

/retest

@rhamilto
Copy link
Member Author

rhamilto commented Mar 9, 2026

/retest

@rhamilto rhamilto force-pushed the CONSOLE-4447-knative branch from 1e2584c to 3dc2af9 Compare March 9, 2026 17:50
@openshift-ci openshift-ci bot added the component/dev-console Related to dev-console label Mar 9, 2026
@rhamilto rhamilto force-pushed the CONSOLE-4447-knative branch from 3dc2af9 to 5f0021c Compare March 9, 2026 17:52
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 9, 2026

📝 Walkthrough

Walkthrough

This pull request modernizes modal implementations across the knative-plugin package by migrating from deprecated internal modal components to PatternFly Modal composition patterns. Multiple modal components (pub-sub, sink, traffic-splitting, test-function, delete-revision) transition from ModalTitle/ModalSubmitFooter-based structures to ModalHeader/ModalBody/ModalFooter/ModalFooterWithAlerts compositions. Modal wrapper components are updated to use PatternFly's Modal with explicit isOpen and variant props instead of ModalWrapper. Associated test mocks are updated to reflect the new PatternFly component usage. Supporting changes include test selector updates, property access path corrections for service metadata, and stylesheet adjustments for the test-function modal layout.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: migrating knative-plugin modals to PatternFly 6, which is the primary focus of the entire changeset across 17 modified files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Comment @coderabbitai help to get the list of available commands and usage tips.

@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Mar 9, 2026

@rhamilto: This pull request references CONSOLE-4447 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Summary

Migrate knative-plugin modals from deprecated factory components to PatternFly 6 Modal components.

This PR migrates 7 modals:

  • SinkSourceModal
  • PubSubModal
  • SinkPubsubModal
  • DeleteRevisionModal
  • SinkUriModal
  • TestFunctionModal
  • TrafficSplittingModal

Note: This PR includes changes from #16015, so it should merge first.

Changes

  • Replace ModalWrapper with PatternFly 6 Modal in controller components
  • Replace ModalTitle with ModalHeader (with labelId and data-test-id="modal-title")
  • Move Form inside ModalBody for consistency
  • Replace ModalSubmitFooter with ModalFooter or ModalFooterWithAlerts
  • Add form attribute to submit buttons to connect to form id
  • Add data-test-id="modal-cancel-action" to cancel buttons for integration tests
  • Update unit tests to mock PatternFly 6 components
  • Fix bug in TestFunction: service.data.metadataservice.metadata

Pattern

All modals now follow consistent pattern:

  • Modal wrapper in Controller component with variant="small"
  • ModalHeader with accessibility labelId and data-test-id="modal-title"
  • Form inside ModalBody with unique id and className="pf-v6-u-mr-md"
  • Submit button with type="submit" and form attribute
  • Cancel button with variant="link" and data-test-id="modal-cancel-action"

Test plan

  • Unit tests passing for all modified modal components
  • Integration tests passing with updated test IDs
  • Build passing
  • Visual/functional testing of each modal

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • Refactor

  • Updated modal dialogs to use PatternFly components for improved consistency and visual organization.

  • Reorganized modal layouts with clearer separation of headers, body content, and footer actions.

  • Improved form submission handling with explicit form-to-button associations.

  • Tests

  • Updated test infrastructure to align with new modal component structure.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 10

🧹 Nitpick comments (1)
frontend/packages/knative-plugin/src/components/sink-source/__tests__/SinkSourceModal.spec.tsx (1)

7-16: Don't mock away the footer buttons in this migration test.

The risky part of this refactor is the footer wiring (form="sink-source-form" and the cancel action), but Button is mocked to null and the spec submits the form programmatically. This test can still pass even if the migrated footer buttons stop working.

🧪 Tighten the spec around the new footer contract
-import { render, fireEvent } from '@testing-library/react';
+import { render, fireEvent, screen } from '@testing-library/react';
@@
 jest.mock('@patternfly/react-core', () => ({
   ...jest.requireActual('@patternfly/react-core'),
   ModalHeader: jest.fn(() => null),
   ModalBody: jest.fn(({ children }) => <div>{children}</div>),
-  Button: jest.fn(() => null),
+  Button: jest.fn(({ children, isLoading, isDisabled, variant, ...props }) => (
+    <button {...props} disabled={Boolean(isLoading || isDisabled)}>
+      {children}
+    </button>
+  )),
   Form: jest.fn(({ children, ...props }) => <form {...props}>{children}</form>),
 }));
@@
-  it('should render form with id', () => {
-    const { container } = render(<SinkSourceModal {...formProps} />);
-    const form = container.querySelector('form');
-    expect(form).toBeInTheDocument();
-    expect(form).toHaveAttribute('id', 'sink-source-form');
+  it('wires the footer submit button to the form', () => {
+    const { container } = render(<SinkSourceModal {...formProps} />);
+    expect(container.querySelector('#sink-source-form')).toBeInTheDocument();
+    expect(screen.getByRole('button', { name: 'knative-plugin~Save' })).toHaveAttribute(
+      'form',
+      'sink-source-form',
+    );
   });

Also applies to: 61-75

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/packages/knative-plugin/src/components/sink-source/__tests__/SinkSourceModal.spec.tsx`
around lines 7 - 16, The test currently mocks away Button and the modal footer
(ModalFooterWithAlerts), which removes the real footer buttons and prevents
verifying the footer wiring (form="sink-source-form" and cancel action); update
the jest.mock for '@patternfly/react-core' to stop overriding Button (remove or
return the actual Button via jest.requireActual) and change the mock for
'@console/shared/src/components/modals/ModalFooterWithAlerts' to return the real
ModalFooterWithAlerts (use jest.requireActual) or at least render its children
including any Button elements instead of null so the footer buttons remain in
the DOM and the spec can assert the migrated footer contract (look for
ModalFooterWithAlerts, Button, and Form in SinkSourceModal.spec.tsx).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@frontend/packages/knative-plugin/src/components/revisions/DeleteRevisionModal.tsx`:
- Around line 36-41: The confirmation text in DeleteRevisionModal currently uses
three separate t() calls around strong elements which hard-codes English word
order; replace them with a single translation key (using either i18n's t with
interpolation or the Trans component) that accepts placeholders for revision,
service and namespace (pass deleteRevision.metadata.name, serviceName, and
deleteRevision.metadata.namespace) and preserve the <strong> styling by using
Trans's components or t(..., { interpolation }) so translators can reorder words
and punctuation correctly.

In
`@frontend/packages/knative-plugin/src/components/revisions/DeleteRevisionModalController.tsx`:
- Around line 87-94: The Modal's title id is inconsistent between the
early-return ModalHeader ("unable-delete-revision-modal-title") and the
normal-flow title ("delete-revision-modal-title"), preventing the outer Modal
from referencing a stable label; update both ModalHeader usages in
DeleteRevisionModalController.tsx to use a single normalized id (e.g.,
"delete-revision-modal-title") and add aria-labelledby="{that-id}" to the outer
Modal component (the Modal instance rendered in this controller) so the dialog
correctly references the title for accessibility.

In
`@frontend/packages/knative-plugin/src/components/sink-pubsub/__tests__/SinkPubsubModal.spec.tsx`:
- Around line 4-14: Tests currently mock Button to null so they never exercise
the footer->form submit link introduced by the refactor; update the mocks in
SinkPubsubModal.spec.tsx so the Button mock renders an element that
preserves/accepts the form prop (or stop mocking Button entirely) and ensure
ModalFooterWithAlerts mock renders a footer save button with
form="sink-pubsub-form" that can be clicked in the test; then add an assertion
that clicking the footer save button triggers the form submit path (e.g., assert
the form submit handler or the expected post-submit side effect from the Form
component) to cover the new contract between ModalFooterWithAlerts/Button and
the Form.

In
`@frontend/packages/knative-plugin/src/components/sink-source/SinkSourceController.tsx`:
- Around line 20-24: The Modal wrapper in SinkSourceModalProvider is missing an
accessible name; update the Modal element in the SinkSourceModalProvider
component to include aria-labelledby="sink-source-modal-title" so it references
the ModalHeader's labelId (used inside SinkSourceController/ModalHeader),
ensuring the Modal and ModalHeader are connected for accessibility.

In
`@frontend/packages/knative-plugin/src/components/sink-uri/__tests__/SinkUriModal.spec.tsx`:
- Around line 6-24: The current spec only verifies render, so add tests in
SinkUriModal.spec.tsx that exercise the footer-to-form contract: render the
SinkUriModal (or the specific component under test), locate the submit button
rendered via the mocked ModalFooterWithAlerts/Button, assert its form attribute
equals the Form's id (or that the form element has the expected id from the
component), and simulate a click (or fireEvent.submit on the form) to verify the
component's onSubmit/submit handler is invoked; also add a test that ensures a
disabled/missing submit button fails the expected submit behavior. Use the
existing mocked Form, ModalFooterWithAlerts, and Button symbols to find elements
and assert the form-id/form-attribute linkage and actual submit invocation.

In
`@frontend/packages/knative-plugin/src/components/sink-uri/SinkUriController.tsx`:
- Around line 23-25: The Modal wrapper in SinkUriController is missing the
aria-labelledby attribute that should reference the ModalHeader's ID
("sink-uri-modal-title"); update the Modal element in SinkUriController (the
<Modal> that renders <SinkUriController ... />) to include
aria-labelledby="sink-uri-modal-title" so the dialog's accessible name is tied
to the header ID used by SinkUriModal/ModalHeader.

In
`@frontend/packages/knative-plugin/src/components/test-function/TestFunctionController.tsx`:
- Around line 42-44: The Modal instance wrapping TestFunctionController is
missing an accessibility link to the modal header; add
aria-labelledby="test-function-modal-title" to the Modal props so screen readers
can associate the dialog with the TestFunctionController's ModalHeader (which
uses labelId="test-function-modal-title"); keep existing onClose/cancel props
and other props unchanged.

In
`@frontend/packages/knative-plugin/src/components/test-function/TestFunctionModal.tsx`:
- Around line 34-49: The Form onSubmit in TestFunctionModal currently calls
handleSubmit() without the event which can allow a full page reload; update the
Form's onSubmit handler to accept the event parameter, call
event.preventDefault(), and then invoke Formik's handleSubmit with that event
before calling setCurrentView(ModalPanel.Response) (referencing the Form id
"test-function-form", the handleSubmit function and
setCurrentView/ModalPanel.Response symbols) so the default browser submit is
stopped and Formik handles submission correctly.

In
`@frontend/packages/knative-plugin/src/components/traffic-splitting/__tests__/TrafficSplittingModal.spec.tsx`:
- Around line 10-20: The test mock for Button hides the real footer submit
wiring — stop returning null for Button in the jest.mock so the footer submit
button is rendered (or replace the Button mock with one that renders a native
<button> and forwards props like type and onClick); update the test to click the
ModalFooterWithAlerts/Button instance (instead of only calling
fireEvent.submit(form)) to verify the submit button in the footer is actually
wired to the traffic-splitting-form handler (references: mocked Button, Form,
ModalFooterWithAlerts and the traffic-splitting-form submit test that currently
uses fireEvent.submit(form)).

In
`@frontend/packages/knative-plugin/src/components/traffic-splitting/TrafficSplittingController.tsx`:
- Around line 59-65: The Modal wrapper lacks an aria-labelledby that points to
the ModalHeader id; add aria-labelledby="traffic-splitting-modal-title" to the
Modal element that renders TrafficSplittingController so the dialog is properly
labeled (i.e., update the Modal JSX where Modal is opened to include
aria-labelledby="traffic-splitting-modal-title", referencing the existing
labelId on the ModalHeader).

---

Nitpick comments:
In
`@frontend/packages/knative-plugin/src/components/sink-source/__tests__/SinkSourceModal.spec.tsx`:
- Around line 7-16: The test currently mocks away Button and the modal footer
(ModalFooterWithAlerts), which removes the real footer buttons and prevents
verifying the footer wiring (form="sink-source-form" and cancel action); update
the jest.mock for '@patternfly/react-core' to stop overriding Button (remove or
return the actual Button via jest.requireActual) and change the mock for
'@console/shared/src/components/modals/ModalFooterWithAlerts' to return the real
ModalFooterWithAlerts (use jest.requireActual) or at least render its children
including any Button elements instead of null so the footer buttons remain in
the DOM and the spec can assert the migrated footer contract (look for
ModalFooterWithAlerts, Button, and Form in SinkSourceModal.spec.tsx).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bab54361-16fd-4f88-8d2e-9a67062feb30

📥 Commits

Reviewing files that changed from the base of the PR and between 874c37e and 5f0021c.

📒 Files selected for processing (22)
  • frontend/packages/dev-console/integration-tests/support/pages/modal.ts
  • frontend/packages/knative-plugin/src/components/pub-sub/PubSubController.tsx
  • frontend/packages/knative-plugin/src/components/pub-sub/PubSubModal.tsx
  • frontend/packages/knative-plugin/src/components/revisions/DeleteRevisionModal.tsx
  • frontend/packages/knative-plugin/src/components/revisions/DeleteRevisionModalController.tsx
  • frontend/packages/knative-plugin/src/components/sink-pubsub/SinkPubsubController.tsx
  • frontend/packages/knative-plugin/src/components/sink-pubsub/SinkPubsubModal.tsx
  • frontend/packages/knative-plugin/src/components/sink-pubsub/__tests__/SinkPubsubModal.spec.tsx
  • frontend/packages/knative-plugin/src/components/sink-source/SinkSourceController.tsx
  • frontend/packages/knative-plugin/src/components/sink-source/SinkSourceModal.tsx
  • frontend/packages/knative-plugin/src/components/sink-source/__tests__/SinkSourceModal.spec.tsx
  • frontend/packages/knative-plugin/src/components/sink-uri/SinkUriController.tsx
  • frontend/packages/knative-plugin/src/components/sink-uri/SinkUriModal.tsx
  • frontend/packages/knative-plugin/src/components/sink-uri/__tests__/SinkUriModal.spec.tsx
  • frontend/packages/knative-plugin/src/components/test-function/RequestPane.tsx
  • frontend/packages/knative-plugin/src/components/test-function/TestFunction.tsx
  • frontend/packages/knative-plugin/src/components/test-function/TestFunctionController.tsx
  • frontend/packages/knative-plugin/src/components/test-function/TestFunctionModal.scss
  • frontend/packages/knative-plugin/src/components/test-function/TestFunctionModal.tsx
  • frontend/packages/knative-plugin/src/components/traffic-splitting/TrafficSplittingController.tsx
  • frontend/packages/knative-plugin/src/components/traffic-splitting/TrafficSplittingModal.tsx
  • frontend/packages/knative-plugin/src/components/traffic-splitting/__tests__/TrafficSplittingModal.spec.tsx

Comment on lines +36 to +41
<p>
{t('knative-plugin~Are you sure you want to delete ')}
<strong className="co-break-word">{deleteRevision.metadata.name}</strong>{' '}
{t('knative-plugin~from ')} <strong className="co-break-word">{serviceName}</strong>{' '}
{t('knative-plugin~in namespace ')} <strong>{deleteRevision.metadata.namespace}</strong>
?
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Keep the confirmation sentence in one translation key.

The three separate t() calls around the <strong> markers hard-code English word order and punctuation. That won't localize cleanly once translators need to reorder revision, service, and namespace. Please switch this paragraph to a single Trans or interpolated message.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/packages/knative-plugin/src/components/revisions/DeleteRevisionModal.tsx`
around lines 36 - 41, The confirmation text in DeleteRevisionModal currently
uses three separate t() calls around strong elements which hard-codes English
word order; replace them with a single translation key (using either i18n's t
with interpolation or the Trans component) that accepts placeholders for
revision, service and namespace (pass deleteRevision.metadata.name, serviceName,
and deleteRevision.metadata.namespace) and preserve the <strong> styling by
using Trans's components or t(..., { interpolation }) so translators can reorder
words and punctuation correctly.

Comment on lines +87 to +94
<ModalHeader
title={t('knative-plugin~Unable to delete {{revlabel}}', {
revlabel: RevisionModel.label,
})}
titleIconVariant="danger"
labelId="unable-delete-revision-modal-title"
data-test-id="modal-title"
/>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cd frontend/packages/knative-plugin && find . -name "DeleteRevisionModalController.tsx" -type f

Repository: openshift/console

Length of output: 121


🏁 Script executed:

cat -n frontend/packages/knative-plugin/src/components/revisions/DeleteRevisionModalController.tsx | head -220

Repository: openshift/console

Length of output: 8718


🌐 Web query:

PatternFly Modal aria-labelledby accessibility requirement

💡 Result:

In PatternFly, a Modal must have an accessible name. The recommended/default way is to set aria-labelledby on the modal container to the id of the element that visually titles the modal (typically the modal title element, e.g. .pf-v6-c-modal-box__title). This is an accessibility requirement because it gives the dialog its programmatic label. [1], [2]

For PatternFly React specifically:

  • Use aria-labelledby when the modal’s label comes from an element in the modal header—PatternFly notes it’s required when you use the header prop rather than the title prop. [1]
  • If there is no visible title text to reference, provide an accessible name with aria-label instead (PatternFly notes this is required in that case). [1]

Sources
[1] PatternFly Modal – Accessibility (React) (patternfly.org)
[2] PatternFly Modal – HTML docs (patternfly.org)

Citations:


🏁 Script executed:

cat -n frontend/packages/knative-plugin/src/components/revisions/DeleteRevisionModal.tsx | head -150

Repository: openshift/console

Length of output: 3479


Add aria-labelledby to the outer Modal and normalize the title id across both branches.

PatternFly's Modal component requires an accessible name via aria-labelledby on the outer dialog container. Your code paths render two different title ids—unable-delete-revision-modal-title (early return) and delete-revision-modal-title (normal flow)—making it impossible for the Modal at line 204 to reference a stable id. Normalize to a single title id and add the aria-labelledby attribute to the Modal container.

♿ Fix outline
-          labelId="unable-delete-revision-modal-title"
+          labelId="delete-revision-modal-title"
@@
-    <Modal isOpen onClose={props.closeOverlay} variant="small">
+    <Modal
+      isOpen
+      onClose={props.closeOverlay}
+      variant="small"
+      aria-labelledby="delete-revision-modal-title"
+    >
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/packages/knative-plugin/src/components/revisions/DeleteRevisionModalController.tsx`
around lines 87 - 94, The Modal's title id is inconsistent between the
early-return ModalHeader ("unable-delete-revision-modal-title") and the
normal-flow title ("delete-revision-modal-title"), preventing the outer Modal
from referencing a stable label; update both ModalHeader usages in
DeleteRevisionModalController.tsx to use a single normalized id (e.g.,
"delete-revision-modal-title") and add aria-labelledby="{that-id}" to the outer
Modal component (the Modal instance rendered in this controller) so the dialog
correctly references the title for accessibility.

Comment on lines +4 to 14
jest.mock('@patternfly/react-core', () => ({
...jest.requireActual('@patternfly/react-core'),
ModalHeader: jest.fn(() => null),
ModalBody: jest.fn(({ children }) => <div>{children}</div>),
Button: jest.fn(() => null),
Form: jest.fn(({ children, ...props }) => <form {...props}>{children}</form>),
}));

jest.mock('@console/shared/src/components/modals/ModalFooterWithAlerts', () => ({
ModalFooterWithAlerts: jest.fn(({ children }) => <div>{children}</div>),
}));
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

These tests no longer cover the migrated submit path.

Because Button is mocked to null and the assertions stop at “renders”, this spec will not catch a broken form="sink-pubsub-form" link between the footer save button and the form. That is the key behavior introduced by this refactor.

Minimal way to exercise the new contract
 jest.mock('@patternfly/react-core', () => ({
   ...jest.requireActual('@patternfly/react-core'),
   ModalHeader: jest.fn(() => null),
   ModalBody: jest.fn(({ children }) => <div>{children}</div>),
-  Button: jest.fn(() => null),
+  Button: jest.fn(({ children, ...props }) => <button {...props}>{children}</button>),
   Form: jest.fn(({ children, ...props }) => <form {...props}>{children}</form>),
 }));
@@
-  it('should render with all required props', () => {
-    const { container } = render(<SinkPubsubModal {...formProps} />);
-    expect(container).toBeInTheDocument();
+  it('wires the footer save button to the form', () => {
+    const { getByRole } = render(<SinkPubsubModal {...formProps} />);
+    expect(getByRole('button', { name: 'knative-plugin~Save' })).toHaveAttribute(
+      'form',
+      'sink-pubsub-form',
+    );
   });

Also applies to: 59-66

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/packages/knative-plugin/src/components/sink-pubsub/__tests__/SinkPubsubModal.spec.tsx`
around lines 4 - 14, Tests currently mock Button to null so they never exercise
the footer->form submit link introduced by the refactor; update the mocks in
SinkPubsubModal.spec.tsx so the Button mock renders an element that
preserves/accepts the form prop (or stop mocking Button entirely) and ensure
ModalFooterWithAlerts mock renders a footer save button with
form="sink-pubsub-form" that can be clicked in the test; then add an assertion
that clicking the footer save button triggers the form submit path (e.g., assert
the form submit handler or the expected post-submit side effect from the Form
component) to cover the new contract between ModalFooterWithAlerts/Button and
the Form.

Comment on lines +20 to +24
const SinkSourceModalProvider: OverlayComponent<Props> = (props) => (
<Modal isOpen onClose={props.closeOverlay} variant="small">
<SinkSourceController cancel={props.closeOverlay} close={props.closeOverlay} {...props} />
</Modal>
);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find frontend/packages/knative-plugin/src/components/sink-source -type f -name "*.tsx" -o -name "*.ts" | head -20

Repository: openshift/console

Length of output: 485


🏁 Script executed:

cat -n frontend/packages/knative-plugin/src/components/sink-source/SinkSourceController.tsx | head -50

Repository: openshift/console

Length of output: 1470


🏁 Script executed:

cd frontend/packages/knative-plugin/src/components/sink-source && ls -la

Repository: openshift/console

Length of output: 444


🏁 Script executed:

cat -n frontend/packages/knative-plugin/src/components/sink-source/SinkSourceModal.tsx

Repository: openshift/console

Length of output: 2907


🏁 Script executed:

cat -n frontend/packages/knative-plugin/src/components/sink-source/SinkSource.tsx

Repository: openshift/console

Length of output: 3716


Wire aria-labelledby on the Modal to connect it to the ModalHeader.

The outer Modal component (lines 20-24) lacks an accessible name. Since SinkSourceModal uses a ModalHeader with labelId="sink-source-modal-title", the Modal wrapper must reference this ID via aria-labelledby="sink-source-modal-title" to meet PatternFly's accessibility requirements.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/packages/knative-plugin/src/components/sink-source/SinkSourceController.tsx`
around lines 20 - 24, The Modal wrapper in SinkSourceModalProvider is missing an
accessible name; update the Modal element in the SinkSourceModalProvider
component to include aria-labelledby="sink-source-modal-title" so it references
the ModalHeader's labelId (used inside SinkSourceController/ModalHeader),
ensuring the Modal and ModalHeader are connected for accessibility.

Comment on lines +6 to 24
jest.mock('@patternfly/react-core', () => ({
...jest.requireActual('@patternfly/react-core'),
ModalHeader: jest.fn(() => null),
ModalBody: jest.fn(({ children }) => <div>{children}</div>),
Button: jest.fn(() => null),
Form: jest.fn(({ children, ...props }) => <form {...props}>{children}</form>),
FormGroup: jest.fn(({ children }) => <div>{children}</div>),
FormHelperText: jest.fn(() => null),
HelperText: jest.fn(() => null),
HelperTextItem: jest.fn(() => null),
TextInputTypes: {
text: 'text',
url: 'url',
},
}));

jest.mock('@console/shared/src/components/modals/ModalFooterWithAlerts', () => ({
ModalFooterWithAlerts: jest.fn(({ children }) => <div>{children}</div>),
}));
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

The updated spec is still render-only, so the modal migration is effectively untested.

After moving actions into a PF footer, the risky part is the footer-to-form contract. These assertions only check that rendering does not throw, so a broken submit button or missing form id would still pass.

Also applies to: 58-79

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/packages/knative-plugin/src/components/sink-uri/__tests__/SinkUriModal.spec.tsx`
around lines 6 - 24, The current spec only verifies render, so add tests in
SinkUriModal.spec.tsx that exercise the footer-to-form contract: render the
SinkUriModal (or the specific component under test), locate the submit button
rendered via the mocked ModalFooterWithAlerts/Button, assert its form attribute
equals the Form's id (or that the form element has the expected id from the
component), and simulate a click (or fireEvent.submit on the form) to verify the
component's onSubmit/submit handler is invoked; also add a test that ensures a
disabled/missing submit button fails the expected submit behavior. Use the
existing mocked Form, ModalFooterWithAlerts, and Button symbols to find elements
and assert the form-id/form-attribute linkage and actual submit invocation.

Comment on lines +23 to +25
<Modal isOpen onClose={props.closeOverlay} variant="small">
<SinkUriController cancel={props.closeOverlay} close={props.closeOverlay} {...props} />
</ModalWrapper>
</Modal>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Find the SinkUriController.tsx file
find . -type f -name "SinkUriController.tsx" 2>/dev/null | head -5

Repository: openshift/console

Length of output: 141


🏁 Script executed:

# Check the SinkUriModal.tsx file too
find . -type f -name "SinkUriModal.tsx" 2>/dev/null | head -5

Repository: openshift/console

Length of output: 136


🏁 Script executed:

# Find the knative-plugin directory structure
find . -type d -name "knative-plugin" 2>/dev/null | head -3

Repository: openshift/console

Length of output: 95


🏁 Script executed:

cat -n ./frontend/packages/knative-plugin/src/components/sink-uri/SinkUriController.tsx | head -30

Repository: openshift/console

Length of output: 1459


🏁 Script executed:

cat -n ./frontend/packages/knative-plugin/src/components/sink-uri/SinkUriModal.tsx | head -50

Repository: openshift/console

Length of output: 1858


🏁 Script executed:

# Search for other Modal usage in the codebase to see if aria-labelledby pattern is used elsewhere
rg -A 3 -B 1 '<Modal' ./frontend --type tsx --type ts | grep -A 3 'aria-labelledby\|labelId' | head -40

Repository: openshift/console

Length of output: 88


🏁 Script executed:

# Check PatternFly version
cat ./frontend/packages/knative-plugin/package.json 2>/dev/null | grep -A 5 '@patternfly'

Repository: openshift/console

Length of output: 43


🏁 Script executed:

# Search for aria-labelledby usage in Modal context
rg 'aria-labelledby.*modal\|Modal.*aria-labelledby' ./frontend -i | head -20

Repository: openshift/console

Length of output: 43


🏁 Script executed:

# Find package.json for knative plugin
find ./frontend/packages/knative-plugin -name "package.json" -type f

Repository: openshift/console

Length of output: 174


🏁 Script executed:

# Look for other Modal patterns with labelId
rg '<Modal' ./frontend -A 5 | grep -B 5 -A 5 'labelId\|aria-label' | head -50

Repository: openshift/console

Length of output: 4307


🌐 Web query:

PatternFly React Modal accessibility aria-labelledby best practices

💡 Result:

  • Give the modal an accessible name (required):

    • If your modal has a visible title (e.g., ModalHeader), set aria-labelledby on Modal to the ID of the title element (PatternFly notes this is required when .pf-v6-c-modal-box__title/a title is present). [1][2]
    • If there is no visible title, use aria-label on Modal instead. [1][2]
  • Wire PatternFly React IDs correctly (recommended):

    • Set ModalHeader labelId="my-modal-title" and pass aria-labelledby="my-modal-title" to Modal (PatternFly React docs explicitly say aria-labelledby should include the ModalHeader labelId). [2]
  • Add a description when it helps (recommended):

    • If there’s static content that explains the modal’s purpose, set aria-describedby on Modal to the ID of that descriptive content (PatternFly React: should match ModalHeader descriptorId; PatternFly accessibility guidance: typically the primary modal content). [1][2]
  • Don’t forget other required a11y bits PatternFly calls out:

    • Modal container should have role="dialog" and aria-modal="true". [1][3]
    • Close button needs an accessible name (PatternFly uses aria-label="Close"). [1][3]

Example (PatternFly React):

<Modal
  isOpen
  aria-labelledby="user-edit-title"
  aria-describedby="user-edit-desc"
  onClose={onClose}
>
  <ModalHeader labelId="user-edit-title" descriptorId="user-edit-desc" title="Edit user" />
  <ModalBody>...</ModalBody>
</Modal>

Sources: PatternFly Modal accessibility guidance [1][3] and PatternFly React Modal prop docs [2].


Wire aria-labelledby on the Modal to connect the title.

The <Modal> component is missing aria-labelledby, even though SinkUriModal provides labelId="sink-uri-modal-title" on the ModalHeader. PatternFly requires the modal to declare its accessible name by referencing the header's ID—without it, screen readers announce the dialog without a title. This is a required accessibility pattern when a visible title is present.

♿ Suggested fix
-    <Modal isOpen onClose={props.closeOverlay} variant="small">
+    <Modal
+      isOpen
+      onClose={props.closeOverlay}
+      variant="small"
+      aria-labelledby="sink-uri-modal-title"
+    >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Modal isOpen onClose={props.closeOverlay} variant="small">
<SinkUriController cancel={props.closeOverlay} close={props.closeOverlay} {...props} />
</ModalWrapper>
</Modal>
<Modal
isOpen
onClose={props.closeOverlay}
variant="small"
aria-labelledby="sink-uri-modal-title"
>
<SinkUriController cancel={props.closeOverlay} close={props.closeOverlay} {...props} />
</Modal>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/packages/knative-plugin/src/components/sink-uri/SinkUriController.tsx`
around lines 23 - 25, The Modal wrapper in SinkUriController is missing the
aria-labelledby attribute that should reference the ModalHeader's ID
("sink-uri-modal-title"); update the Modal element in SinkUriController (the
<Modal> that renders <SinkUriController ... />) to include
aria-labelledby="sink-uri-modal-title" so the dialog's accessible name is tied
to the header ID used by SinkUriModal/ModalHeader.

Comment on lines +42 to +44
<Modal isOpen onClose={props.closeOverlay} variant="small">
<TestFunctionController cancel={props.closeOverlay} close={props.closeOverlay} {...props} />
</ModalWrapper>
</Modal>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Missing aria-labelledby for modal accessibility.

The TestFunctionModal child component sets labelId="test-function-modal-title" on its ModalHeader, but the parent Modal here doesn't reference it. Screen readers won't associate the modal with its title without this connection.

♿ Proposed fix for accessibility
-    <Modal isOpen onClose={props.closeOverlay} variant="small">
+    <Modal isOpen onClose={props.closeOverlay} variant="small" aria-labelledby="test-function-modal-title">
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Modal isOpen onClose={props.closeOverlay} variant="small">
<TestFunctionController cancel={props.closeOverlay} close={props.closeOverlay} {...props} />
</ModalWrapper>
</Modal>
<Modal isOpen onClose={props.closeOverlay} variant="small" aria-labelledby="test-function-modal-title">
<TestFunctionController cancel={props.closeOverlay} close={props.closeOverlay} {...props} />
</Modal>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/packages/knative-plugin/src/components/test-function/TestFunctionController.tsx`
around lines 42 - 44, The Modal instance wrapping TestFunctionController is
missing an accessibility link to the modal header; add
aria-labelledby="test-function-modal-title" to the Modal props so screen readers
can associate the dialog with the TestFunctionController's ModalHeader (which
uses labelId="test-function-modal-title"); keep existing onClose/cancel props
and other props unchanged.

Comment on lines +34 to +49
<Form
id="test-function-form"
onSubmit={() => {
handleSubmit();
setCurrentView(ModalPanel.Response);
}}
className="pf-v6-u-mr-md"
>
<Button type="submit" variant="primary" data-test="test-action" isDisabled={isSubmitting}>
{t('knative-plugin~Test')}
</Button>
&nbsp; &nbsp;
<Button type="button" variant="link" data-test="cancel-action" onClick={cancel}>
{t('knative-plugin~Cancel')}
</Button>
</form>
) : (
<>
<Button
type="button"
variant="primary"
data-test="back-action"
onClick={() => {
clearResponseValues(props);
setCurrentView(ModalPanel.Request);
}}
>
{t('knative-plugin~Back')}
</Button>
&nbsp;
<Button
type="button"
variant="link"
data-test="close-action"
onClick={() => {
clearResponseValues(props);
close();
}}
>
{t('knative-plugin~Close')}
</Button>
</>
)}
</>
);

return (
<Modal
variant={ModalVariant.small}
isOpen
header={header}
className="kn-test-sf-modal"
onClose={close}
position="top"
footer={footer}
data-test="test-serverless-function"
>
<div className="kn-test-sf-modal__body">
<>
{currentView === ModalPanel.Request ? (
<RequestPane {...props} />
) : (
<ResponsePane {...props} />
)}
</>
</Form>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Form onSubmit handler may cause unexpected page navigation.

The onSubmit wraps Formik's handleSubmit() but doesn't pass the event or call preventDefault(). Formik's handleSubmit only prevents default when it receives the event directly. This could cause a full page reload when submitting.

🐛 Proposed fix to prevent default form submission
         <Form
           id="test-function-form"
-          onSubmit={() => {
-            handleSubmit();
+          onSubmit={(e) => {
+            e.preventDefault();
+            handleSubmit();
             setCurrentView(ModalPanel.Response);
           }}
           className="pf-v6-u-mr-md"
         >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Form
id="test-function-form"
onSubmit={() => {
handleSubmit();
setCurrentView(ModalPanel.Response);
}}
className="pf-v6-u-mr-md"
>
<Button type="submit" variant="primary" data-test="test-action" isDisabled={isSubmitting}>
{t('knative-plugin~Test')}
</Button>
&nbsp; &nbsp;
<Button type="button" variant="link" data-test="cancel-action" onClick={cancel}>
{t('knative-plugin~Cancel')}
</Button>
</form>
) : (
<>
<Button
type="button"
variant="primary"
data-test="back-action"
onClick={() => {
clearResponseValues(props);
setCurrentView(ModalPanel.Request);
}}
>
{t('knative-plugin~Back')}
</Button>
&nbsp;
<Button
type="button"
variant="link"
data-test="close-action"
onClick={() => {
clearResponseValues(props);
close();
}}
>
{t('knative-plugin~Close')}
</Button>
</>
)}
</>
);
return (
<Modal
variant={ModalVariant.small}
isOpen
header={header}
className="kn-test-sf-modal"
onClose={close}
position="top"
footer={footer}
data-test="test-serverless-function"
>
<div className="kn-test-sf-modal__body">
<>
{currentView === ModalPanel.Request ? (
<RequestPane {...props} />
) : (
<ResponsePane {...props} />
)}
</>
</Form>
<Form
id="test-function-form"
onSubmit={(e) => {
e.preventDefault();
handleSubmit();
setCurrentView(ModalPanel.Response);
}}
className="pf-v6-u-mr-md"
>
<>
{currentView === ModalPanel.Request ? (
<RequestPane {...props} />
) : (
<ResponsePane {...props} />
)}
</>
</Form>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/packages/knative-plugin/src/components/test-function/TestFunctionModal.tsx`
around lines 34 - 49, The Form onSubmit in TestFunctionModal currently calls
handleSubmit() without the event which can allow a full page reload; update the
Form's onSubmit handler to accept the event parameter, call
event.preventDefault(), and then invoke Formik's handleSubmit with that event
before calling setCurrentView(ModalPanel.Response) (referencing the Form id
"test-function-form", the handleSubmit function and
setCurrentView/ModalPanel.Response symbols) so the default browser submit is
stopped and Formik handles submission correctly.

Comment on lines +10 to 20
jest.mock('@patternfly/react-core', () => ({
...jest.requireActual('@patternfly/react-core'),
ModalHeader: jest.fn(() => null),
ModalBody: jest.fn(({ children }) => <div>{children}</div>),
Button: jest.fn(() => null),
Form: jest.fn(({ children, ...props }) => <form {...props}>{children}</form>),
}));

jest.mock('@console/shared/src/components/modals/ModalFooterWithAlerts', () => ({
ModalFooterWithAlerts: jest.fn(({ children }) => <div>{children}</div>),
}));
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

The submit test bypasses the behavior this refactor changed.

fireEvent.submit(form) proves the form handler works, but it does not prove the footer submit button is actually wired back to traffic-splitting-form. With Button mocked to null, this regression would slip through.

Also applies to: 54-61

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/packages/knative-plugin/src/components/traffic-splitting/__tests__/TrafficSplittingModal.spec.tsx`
around lines 10 - 20, The test mock for Button hides the real footer submit
wiring — stop returning null for Button in the jest.mock so the footer submit
button is rendered (or replace the Button mock with one that renders a native
<button> and forwards props like type and onClick); update the test to click the
ModalFooterWithAlerts/Button instance (instead of only calling
fireEvent.submit(form)) to verify the submit button in the footer is actually
wired to the traffic-splitting-form handler (references: mocked Button, Form,
ModalFooterWithAlerts and the traffic-splitting-form submit test that currently
uses fireEvent.submit(form)).

Comment on lines +59 to +65
<Modal isOpen onClose={props.closeOverlay} variant="small">
<TrafficSplittingController
cancel={props.closeOverlay}
close={props.closeOverlay}
{...props}
/>
</ModalWrapper>
</Modal>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

fd -t f "TrafficSplitting" --extension tsx

Repository: openshift/console

Length of output: 644


🏁 Script executed:

cat frontend/packages/knative-plugin/src/components/traffic-splitting/TrafficSplittingController.tsx | head -80

Repository: openshift/console

Length of output: 2501


🏁 Script executed:

cat frontend/packages/knative-plugin/src/components/traffic-splitting/TrafficSplittingModal.tsx

Repository: openshift/console

Length of output: 1977


🏁 Script executed:

rg -t tsx "Modal.*aria-labelledby" --max-count=10 -B 2 -A 2

Repository: openshift/console

Length of output: 88


🏁 Script executed:

rg -t tsx "ModalHeader" --max-count=15 -B 3 | head -100

Repository: openshift/console

Length of output: 88


🏁 Script executed:

rg "aria-labelledby" --type-list | grep -i ts

Repository: openshift/console

Length of output: 450


🏁 Script executed:

rg "aria-labelledby" . --max-count=15 -B 2 -A 2

Repository: openshift/console

Length of output: 14681


🏁 Script executed:

rg "Modal.*isOpen" . -B 1 -A 5 --max-count=20

Repository: openshift/console

Length of output: 36404


Add aria-labelledby to the Modal wrapper.

The outer Modal component is missing the aria-labelledby attribute. TrafficSplittingModal declares labelId="traffic-splitting-modal-title" on ModalHeader, but the wrapper never references it. Per PatternFly's accessibility model, the dialog itself must be labeled, not just the header.

Suggested fix
-    <Modal isOpen onClose={props.closeOverlay} variant="small">
+    <Modal
+      isOpen
+      onClose={props.closeOverlay}
+      variant="small"
+      aria-labelledby="traffic-splitting-modal-title"
+    >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Modal isOpen onClose={props.closeOverlay} variant="small">
<TrafficSplittingController
cancel={props.closeOverlay}
close={props.closeOverlay}
{...props}
/>
</ModalWrapper>
</Modal>
<Modal
isOpen
onClose={props.closeOverlay}
variant="small"
aria-labelledby="traffic-splitting-modal-title"
>
<TrafficSplittingController
cancel={props.closeOverlay}
close={props.closeOverlay}
{...props}
/>
</Modal>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/packages/knative-plugin/src/components/traffic-splitting/TrafficSplittingController.tsx`
around lines 59 - 65, The Modal wrapper lacks an aria-labelledby that points to
the ModalHeader id; add aria-labelledby="traffic-splitting-modal-title" to the
Modal element that renders TrafficSplittingController so the dialog is properly
labeled (i.e., update the Modal JSX where Modal is opened to include
aria-labelledby="traffic-splitting-modal-title", referencing the existing
labelId on the ModalHeader).

@rhamilto rhamilto force-pushed the CONSOLE-4447-knative branch from 5f0021c to 360866c Compare March 9, 2026 18:24
Migrate 7 modals from deprecated @console/internal/components/factory ModalWrapper
to modern @patternfly/react-core Modal components:
- SinkSourceModal
- PubSubModal
- SinkPubsubModal
- DeleteRevisionModal
- SinkUriModal
- TestFunctionModal
- TrafficSplittingModal

Changes:
- Replace ModalWrapper with PatternFly 6 Modal in controller components
- Replace ModalTitle with ModalHeader (with labelId and data-test-id="modal-title")
- Move Form inside ModalBody for consistency
- Replace ModalSubmitFooter with ModalFooter or ModalFooterWithAlerts
- Add form attribute to submit buttons to connect to form id
- Add data-test-id="modal-cancel-action" to cancel buttons for integration tests
- Update unit tests to mock PatternFly 6 components
- Fix TestFunction bug: service.data.metadata -> service.metadata

All modals now follow consistent pattern:
- Modal wrapper in Controller component
- ModalHeader with accessibility labelId and test ID
- Form inside ModalBody with unique id and className="pf-v6-u-mr-md"
- Submit button with type="submit" and form attribute
- Cancel button with variant="link" and test ID

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@rhamilto rhamilto force-pushed the CONSOLE-4447-knative branch from 360866c to b219911 Compare March 9, 2026 20:40
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 10, 2026

@rhamilto: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-gcp-console b219911 link true /test e2e-gcp-console

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. component/core Related to console core functionality component/dev-console Related to dev-console component/knative Related to knative-plugin component/metal3 Related to metal3-plugin component/olm Related to OLM component/shared Related to console-shared component/topology Related to topology docs-approved Signifies that Docs has signed off on this PR jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. px-approved Signifies that Product Support has signed off on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants