Skip to content

Commit 03bb303

Browse files
committed
rm loading, prm test
1 parent cc49358 commit 03bb303

File tree

4 files changed

+131
-22
lines changed

4 files changed

+131
-22
lines changed

client/src/App.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -329,8 +329,6 @@ const App = () => {
329329
}
330330
} catch (error) {
331331
console.error("Error loading OAuth tokens:", error);
332-
} finally {
333-
updateAuthState({ loading: false });
334332
}
335333
};
336334

client/src/components/AuthDebugger.tsx

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -60,23 +60,23 @@ const AuthDebugger = ({
6060
authState,
6161
updateAuthState,
6262
}: AuthDebuggerProps) => {
63-
// Initialize loading state
63+
// Check for existing tokens on mount
6464
useEffect(() => {
65-
if (authState.loading && serverUrl) {
66-
// Check if we have existing tokens
65+
if (serverUrl && !authState.oauthTokens) {
6766
const checkTokens = async () => {
6867
const provider = new DebugInspectorOAuthClientProvider(serverUrl);
6968
const existingTokens = await provider.tokens();
70-
71-
updateAuthState({
72-
loading: false,
73-
oauthTokens: existingTokens || null,
74-
});
69+
if (existingTokens) {
70+
updateAuthState({
71+
oauthTokens: existingTokens,
72+
oauthStep: "complete",
73+
});
74+
}
7575
};
76-
7776
checkTokens();
7877
}
79-
}, [serverUrl, authState.loading, updateAuthState]);
78+
}, [serverUrl]); // Only run when serverUrl changes
79+
8080
const startOAuthFlow = useCallback(() => {
8181
if (!serverUrl) {
8282
updateAuthState({
@@ -241,10 +241,7 @@ const AuthDebugger = ({
241241
<StatusMessage message={authState.statusMessage} />
242242
)}
243243

244-
{authState.loading ? (
245-
<p>Loading authentication status...</p>
246-
) : (
247-
<div className="space-y-4">
244+
<div className="space-y-4">
248245
{authState.oauthTokens && (
249246
<div className="space-y-2">
250247
<p className="text-sm font-medium">Access Token:</p>
@@ -286,7 +283,6 @@ const AuthDebugger = ({
286283
the standard automatic flow.
287284
</p>
288285
</div>
289-
)}
290286
</div>
291287

292288
<OAuthFlowProgress

client/src/components/__tests__/AuthDebugger.test.tsx

Lines changed: 120 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,9 @@ describe("AuthDebugger", () => {
106106

107107
mockDiscoverOAuthMetadata.mockResolvedValue(mockOAuthMetadata);
108108
mockRegisterClient.mockResolvedValue(mockOAuthClientInfo);
109-
mockDiscoverOAuthProtectedResourceMetadata.mockResolvedValue(null);
109+
mockDiscoverOAuthProtectedResourceMetadata.mockRejectedValue(
110+
new Error("No protected resource metadata found")
111+
);
110112
mockStartAuthorization.mockImplementation(async (_sseUrl, options) => {
111113
const authUrl = new URL("https://oauth.example.com/authorize");
112114

@@ -448,7 +450,7 @@ describe("AuthDebugger", () => {
448450
await act(async () => {
449451
renderAuthDebugger({
450452
updateAuthState,
451-
authState: { ...defaultAuthState, loading: false },
453+
authState: { ...defaultAuthState },
452454
});
453455
});
454456

@@ -471,7 +473,7 @@ describe("AuthDebugger", () => {
471473
).mock.calls.find((call) => call[0] === SESSION_KEYS.AUTH_DEBUGGER_STATE);
472474

473475
expect(storedStateCall).toBeDefined();
474-
const storedState = JSON.parse(storedStateCall![1]);
476+
const storedState = JSON.parse(storedStateCall![1] as string);
475477

476478
expect(storedState).toMatchObject({
477479
oauthStep: "authorization_code",
@@ -487,4 +489,119 @@ describe("AuthDebugger", () => {
487489
});
488490
});
489491
});
492+
493+
describe("OAuth Protected Resource Metadata", () => {
494+
it("should successfully fetch and display protected resource metadata", async () => {
495+
const updateAuthState = jest.fn();
496+
const mockResourceMetadata = {
497+
resource: "https://example.com/api",
498+
authorization_servers: ["https://custom-auth.example.com"],
499+
bearer_methods_supported: ["header", "body"],
500+
resource_documentation: "https://example.com/api/docs",
501+
resource_policy_uri: "https://example.com/api/policy",
502+
};
503+
504+
// Mock successful metadata discovery
505+
mockDiscoverOAuthProtectedResourceMetadata.mockResolvedValue(
506+
mockResourceMetadata
507+
);
508+
mockDiscoverOAuthMetadata.mockResolvedValue(mockOAuthMetadata);
509+
510+
await act(async () => {
511+
renderAuthDebugger({
512+
updateAuthState,
513+
authState: { ...defaultAuthState },
514+
});
515+
});
516+
517+
// Click Guided OAuth Flow to start the process
518+
await act(async () => {
519+
fireEvent.click(screen.getByText("Guided OAuth Flow"));
520+
});
521+
522+
// Verify that the flow started with metadata discovery
523+
expect(updateAuthState).toHaveBeenCalledWith({
524+
oauthStep: "metadata_discovery",
525+
authorizationUrl: null,
526+
statusMessage: null,
527+
latestError: null,
528+
});
529+
530+
// Click Continue to trigger metadata discovery
531+
const continueButton = await screen.findByText("Continue");
532+
await act(async () => {
533+
fireEvent.click(continueButton);
534+
});
535+
536+
// Wait for the metadata to be fetched
537+
await waitFor(() => {
538+
expect(mockDiscoverOAuthProtectedResourceMetadata).toHaveBeenCalledWith(
539+
"https://example.com"
540+
);
541+
});
542+
543+
// Verify the state was updated with the resource metadata
544+
await waitFor(() => {
545+
expect(updateAuthState).toHaveBeenCalledWith(
546+
expect.objectContaining({
547+
resourceMetadata: mockResourceMetadata,
548+
authServerUrl: new URL("https://custom-auth.example.com"),
549+
oauthStep: "client_registration",
550+
})
551+
);
552+
});
553+
});
554+
555+
it("should handle protected resource metadata fetch failure gracefully", async () => {
556+
const updateAuthState = jest.fn();
557+
const mockError = new Error("Failed to fetch resource metadata");
558+
559+
// Mock failed metadata discovery
560+
mockDiscoverOAuthProtectedResourceMetadata.mockRejectedValue(mockError);
561+
// But OAuth metadata should still work with the original URL
562+
mockDiscoverOAuthMetadata.mockResolvedValue(mockOAuthMetadata);
563+
564+
await act(async () => {
565+
renderAuthDebugger({
566+
updateAuthState,
567+
authState: { ...defaultAuthState },
568+
});
569+
});
570+
571+
// Click Guided OAuth Flow
572+
await act(async () => {
573+
fireEvent.click(screen.getByText("Guided OAuth Flow"));
574+
});
575+
576+
// Click Continue to trigger metadata discovery
577+
const continueButton = await screen.findByText("Continue");
578+
await act(async () => {
579+
fireEvent.click(continueButton);
580+
});
581+
582+
// Wait for the metadata fetch to fail
583+
await waitFor(() => {
584+
expect(mockDiscoverOAuthProtectedResourceMetadata).toHaveBeenCalledWith(
585+
"https://example.com"
586+
);
587+
});
588+
589+
// Verify the flow continues despite the error
590+
await waitFor(() => {
591+
expect(updateAuthState).toHaveBeenCalledWith(
592+
expect.objectContaining({
593+
resourceMetadataError: mockError,
594+
// Should use the original server URL as fallback
595+
authServerUrl: new URL("https://example.com"),
596+
oauthStep: "client_registration",
597+
})
598+
);
599+
});
600+
601+
// Verify that regular OAuth metadata discovery was still called
602+
expect(mockDiscoverOAuthMetadata).toHaveBeenCalledWith(
603+
new URL("https://example.com")
604+
);
605+
});
606+
});
490607
});

client/src/lib/auth-types.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ export interface StatusMessage {
2727
export interface AuthDebuggerState {
2828
isInitiatingAuth: boolean;
2929
oauthTokens: OAuthTokens | null;
30-
loading: boolean;
3130
oauthStep: OAuthStep;
3231
resourceMetadata: OAuthProtectedResourceMetadata | null;
3332
resourceMetadataError:
@@ -47,7 +46,6 @@ export interface AuthDebuggerState {
4746
export const EMPTY_DEBUGGER_STATE: AuthDebuggerState = {
4847
isInitiatingAuth: false,
4948
oauthTokens: null,
50-
loading: true,
5149
oauthStep: "metadata_discovery",
5250
oauthMetadata: null,
5351
resourceMetadata: null,

0 commit comments

Comments
 (0)