fix: enhance error handling for custom headers and improve test coverage for header management

This commit is contained in:
jeetul.samaiya 2025-09-10 21:01:24 +05:30
commit 90ab419d12
3 changed files with 163 additions and 41 deletions

View file

@ -137,7 +137,11 @@ const App = () => {
if (savedHeaders) {
try {
return JSON.parse(savedHeaders);
} catch {
} catch (error) {
console.warn(
`Failed to parse custom headers: "${savedHeaders}", will try legacy migration`,
error,
);
// Fall back to migration if JSON parsing fails
}
}

View file

@ -153,6 +153,7 @@ const CustomHeaders = ({
size="sm"
onClick={addHeader}
className="text-xs px-2"
data-testid="add-header-button"
>
<Plus className="w-3 h-3 mr-1" />
Add
@ -185,6 +186,7 @@ const CustomHeaders = ({
value={header.name}
onChange={(e) => updateHeader(index, "name", e.target.value)}
className="font-mono text-xs"
data-testid={`header-name-input-${index}`}
/>
<div className="relative">
<Input
@ -195,6 +197,7 @@ const CustomHeaders = ({
}
type={visibleValues.has(index) ? "text" : "password"}
className="font-mono text-xs pr-8"
data-testid={`header-value-input-${index}`}
/>
<Button
type="button"

View file

@ -1,4 +1,10 @@
import { render, screen, fireEvent, act } from "@testing-library/react";
import {
render,
screen,
fireEvent,
act,
waitFor,
} from "@testing-library/react";
import "@testing-library/jest-dom";
import { describe, it, beforeEach, jest } from "@jest/globals";
import Sidebar from "../Sidebar";
@ -623,117 +629,179 @@ describe("Sidebar", () => {
fireEvent.click(button);
};
it("should update bearer token", () => {
const setBearerToken = jest.fn();
it("should update bearer token via custom headers", async () => {
const setCustomHeaders = jest.fn();
renderSidebar({
bearerToken: "",
setBearerToken,
customHeaders: [],
setCustomHeaders,
transportType: "sse", // Set transport type to SSE
});
openAuthSection();
const tokenInput = screen.getByTestId("bearer-token-input");
fireEvent.change(tokenInput, { target: { value: "new_token" } });
// Add a new header
const addButton = screen.getByTestId("add-header-button");
fireEvent.click(addButton);
expect(setBearerToken).toHaveBeenCalledWith("new_token");
// Verify that setCustomHeaders was called to add an empty header
expect(setCustomHeaders).toHaveBeenCalledWith([
{
name: "",
value: "",
enabled: true,
},
]);
});
it("should update header name", () => {
const setHeaderName = jest.fn();
it("should update header name via custom headers", () => {
const setCustomHeaders = jest.fn();
renderSidebar({
headerName: "Authorization",
setHeaderName,
customHeaders: [
{
name: "Authorization",
value: "Bearer token123",
enabled: true,
},
],
setCustomHeaders,
transportType: "sse",
});
openAuthSection();
const headerInput = screen.getByTestId("header-input");
fireEvent.change(headerInput, { target: { value: "X-Custom-Auth" } });
const headerNameInput = screen.getByTestId("header-name-input-0");
fireEvent.change(headerNameInput, { target: { value: "X-Custom-Auth" } });
expect(setHeaderName).toHaveBeenCalledWith("X-Custom-Auth");
expect(setCustomHeaders).toHaveBeenCalledWith([
{
name: "X-Custom-Auth",
value: "Bearer token123",
enabled: true,
},
]);
});
it("should clear bearer token", () => {
const setBearerToken = jest.fn();
it("should clear bearer token via custom headers", () => {
const setCustomHeaders = jest.fn();
renderSidebar({
bearerToken: "existing_token",
setBearerToken,
customHeaders: [
{
name: "Authorization",
value: "Bearer existing_token",
enabled: true,
},
],
setCustomHeaders,
transportType: "sse", // Set transport type to SSE
});
openAuthSection();
const tokenInput = screen.getByTestId("bearer-token-input");
fireEvent.change(tokenInput, { target: { value: "" } });
const headerValueInput = screen.getByTestId("header-value-input-0");
fireEvent.change(headerValueInput, { target: { value: "" } });
expect(setBearerToken).toHaveBeenCalledWith("");
expect(setCustomHeaders).toHaveBeenCalledWith([
{
name: "Authorization",
value: "",
enabled: true,
},
]);
});
it("should properly render bearer token input", () => {
it("should properly render header value input as password field", () => {
const { rerender } = renderSidebar({
bearerToken: "existing_token",
customHeaders: [
{
name: "Authorization",
value: "Bearer existing_token",
enabled: true,
},
],
transportType: "sse", // Set transport type to SSE
});
openAuthSection();
// Token input should be a password field
const tokenInput = screen.getByTestId("bearer-token-input");
const tokenInput = screen.getByTestId("header-value-input-0");
expect(tokenInput).toHaveProperty("type", "password");
// Update the token
fireEvent.change(tokenInput, { target: { value: "new_token" } });
fireEvent.change(tokenInput, { target: { value: "Bearer new_token" } });
// Rerender with updated token
rerender(
<TooltipProvider>
<Sidebar
{...defaultProps}
bearerToken="new_token"
customHeaders={[
{
name: "Authorization",
value: "Bearer new_token",
enabled: true,
},
]}
transportType="sse"
/>
</TooltipProvider>,
);
// Token input should still exist after update
expect(screen.getByTestId("bearer-token-input")).toBeInTheDocument();
expect(screen.getByTestId("header-value-input-0")).toBeInTheDocument();
});
it("should maintain token visibility state after update", () => {
const { rerender } = renderSidebar({
bearerToken: "existing_token",
customHeaders: [
{
name: "Authorization",
value: "Bearer existing_token",
enabled: true,
},
],
transportType: "sse", // Set transport type to SSE
});
openAuthSection();
// Token input should be a password field
const tokenInput = screen.getByTestId("bearer-token-input");
const tokenInput = screen.getByTestId("header-value-input-0");
expect(tokenInput).toHaveProperty("type", "password");
// Update the token
fireEvent.change(tokenInput, { target: { value: "new_token" } });
fireEvent.change(tokenInput, { target: { value: "Bearer new_token" } });
// Rerender with updated token
rerender(
<TooltipProvider>
<Sidebar
{...defaultProps}
bearerToken="new_token"
customHeaders={[
{
name: "Authorization",
value: "Bearer new_token",
enabled: true,
},
]}
transportType="sse"
/>
</TooltipProvider>,
);
// Token input should still exist after update
expect(screen.getByTestId("bearer-token-input")).toBeInTheDocument();
expect(screen.getByTestId("header-value-input-0")).toBeInTheDocument();
});
it("should maintain header name when toggling auth section", () => {
renderSidebar({
headerName: "X-API-Key",
customHeaders: [
{
name: "X-API-Key",
value: "api-key-123",
enabled: true,
},
],
transportType: "sse",
});
@ -741,7 +809,7 @@ describe("Sidebar", () => {
openAuthSection();
// Verify header name is displayed
const headerInput = screen.getByTestId("header-input");
const headerInput = screen.getByTestId("header-name-input-0");
expect(headerInput).toHaveValue("X-API-Key");
// Close auth section
@ -752,19 +820,66 @@ describe("Sidebar", () => {
fireEvent.click(authButton);
// Verify header name is still preserved
expect(screen.getByTestId("header-input")).toHaveValue("X-API-Key");
expect(screen.getByTestId("header-name-input-0")).toHaveValue(
"X-API-Key",
);
});
it("should display default header name when not specified", () => {
it("should display placeholder for header name when no headers exist", () => {
renderSidebar({
headerName: undefined,
customHeaders: [],
transportType: "sse",
});
openAuthSection();
const headerInput = screen.getByTestId("header-input");
expect(headerInput).toHaveAttribute("placeholder", "Authorization");
// Verify that the "No custom headers configured" message is shown
expect(
screen.getByText("No custom headers configured"),
).toBeInTheDocument();
expect(
screen.getByText('Click "Add" to get started'),
).toBeInTheDocument();
// Verify the Add button is present
const addButton = screen.getByTestId("add-header-button");
expect(addButton).toBeInTheDocument();
});
it("should allow editing existing headers", () => {
const setCustomHeaders = jest.fn();
renderSidebar({
customHeaders: [
{
name: "Authorization",
value: "Bearer token123",
enabled: true,
},
],
setCustomHeaders,
transportType: "sse",
});
openAuthSection();
// Verify header inputs are rendered
const headerNameInput = screen.getByTestId("header-name-input-0");
const headerValueInput = screen.getByTestId("header-value-input-0");
expect(headerNameInput).toHaveValue("Authorization");
expect(headerValueInput).toHaveValue("Bearer token123");
expect(headerNameInput).toHaveAttribute("placeholder", "Header Name");
expect(headerValueInput).toHaveAttribute("placeholder", "Header Value");
// Update header name
fireEvent.change(headerNameInput, { target: { value: "X-API-Key" } });
expect(setCustomHeaders).toHaveBeenCalledWith([
{
name: "X-API-Key",
value: "Bearer token123",
enabled: true,
},
]);
});
});