Repository navigation
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
Referenced required request bodies can bypass validation, and several new files violate repository conventions.
6 open findings
Resolve referenced request bodies before checking required · New Use lowercase hexadecimal colors in SCSS · New Use lowercase hexadecimal color formatting · New Use the required TypeScript Cypress test naming convention · New Use TSX for the new JSX test · New Use the required TypeScript unit test naming convention · New
What changed in this PR
Adds OAS 3.2 additionalOperations support across rendering, resolution, callbacks, webhooks, execution, and styling.
Changes:
- Discovers custom methods while rejecting fixed-field duplicates.
- Adds custom operation rendering, styling, resolution, and nested Path Item support.
- Adds documentation and comprehensive unit/E2E coverage.
| File | Description |
|---|---|
docs/usage/configuration.md |
Documents custom submit methods. |
src/core/components/layouts/base.jsx |
Renders OAS 3.2 webhooks. |
src/core/components/operation-summary-method.jsx |
Preserves custom method casing. |
src/core/components/operation-summary.jsx |
Removes method-specific summary classes. |
src/core/components/operation.jsx |
Applies neutral custom styling. |
src/core/components/overview.jsx |
Preserves custom labels in links. |
src/core/plugins/oas3/selectors.js |
Resolves custom-operation request bodies. |
src/core/plugins/oas32/index.js |
Registers new selector wrappers. |
src/core/plugins/oas32/spec-extensions/wrap-selectors.js |
Handles custom methods, callbacks, and webhooks. |
src/core/plugins/spec/reducers.js |
Validates custom-operation parameters. |
src/core/plugins/spec/selectors.js |
Discovers and resolves additional operations. |
src/style/_dark-mode.scss |
Adds dark-mode custom styling. |
src/style/_layout.scss |
Adds custom operation styling. |
src/style/_variables.scss |
Defines the custom method color. |
test/e2e-cypress/e2e/features/oas32/oas32-additional-operations.cy.js |
Adds end-to-end coverage. |
test/e2e-cypress/static/documents/features/oas32-additional-operations.yaml |
Provides the E2E fixture. |
test/unit/components/additional-operations.jsx |
Tests labels and styling. |
test/unit/core/plugins/oas32/additional-path-items.test.js |
Tests nested Path Items. |
test/unit/core/plugins/oas32/query-operation-rendering.test.js |
Tests custom method discovery. |
test/unit/core/plugins/oas32/spec-extensions/wrap-selectors.test.js |
Updates wrapper setup. |
test/unit/core/plugins/spec/assets/petstore.json |
Reformats the existing fixture. |
test/unit/core/plugins/spec/selectors.js |
Tests discovery, paths, and request bodies. |
🧠 Review effort: Balanced
Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.
| @@ -0,0 +1,418 @@ | |||
| /** | |||
| const DEFAULT_TAG = "default" | ||
|
|
||
| const OPERATION_METHODS = [ | ||
| export const OPERATION_METHODS = [ |
There was a problem hiding this comment.
Anything that we export from this file will be registered as a selector because the plugin imports everything through import * as selectors from "./selectors” and adds to the system with selectors: { ...selectors }. Should we move OPERATION_METHODS and isFixedOperationMethod to some util file instead? Could be in src/core/utils/operation-methods.ts or something similar instead, as it's imported by other plugins as well.
| * Entries that duplicate a fixed field (in any case) are invalid per OAS 3.2 | ||
| * and must be ignored. | ||
| */ | ||
| const isFixedFieldMethod = (method) => |
There was a problem hiding this comment.
Is this different from isFixedOperationMethod? Could we reuse that instead?
| * | ||
| * Reference: https://spec.openapis.org/oas/v3.2.0.html#path-item-object | ||
| */ | ||
| export const validOperationMethods = createOnlyOAS32SelectorWrapper( |
There was a problem hiding this comment.
I wonder how often this selector is called - would it make sense to memoize it with createSelector, if it's possible and will still work as expected?
Similar with selectWebhooksOperations - I see that it was memoized for OAS 3.1.
| .specJsonWithResolvedSubtrees() | ||
| .get("paths") | ||
|
|
||
| if (paths?.forEach) { |
There was a problem hiding this comment.
Would this work?
| if (paths?.forEach) { | |
| if (Map.isMap(paths)) { |
| paths.forEach((pathItem) => { | ||
| const additionalOperations = pathItem?.get?.("additionalOperations") | ||
|
|
||
| if (additionalOperations?.forEach) { |
There was a problem hiding this comment.
Same as above:
| if (additionalOperations?.forEach) { | |
| if (Map.isMap(additionalOperations)) { |
| })), | ||
| specSelectors: { | ||
| specJsonWithResolvedSubtrees: jest.fn(() => | ||
| Map({ |
There was a problem hiding this comment.
Would one fromJS work instead of nesting Maps, e.g.
fromJS({
paths: {
"/pets": {
Similar in other tests.
| }) | ||
|
|
||
| describe("state and validation", () => { | ||
| it("keeps parameter values and validation scoped to the custom operation", () => { |
There was a problem hiding this comment.
In e2e tests, should we not be using inputs and execute try it out to check if validation works?


Adds OpenAPI 3.2 Path Item additionalOperations support to Swagger UI. Custom HTTP methods (e.g. COPY, LINK, Search-Pets) are discovered and rendered as first-class operations under paths, callbacks and webhooks, with the exact method token shown as the badge label.
Description
This PR builds on the community contribution by @cmmoran in #10956 and keeps the original commits. On top of that work, it addresses the maintainer review comments, fixes the gaps found during review, and adds the requested Cypress coverage.
From the original contribution (@commoran):
Adds OpenAPI 3.2 Path Item additionalOperations support to Swagger UI. Custom operation methods are discovered and rendered as first-class operations, including their request parameters, request bodies, responses, deep links, validation state, and operation-specific metadata.
Custom methods retain the exact method token from the OpenAPI document. Standard methods continue to use the existing built-in behavior, while custom methods receive neutral styling rather than being added as hard-coded method names.
Added in this PR:
Review feedback: custom methods use a single neutral opblock-custom class (light and dark themes) and reuse
OPERATION_METHODSinstead of a local list. Removed the unusedopblock-summary-{method}/bold-label-{method}classes and switched toincludes().POST, post, HEAD, QUERY…) are ignored regardless of case, as the spec requires.operationSpecPathalways resolves fixed methods to their direct path, so an invalid entry can't take over the real operation.specJsonWithResolvedSubtrees, so operations inside$ref'd Path Items aren't filtered out.callbacksOperations,selectWebhooksOperations,webhooks) collect additionalOperations from nested Path Items through a sharedpathItemOperationshelper. The webhooks section inbase.jsxnow renders for isOAS31 || isOAS32.additionalOperationsrequest execution.supportedSubmitMethodsdocuments exact, case-sensitive custom tokens.Known limitation: custom operations without an operationId render correctly but can't be run from Try it out. With swagger-client 3.38.2, buildRequest fails with Operation undefined not found when it only has the path and method. This needs a follow-up in swagger-js; the Cypress test for it is included as
it.skip.Motivation and Context
OAS 3.2 allows arbitrary HTTP methods under additionalOperations on the Path Item Object (spec). Swagger UI previously left these operations out and couldn't resolve their data through the normal selector paths.
Supersedes #10956 Depends on swagger-api/swagger-client#4238 (released in swagger-client 3.38.2)
How Has This Been Tested?
npm run lint-errors: passednpm run test:unit -- --runInBand:passed, skippedScreenshots (if appropriate):
Checklist
My PR contains...
src/is unmodified: changes to documentation, CI, metadata, etc.)package.json)My changes...
Documentation
Automated tests