Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/hooks/Auth0Context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,17 @@ export interface Auth0ContextInterface extends AuthState {
* Retrieves the stored credentials, refreshing them if necessary.
* @param scope The scopes to request for the new access token (used during refresh).
* @param minTtl The minimum time-to-live (in seconds) required for the access token.
* @param parameters Additional parameters to send during the refresh request.
* @param forceRefresh If true, forces a refresh of the credentials.
* @returns A promise that resolves with the user's credentials.
* @throws {AuthError} If credentials cannot be retrieved or refreshed.
*/
getCredentials(scope?: string, minTtl?: number): Promise<Credentials>;
getCredentials(
scope?: string,
minTtl?: number,
parameters?: Record<string, unknown>,
forceRefresh?: boolean
): Promise<Credentials>;

/**
* Clears the user's credentials without clearing their web session and logs them out.
Expand Down
3 changes: 2 additions & 1 deletion src/hooks/Auth0Provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,10 @@ export const Auth0Provider = ({
window?.location?.search?.includes('state=');
if (hasRedirectParams) {
try {
user = await client.webAuth.getWebUser();
// If it does, handle the redirect. This will exchange the code for tokens.
await client.webAuth.handleRedirectCallback();
// should get the user after handle redirect
user = await client.webAuth.getWebUser();
// Clean the URL
window.history.replaceState(
{},
Expand Down
76 changes: 73 additions & 3 deletions src/hooks/__tests__/Auth0Provider.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {
import '@testing-library/jest-dom';
import { Auth0Provider, useAuth0 } from '..';
import Auth0 from '../../index';
import { Auth0User } from '../../core/models';

// Mock TurboModuleRegistry first
jest.mock('react-native/Libraries/TurboModule/TurboModuleRegistry', () => ({
Expand Down Expand Up @@ -68,8 +67,12 @@ jest.mock('../../index');
const MockAuth0 = Auth0 as jest.MockedClass<typeof Auth0>;

// Mock the Auth0User model's factory method
jest.mock('../../core/models/Auth0User');
const MockAuth0User = Auth0User as jest.MockedClass<typeof Auth0User>;
jest.mock('../../core/models/Auth0User', () => ({
Auth0User: {
fromIdToken: jest.fn(),
},
}));
const { Auth0User: MockAuth0User } = require('../../core/models/Auth0User');

// 2. A more complete mock client factory
const createMockClient = () => {
Expand All @@ -89,6 +92,7 @@ const createMockClient = () => {
cancelWebAuth: jest.fn().mockResolvedValue(undefined),
handleRedirectCallback: jest.fn().mockResolvedValue(undefined),
checkWebSession: jest.fn().mockResolvedValue(null),
getWebUser: jest.fn().mockResolvedValue(null),
},
credentialsManager: {
hasValidCredentials: jest.fn().mockResolvedValue(false),
Expand Down Expand Up @@ -803,4 +807,70 @@ describe('Auth0Provider', () => {
});
});
});

// Web Platform Method Tests
describe('Web Platform Methods', () => {
it('should verify webAuth methods exist and are callable', () => {
// Verify all required webAuth methods exist in the mock
expect(mockClientInstance.webAuth.handleRedirectCallback).toBeDefined();
expect(mockClientInstance.webAuth.getWebUser).toBeDefined();
expect(mockClientInstance.webAuth.checkWebSession).toBeDefined();

// Verify they are functions
expect(typeof mockClientInstance.webAuth.handleRedirectCallback).toBe(
'function'
);
expect(typeof mockClientInstance.webAuth.getWebUser).toBe('function');
expect(typeof mockClientInstance.webAuth.checkWebSession).toBe(
'function'
);
});

it('should verify webAuth methods can be mocked properly', async () => {
const mockUser = { sub: 'test|123', name: 'Test User' };

// Setup mocks
mockClientInstance.webAuth.handleRedirectCallback.mockResolvedValue(
undefined
);
mockClientInstance.webAuth.getWebUser.mockResolvedValue(mockUser);
mockClientInstance.webAuth.checkWebSession.mockResolvedValue(undefined);

// Call the methods
await mockClientInstance.webAuth.handleRedirectCallback();
const user = await mockClientInstance.webAuth.getWebUser();
await mockClientInstance.webAuth.checkWebSession();

// Verify calls were made
expect(
mockClientInstance.webAuth.handleRedirectCallback
).toHaveBeenCalledTimes(1);
expect(mockClientInstance.webAuth.getWebUser).toHaveBeenCalledTimes(1);
expect(mockClientInstance.webAuth.checkWebSession).toHaveBeenCalledTimes(
1
);
expect(user).toEqual(mockUser);
});

it('should verify the sequence of webAuth method calls can be tracked', async () => {
// Setup mocks
mockClientInstance.webAuth.handleRedirectCallback.mockResolvedValue(
undefined
);
mockClientInstance.webAuth.getWebUser.mockResolvedValue(null);

// Call methods in sequence
await mockClientInstance.webAuth.handleRedirectCallback();
await mockClientInstance.webAuth.getWebUser();

// Verify call order using invocationCallOrder
const handleRedirectCallOrder =
mockClientInstance.webAuth.handleRedirectCallback.mock
.invocationCallOrder[0];
const getWebUserCallOrder =
mockClientInstance.webAuth.getWebUser.mock.invocationCallOrder[0];

expect(getWebUserCallOrder).toBeGreaterThan(handleRedirectCallOrder);
});
});
});