Skip to content

feat: render swagger endpoint list - #69

Closed
Ivan-khodorov wants to merge 1 commit into
developfrom
story/4-endpoint-list
Closed

feat: render swagger endpoint list#69
Ivan-khodorov wants to merge 1 commit into
developfrom
story/4-endpoint-list

Conversation

@Ivan-khodorov

@Ivan-khodorov Ivan-khodorov commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Summary

Implements the first Swagger Viewer step from Feature 4: endpoint list rendering.

This PR replaces the temporary SwaggerViewer placeholder with a real endpoint list organized by path and HTTP method. It is based on the current
story/3-schema-json-yaml-support Editor branch and keeps the new src/components/swagger-viewer structure as the source of truth.

Changes Made

  • Added normalized endpoint extraction from OpenAPI paths
  • Added stable endpoint sorting by path and HTTP method order
  • Added endpoint metadata support: method, path, summary, operationId, description, deprecated flag, and tags
  • Replaced the SwaggerViewer placeholder with a grouped MUI endpoint list
  • Kept the old swagger-view path as a compatibility re-export to avoid duplicate Viewer implementations
  • Updated EN/RU Viewer dictionary keys
  • Updated SwaggerEditor test mock to verify that calculated endpoints are passed into SwaggerViewer
  • Added tests for endpoint extraction and Viewer endpoint rendering

Related issue

Closes #64

Feature

Feature 4: Swagger Viewer

Acceptance criteria

Feature 1: App Header
  • Non-auth users see Sign In / Sign Up in header (upper right) — 15
  • Auth users see History / Sign Out in header — 10
  • About link in header and footer — 10
  • Expired/invalid token → redirect from private routes to Main — 10
  • Sign In / Sign Up buttons redirect to respective form route — 15
Feature 2: Sign In / Sign Up
  • Sign In / Sign Up / Sign Out buttons present everywhere they should be — 10
  • Client-side validation (email, password: 8+ chars, letter+digit+special, Unicode) — 20
  • Successful login → redirect to Main — 10
  • Logged-in user on Sign In / Sign Up routes → redirect to Main — 10
Feature 3: Swagger Editor
  • Load/paste schema in JSON and YAML — 25
  • Auto-detect input format (JSON vs YAML) — 20
  • Format switch with JSON ↔ YAML conversion, no data loss — 20
  • Schema validation with error indication — 15
  • Auth users save schema; restored on next login — 10
  • Viewer auto-populates with endpoints on valid schema — 10
  • Responsive split view (horizontal/vertical by orientation) — 20
Feature 4: Swagger Viewer
  • Endpoint list organized by path/method — 20
  • Details: method, path, all param types (path/query/header/cookie) — 25
  • Request schema and example payloads displayed — 20
  • Response schema, examples, all status codes displayed — 25
  • Try-It-Out: fill params/headers/body, execute, show response — 20
  • Generate cURL + copy-to-clipboard — 10
Feature 5: History and Analytics
  • SSR-generated; empty state with links to editor/viewer — 15
  • Requests sorted by timestamp (most recent first) — 10
  • Server-side analytics: duration, status, timestamp, method, request size, response size, error details, endpoint/URL — 45
Feature 6: About Page
  • Public route, accessible to all — 5
  • Info about RS School course — 5
  • Team info (names, roles, GitHub links) — 10
  • Design consistent with the app — 5
Feature 7: General Requirements
  • i18n: 2+ languages with toggler in header — 30
  • Sticky header with animation on stick — 10
  • User-friendly error display — 10
  • Private routes protected (401 if not authenticated) — 5
Feature 8: YouTube Video
  • 5–7 min YouTube walkthrough linked, covers all criteria — 50

Screenshots

TODO: add screenshot from the Swagger Viewer endpoint list.

Deployment

TODO: add Vercel Preview URL after PR creation.

Verification

  • npm test — 16 files, 68 tests passed
  • npm run lint — passed
  • npm run build — passed
  • git diff --check — passed

Known limitations

  • This PR implements only the endpoint list criterion from Feature 4.
  • Endpoint details, request schemas, response schemas, Try-It-Out, cURL generation, and request history are intentionally left for follow-up
    Viewer tasks.
  • Auth-dependent Editor stories are still blocked by the Auth/Supabase integration.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would break existing functionality)
  • Documentation update

Checklist

  • Self-review done
  • No console errors / warnings / logs
  • No any / @ts-ignore
  • Tests added / updated and passing

Summary by CodeRabbit

  • New Features

    • Added a full Swagger/OpenAPI editor experience with Monaco support and YAML/JSON format switching.
    • Added a Swagger viewer that displays API metadata and renders endpoints grouped by path, including sorted methods and per-endpoint summaries.
    • Added schema restore/save controls and updated onboarding text via English and Russian localization.
  • Bug Fixes

    • Improved empty/invalid states with clearer, localized messages, including fallback summaries when endpoint descriptions are missing.
  • Tests

    • Added/expanded component and utility test coverage for the editor, viewer, controls, and schema parsing/validation.

@vercel

vercel Bot commented Jul 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
swagger-editor-app Ready Ready Preview, Comment Jul 9, 2026 5:31pm

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Implements a Swagger/OpenAPI editor page with schema parsing, validation, restore/save, Monaco editing, grouped endpoint viewing, format toggling, and localized status messages. Adds tests for the hook and components, updates translations, and wires the editor into the home page.

Changes

Swagger editor workflow

Layer / File(s) Summary
Schema parsing and validation
src/utils/swagger-editor/*, src/services/schema-service.ts, src/utils/network/get-signal-with-timeout.ts, src/types/index.ts, src/constants/default-schema.ts, package.json
Adds schema format types, parsing/conversion utilities, endpoint extraction/grouping, validation, restore/save service calls, timeout signaling, shared OpenAPI document types, a default OpenAPI schema, and the parser/validator dependencies.
Editor state hook and tests
src/utils/hooks/use-swagger.ts, src/utils/hooks/use-swagger.test.ts
Implements debounced validation, schema restore, format toggling, and error handling in useSwagger, with tests for debounce, restore, and conversion paths.
Editor, viewer, and control components
src/components/swagger-editor/*, src/components/swagger-viewer/*, src/components/swagger-control/*, src/components/swagger-monaco-editor/*, src/components/format-toggle/*, src/components/index.ts
Adds the Swagger editor page composition, Monaco editor integration, save/format controls, grouped endpoint viewer, and component tests plus barrel exports.
App shell and shared UI wiring
src/app/[locale]/page.tsx, src/components/header/header.tsx, src/components/main-text/*, src/constants/index.ts, src/app/globals.css, tsconfig.json
Switches the locale page to render SwaggerEditor, centralizes flex styles, adds the main text component, and updates global styling and TypeScript includes.
Localization
src/i18n/messages/en.json, src/i18n/messages/ru.json
Updates metadata text and adds Swagger editor, viewer, and control translations in English and Russian.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant useSwagger
  participant SwaggerEditor
  participant SwaggerControl
  participant SwaggerMonacoEditor
  participant SwaggerViewer
  useSwagger-->>SwaggerEditor: editorValue, schema, format, handlers
  SwaggerEditor->>SwaggerControl: format, validity, save handler
  SwaggerEditor->>SwaggerMonacoEditor: value, format, onChange
  SwaggerEditor->>SwaggerViewer: apiInfo, endpoints, isValid
  SwaggerControl->>useSwagger: handleFormatToggle / save schema
  SwaggerMonacoEditor->>useSwagger: handleEditorChange
Loading

Possibly related PRs

Suggested reviewers: YuliaDemir

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR adds broad Swagger editor/control/Monaco/schema-service and homepage changes that go beyond endpoint list rendering. Split the editor, validation, homepage, and dependency updates into separate PRs, and keep this one focused on the endpoint list.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR implements endpoint list rendering grouped by path and method, with extraction and tests matching issue #64.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: rendering the Swagger endpoint list.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch story/4-endpoint-list

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

@AlyaEngineer AlyaEngineer added the feature-4-viewer Feature 4: Swagger Viewer label Jul 9, 2026
@AlyaEngineer AlyaEngineer linked an issue Jul 9, 2026 that may be closed by this pull request
Comment thread src/i18n/messages/en.json Outdated
Comment thread src/components/swagger-viewer/swagger-viewer.tsx Outdated
Comment thread src/i18n/messages/en.json Outdated
Comment thread src/components/swagger-viewer/swagger-viewer.tsx Outdated
Comment thread src/components/swagger-viewer/swagger-viewer.tsx Outdated
Comment thread src/components/swagger-viewer/swagger-viewer.tsx Outdated
Comment thread src/components/swagger-viewer/swagger-viewer.tsx Outdated
Comment thread src/components/swagger-viewer/swagger-viewer.tsx Outdated

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🧹 Nitpick comments (5)
src/utils/hooks/use-swagger.ts (1)

24-27: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Hardcoded auth stub — flagged by author's own TODO.

isAuthenticated is a hardcoded constant, gating the entire restore-on-mount flow. Since this is explicitly called out as a TODO, worth tracking before merge to main so it isn't forgotten.

Want me to open a follow-up issue to track wiring real authentication here?

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/utils/hooks/use-swagger.ts` around lines 24 - 27, The restore-on-mount
flow in useSwagger is currently gated by a hardcoded isAuthenticated stub, which
is only a temporary TODO. Replace the inline constant with the real
authentication source used by the app, and keep the condition in the same
restore effect logic so the hook only runs when actual auth state is available.
Use the useSwagger hook and its isAuthenticated check as the place to wire this
in.
src/services/schema-service.ts (1)

39-50: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Save error discards response detail.

save throws a generic 'Failed to save schema' regardless of status code or server-provided error body, which limits what callers can surface to users (e.g., quota/auth failures vs. generic 500s look identical).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/services/schema-service.ts` around lines 39 - 50, The save flow in
SchemaService.save currently throws a generic error and drops the HTTP status
and server error body, so update the fetch failure handling to preserve response
details for callers. In the save method, inspect the non-OK response from
/api/schema and build the thrown error using the response status/statusText and
any parsed error payload when available, so different failure cases can be
distinguished by consumers.
src/components/swagger-control/swagger-control.test.tsx (1)

81-93: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Add coverage for the timeout/AbortError branch.

Tests cover the generic save failure (ok: false) but not the AbortError path that shows requestTimeoutError, which is a distinct branch in SwaggerControl's save handler.

✅ Suggested additional test
it('shows a timeout toast when the save request is aborted', async () => {
  global.fetch = vi.fn().mockRejectedValue(
    Object.assign(new Error('aborted'), { name: 'AbortError' }),
  ) as unknown as typeof fetch;

  renderWithToast(<SwaggerControl {...baseProps} isValid />);

  await userEvent.click(screen.getByRole('button', { name: 'saveButton' }));

  await waitFor(() => {
    expect(screen.getByRole('alert')).toHaveTextContent('requestTimeoutError');
  });
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/swagger-control/swagger-control.test.tsx` around lines 81 -
93, Add test coverage in SwaggerControl for the AbortError save-failure branch:
the existing save failure test only covers a false ok response, so add a new
case in swagger-control.test.tsx that mocks fetch to reject with an AbortError
and asserts the toast shows requestTimeoutError. Use the existing save handler
flow in SwaggerControl and the saveButton/alert queries to place the new test
near the current schemaSaveError case.
src/components/swagger-viewer/swagger-viewer.tsx (1)

88-88: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Redundant type cast.

getMethodColor already returns ChipProps['color'] (per its definition), so the as ChipProps['color'] cast here is unnecessary.

♻️ Proposed simplification
-                  <Chip
-                    color={getMethodColor(endpoint.method) as ChipProps['color']}
+                  <Chip
+                    color={getMethodColor(endpoint.method)}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/swagger-viewer/swagger-viewer.tsx` at line 88, The Chip color
prop in swagger-viewer’s endpoint rendering uses an unnecessary type cast
because getMethodColor already returns ChipProps['color']; remove the redundant
cast at the getMethodColor call site in swagger-viewer.tsx and keep the existing
function typing intact.
src/components/swagger-control/swagger-control.tsx (1)

29-39: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Track the auth TODO.

isAuthenticated is hardcoded to true, so the auth guard and conditional rendering are currently dead code. Fine as an interim placeholder given the TODO, but flag for follow-up once real auth lands.

Also applies to: 69-73

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/swagger-control/swagger-control.tsx` around lines 29 - 39,
`isAuthenticated` in `SwaggerControl` is hardcoded to true, so the auth guard in
`handleSaveSchema` and the conditional rendering are effectively dead code. Keep
the placeholder only if needed for the TODO, but make sure this is tracked for
follow-up and is easy to replace once real auth is wired in; update both the
save guard and the related render branch to use the eventual auth source instead
of the inline mock.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/utils/hooks/use-swagger.ts`:
- Around line 29-49: The debounce cleanup in useSwagger’s useEffect only clears
the timer, so an older in-flight validateSwaggerSchema(editorValue) call can
still resolve later and overwrite isValid, error, schema, or format with stale
data. Add a cancellation guard or request token inside useEffect so each
validation run can detect when it has been superseded by a newer editorValue,
and only apply setIsValid, setError, setSchema, and setFormat updates for the
latest run.

---

Nitpick comments:
In `@src/components/swagger-control/swagger-control.test.tsx`:
- Around line 81-93: Add test coverage in SwaggerControl for the AbortError
save-failure branch: the existing save failure test only covers a false ok
response, so add a new case in swagger-control.test.tsx that mocks fetch to
reject with an AbortError and asserts the toast shows requestTimeoutError. Use
the existing save handler flow in SwaggerControl and the saveButton/alert
queries to place the new test near the current schemaSaveError case.

In `@src/components/swagger-control/swagger-control.tsx`:
- Around line 29-39: `isAuthenticated` in `SwaggerControl` is hardcoded to true,
so the auth guard in `handleSaveSchema` and the conditional rendering are
effectively dead code. Keep the placeholder only if needed for the TODO, but
make sure this is tracked for follow-up and is easy to replace once real auth is
wired in; update both the save guard and the related render branch to use the
eventual auth source instead of the inline mock.

In `@src/components/swagger-viewer/swagger-viewer.tsx`:
- Line 88: The Chip color prop in swagger-viewer’s endpoint rendering uses an
unnecessary type cast because getMethodColor already returns ChipProps['color'];
remove the redundant cast at the getMethodColor call site in swagger-viewer.tsx
and keep the existing function typing intact.

In `@src/services/schema-service.ts`:
- Around line 39-50: The save flow in SchemaService.save currently throws a
generic error and drops the HTTP status and server error body, so update the
fetch failure handling to preserve response details for callers. In the save
method, inspect the non-OK response from /api/schema and build the thrown error
using the response status/statusText and any parsed error payload when
available, so different failure cases can be distinguished by consumers.

In `@src/utils/hooks/use-swagger.ts`:
- Around line 24-27: The restore-on-mount flow in useSwagger is currently gated
by a hardcoded isAuthenticated stub, which is only a temporary TODO. Replace the
inline constant with the real authentication source used by the app, and keep
the condition in the same restore effect logic so the hook only runs when actual
auth state is available. Use the useSwagger hook and its isAuthenticated check
as the place to wire this in.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 77ee2abe-05f1-4d7d-94b5-22ceff3148fc

📥 Commits

Reviewing files that changed from the base of the PR and between b8786e6 and f378373.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (36)
  • package.json
  • src/app/[locale]/page.tsx
  • src/app/globals.css
  • src/components/format-toggle/format-toggle.tsx
  • src/components/header/header.tsx
  • src/components/index.ts
  • src/components/main-text/main-text.test.tsx
  • src/components/main-text/main-text.tsx
  • src/components/swagger-control/swagger-control.test.tsx
  • src/components/swagger-control/swagger-control.tsx
  • src/components/swagger-editor/swagger-editor.test.tsx
  • src/components/swagger-editor/swagger-editor.tsx
  • src/components/swagger-monaco-editor/swagger-monaco-editor.test.tsx
  • src/components/swagger-monaco-editor/swagger-monaco-editor.tsx
  • src/components/swagger-viewer/swagger-viewer.test.tsx
  • src/components/swagger-viewer/swagger-viewer.tsx
  • src/constants/default-schema.ts
  • src/constants/index.ts
  • src/i18n/messages/en.json
  • src/i18n/messages/ru.json
  • src/services/schema-service.ts
  • src/types/index.ts
  • src/utils/hooks/use-swagger.test.ts
  • src/utils/hooks/use-swagger.ts
  • src/utils/network/get-signal-with-timeout.ts
  • src/utils/swagger-editor/get-method-color.ts
  • src/utils/swagger-editor/get-swagger-endpoints.ts
  • src/utils/swagger-editor/group-endpoints-by-path.ts
  • src/utils/swagger-editor/is-record.ts
  • src/utils/swagger-editor/schema-format-convert.test.ts
  • src/utils/swagger-editor/schema-format-parse.test.ts
  • src/utils/swagger-editor/schema-format.ts
  • src/utils/swagger-editor/schema-types.ts
  • src/utils/swagger-editor/swagger-validation.test.ts
  • src/utils/swagger-editor/swagger-validation.ts
  • tsconfig.json
💤 Files with no reviewable changes (1)
  • src/app/globals.css
✅ Files skipped from review due to trivial changes (7)
  • src/utils/network/get-signal-with-timeout.ts
  • src/utils/swagger-editor/schema-format-parse.test.ts
  • src/constants/index.ts
  • src/utils/swagger-editor/get-method-color.ts
  • src/utils/swagger-editor/is-record.ts
  • tsconfig.json
  • src/i18n/messages/en.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/swagger-viewer/swagger-viewer.test.tsx

Comment on lines +29 to +49
useEffect(() => {
const timeoutId = window.setTimeout(() => {
validateSwaggerSchema(editorValue)
.then((result) => {
setIsValid(result.isValid);
setError(result.error);
setSchema(result.schema);

if (result.isValid) {
setFormat(result.detectedFormat);
}
})
.catch((validationError) => {
setError(
validationError instanceof Error ? validationError.message : t('conversionError'),
);
});
}, VALIDATION_DEBOUNCE_MS);

return () => window.clearTimeout(timeoutId);
}, [editorValue, t]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the relevant file and related validation helper
git ls-files 'src/utils/hooks/use-swagger.ts' 'src/utils/**' | sed -n '1,120p'

echo
echo '--- outline: src/utils/hooks/use-swagger.ts ---'
ast-grep outline src/utils/hooks/use-swagger.ts --view expanded || true

echo
echo '--- outline: potential validation helper files ---'
fd -a 'swagger' src/utils src | sed -n '1,120p' || true
rg -n "validateSwaggerSchema|SwaggerParser|VALIDATION_DEBOUNCE_MS|useEffect\\(" src/utils src -g '!**/*.d.ts' -g '!**/node_modules/**' || true

Repository: AlyaEngineer/swagger-editor-app

Length of output: 6073


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- src/utils/hooks/use-swagger.ts ---'
cat -n src/utils/hooks/use-swagger.ts | sed -n '1,220p'

echo
echo '--- src/utils/swagger-editor/swagger-validation.ts ---'
cat -n src/utils/swagger-editor/swagger-validation.ts | sed -n '1,220p'

Repository: AlyaEngineer/swagger-editor-app

Length of output: 5981


Prevent stale validation results from overwriting the current editor state
clearTimeout only cancels the debounce timer; once validateSwaggerSchema(editorValue) is in flight, a slower earlier request can still resolve after a later edit and overwrite isValid/error/schema/format with stale data. Add a cancellation flag or request token and skip state updates for superseded runs.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/utils/hooks/use-swagger.ts` around lines 29 - 49, The debounce cleanup in
useSwagger’s useEffect only clears the timer, so an older in-flight
validateSwaggerSchema(editorValue) call can still resolve later and overwrite
isValid, error, schema, or format with stale data. Add a cancellation guard or
request token inside useEffect so each validation run can detect when it has
been superseded by a newer editorValue, and only apply setIsValid, setError,
setSchema, and setFormat updates for the latest run.

@Ivan-khodorov
Ivan-khodorov changed the base branch from story/3-schema-json-yaml-support to develop July 9, 2026 17:45
@AlyaEngineer
AlyaEngineer deleted the story/4-endpoint-list branch July 13, 2026 23:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature-4-viewer Feature 4: Swagger Viewer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Endpoint list

2 participants