Skip to content
250 changes: 250 additions & 0 deletions packages/core/src/auth/__mocks__/core-client.mocks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,250 @@
import { vi } from 'vitest';

import { createMockI18nService } from '../../i18n/__mocks__/i18n-service.mocks';
import type {
AuthDetails,
BasicAuth0ContextInterface,
CoreClientInterface,
User,
Auth0ContextInterface,
GetTokenSilentlyVerboseResponse,
GetTokenSilentlyOptions,
} from '../auth-types';

/**
* Creates a mock user object
*/
export const createMockUser = (overrides?: Partial<User>): User => ({
sub: 'auth0|test-user-123',
name: 'Test User',
given_name: 'Test',
family_name: 'User',
email: 'user@example.com',
email_verified: true,
picture: 'https://example.com/avatar.jpg',
updated_at: '2024-01-01T00:00:00.000Z',
...overrides,
});

/**
* Creates a mock GetTokenSilentlyVerboseResponse
*/
export const createMockVerboseTokenResponse = (
overrides?: Partial<GetTokenSilentlyVerboseResponse>,
): GetTokenSilentlyVerboseResponse => ({
id_token: 'mock-id-token',
access_token: 'mock-access-token',
expires_in: 3600,
...overrides,
});

/**
* Creates a mock BasicAuth0ContextInterface
*/
export const createMockBasicAuth0Context = (
overrides?: Partial<BasicAuth0ContextInterface>,
): BasicAuth0ContextInterface => ({
isAuthenticated: true,
user: createMockUser(),
getAccessTokenSilently: vi.fn().mockImplementation(async (options?: GetTokenSilentlyOptions) => {
if (options?.detailedResponse) {
return createMockVerboseTokenResponse();
}
return 'mock-access-token';
}),
getAccessTokenWithPopup: vi.fn().mockResolvedValue('mock-access-token'),
loginWithRedirect: vi.fn().mockResolvedValue(undefined),
...overrides,
});

/**
* Creates a mock Auth0ContextInterface with full properties
*/
export const createMockAuth0Context = (
overrides?: Partial<Auth0ContextInterface>,
): Auth0ContextInterface => ({
isAuthenticated: true,
isLoading: false,
user: createMockUser(),
getAccessTokenSilently: vi.fn().mockImplementation(async (options?: GetTokenSilentlyOptions) => {
if (options?.detailedResponse) {
return createMockVerboseTokenResponse();
}
return 'mock-access-token';
}),
getAccessTokenWithPopup: vi.fn().mockResolvedValue('mock-access-token'),
loginWithRedirect: vi.fn().mockResolvedValue(undefined),
loginWithPopup: vi.fn().mockResolvedValue(undefined),
logout: vi.fn().mockResolvedValue(undefined),
getIdTokenClaims: vi.fn().mockResolvedValue({
sub: 'auth0|test-user-123',
aud: 'test-client-id',
iss: 'https://test-domain.auth0.com/',
}),
handleRedirectCallback: vi.fn().mockResolvedValue({
appState: {},
}),
...overrides,
});

/**
* Creates a mock AuthDetails object
*/
export const createMockAuthDetails = (overrides?: Partial<AuthDetails>): AuthDetails => ({
authProxyUrl: 'https://mock-auth-proxy.com',
domain: 'mock-domain.auth0.com',
contextInterface: createMockBasicAuth0Context(),
...overrides,
});

/**
* Creates a mock MyAccountClient service
*/
export const createMockMyAccountApiClient = (): CoreClientInterface['myAccountApiClient'] => {
return {
factors: {
list: vi.fn().mockResolvedValue({ factors: [] }),
},
authenticationMethods: {
list: vi.fn().mockResolvedValue({ authentication_methods: [] }),
create: vi.fn().mockResolvedValue({ id: 'new_method_123', type: 'totp' }),
delete: vi.fn().mockResolvedValue(undefined),
verify: vi.fn().mockResolvedValue({ confirmed: true }),
},
} as unknown as CoreClientInterface['myAccountApiClient'];
};

/**
* Creates a mock MyOrganizationClient service
*/
export const createMockMyOrgApiClient = (): CoreClientInterface['myOrgApiClient'] => {
return {
organizationDetails: {
get: vi.fn().mockResolvedValue({
id: 'org_123',
name: 'Test Organization',
display_name: 'Test Organization',
}),
update: vi.fn().mockResolvedValue({
id: 'org_123',
name: 'Test Organization',
display_name: 'Test Organization',
}),
},
organization: {
identityProviders: {
list: vi.fn().mockResolvedValue([]),
get: vi.fn().mockResolvedValue({
id: 'idp_123',
name: 'Test Provider',
strategy: 'oidc',
}),
create: vi.fn().mockResolvedValue({ id: 'idp_123' }),
update: vi.fn().mockResolvedValue({ id: 'idp_123' }),
delete: vi.fn().mockResolvedValue(undefined),
detach: vi.fn().mockResolvedValue(undefined),
domains: {
create: vi.fn().mockResolvedValue(undefined),
delete: vi.fn().mockResolvedValue(undefined),
},
provisioning: {
get: vi.fn().mockRejectedValue({ status: 404 }),
create: vi.fn().mockResolvedValue({}),
delete: vi.fn().mockResolvedValue(undefined),
},
},
domains: {
list: vi.fn().mockResolvedValue([]),
create: vi.fn().mockResolvedValue({
id: 'domain_123',
domain: 'example.com',
status: 'pending',
}),
update: vi.fn().mockResolvedValue({ id: 'domain_123' }),
delete: vi.fn().mockResolvedValue(undefined),
verify: {
create: vi.fn().mockResolvedValue({ status: 'verified' }),
},
identityProviders: {
get: vi.fn().mockResolvedValue({ identity_providers: [] }),
},
},
configuration: {
get: vi.fn().mockResolvedValue({
allowed_strategies: [
'samlp',
'oidc',
'adfs',
'waad',
'google-apps',
'pingfederate',
'okta',
],
connection_deletion_behavior: 'allow',
}),
identityProviders: {
get: vi.fn().mockResolvedValue({
strategies: {
samlp: {
enabled_features: ['provisioning'],
provisioning_methods: ['scim'],
},
oidc: {
enabled_features: [],
provisioning_methods: [],
},
},
}),
},
},
},
} as unknown as CoreClientInterface['myOrgApiClient'];
};

/**
* Creates a mock CoreClientInterface
*/
export const createMockCoreClient = (authDetails?: Partial<AuthDetails>): CoreClientInterface => {
const mockAuth = createMockAuthDetails(authDetails);
const mockI18nService = createMockI18nService();
const mockMyAccountApiClient = createMockMyAccountApiClient();
const mockMyOrgApiClient = createMockMyOrgApiClient();

return {
auth: mockAuth,
i18nService: mockI18nService,
myAccountApiClient: mockMyAccountApiClient,
myOrgApiClient: mockMyOrgApiClient,
getMyAccountApiClient: vi.fn(
() => mockMyAccountApiClient,
) as CoreClientInterface['getMyAccountApiClient'],
getMyOrgApiClient: vi.fn(() => mockMyOrgApiClient) as CoreClientInterface['getMyOrgApiClient'],
getToken: vi.fn().mockResolvedValue('mock-access-token'),
isProxyMode: vi.fn().mockReturnValue(false),
ensureScopes: vi.fn().mockResolvedValue(undefined),
};
};

/**
* Creates a mock CoreClientInterface in proxy mode
*/
export const createMockProxyCoreClient = (
authDetails?: Partial<AuthDetails>,
): CoreClientInterface => {
const mockCoreClient = createMockCoreClient(authDetails);
mockCoreClient.auth.authProxyUrl = 'https://mock-auth-proxy.com';
mockCoreClient.isProxyMode = vi.fn().mockReturnValue(true);
return mockCoreClient;
};

/**
* Creates a mock unauthenticated CoreClientInterface
*/
export const createMockUnauthenticatedCoreClient = (): CoreClientInterface => {
return createMockCoreClient({
contextInterface: createMockBasicAuth0Context({
isAuthenticated: false,
user: undefined,
}),
});
};
2 changes: 2 additions & 0 deletions packages/core/src/auth/__mocks__/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './core-client.mocks';
export * from './token-manager.mocks';
38 changes: 38 additions & 0 deletions packages/core/src/auth/__mocks__/token-manager.mocks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { vi } from 'vitest';

import type { createTokenManager } from '../token-manager';

/**
* Creates a mock token manager service
*/
export const createMockTokenManager = (
tokenValue: string | undefined = 'mock-access-token',
): ReturnType<typeof createTokenManager> => ({
getToken: vi.fn(async () => tokenValue),
});

export const createMockTokenManagerWithScopes = (
tokenValue: string | undefined = 'mock-access-token',
): ReturnType<typeof createTokenManager> & {
lastScope?: string;
lastAudiencePath?: string;
} => {
const mockManager = {
lastScope: undefined as string | undefined,
lastAudiencePath: undefined as string | undefined,
getToken: vi.fn(async (scope: string, audiencePath: string) => {
mockManager.lastScope = scope;
mockManager.lastAudiencePath = audiencePath;
return tokenValue;
}),
};
return mockManager;
};

export const createMockTokenManagerWithError = (
error: Error = new Error('Token retrieval failed'),
): ReturnType<typeof createTokenManager> => ({
getToken: async () => {
throw error;
},
});
25 changes: 25 additions & 0 deletions packages/core/src/auth/__tests__/auth-utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { describe, expect, it } from 'vitest';

import { AuthUtils } from '../auth-utils';

describe('auth-utils', () => {
describe.each([
{
domain: 'https://example.auth0.com',
expected: 'https://example.auth0.com/',
},
{
domain: 'example.auth0.com',
expected: 'https://example.auth0.com/',
},
{
domain: 'http://localhost:3000',
expected: 'http://localhost:3000/',
},
])('toURL with domain', ({ domain, expected }) => {
it('should convert to the expected URL format', () => {
const result = AuthUtils.toURL(domain);
expect(result).toBe(expected);
});
});
});
Loading
Loading