Skip to content
Open
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
87 changes: 84 additions & 3 deletions __tests__/use-enterprise-connect.test.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import React, { useEffect } from 'react';
import { renderHook, waitFor } from '@testing-library/react';
import {
isFederatedDomain as spaIsFederatedDomain,
Auth0Client,
} from '@auth0/auth0-spa-js';
import useEnterpriseConnect from '../src/use-enterprise-connect';
import { Auth0ContextInterface, initialContext } from '../src/auth0-context';
import { createWrapper } from './helpers';

jest.mock('@auth0/auth0-spa-js');
Expand All @@ -20,6 +22,87 @@ describe('useEnterpriseConnect', () => {
});
});

it('should keep the result stable when the provider initializes or the consumer re-renders', async () => {
const effect = jest.fn();
const { result, rerender } = renderHook(
() => {
const enterpriseConnect = useEnterpriseConnect();
useEffect(effect, [enterpriseConnect]);
return enterpriseConnect;
},
{ wrapper: createWrapper() }
);
const initial = result.current;

await waitFor(() => expect(clientMock.getUser).toHaveBeenCalled());
for (let i = 0; i < 3; i++) {
rerender();
}

expect(effect).toHaveBeenCalledTimes(1);
expect(result.current).toBe(initial);
});

it.each(['getConfiguration', 'loginWithRedirect'] as const)(
'should update the result when %s changes in a custom context',
async (method) => {
const getConfiguration = jest.fn(() => ({
domain: 'first.example.com',
clientId: '__test_client_id__',
}));
const loginWithRedirect = jest.fn();
let contextValue: Auth0ContextInterface = {
...initialContext,
getConfiguration,
loginWithRedirect,
};
const context =
React.createContext<Auth0ContextInterface>(initialContext);
const wrapper = ({ children }: React.PropsWithChildren) => (
<context.Provider value={contextValue}>{children}</context.Provider>
);
const { result, rerender } = renderHook(
() => useEnterpriseConnect(context),
{ wrapper }
);
const initial = result.current;
const nextGetConfiguration = jest.fn(() => ({
domain: 'second.example.com',
clientId: '__test_client_id__',
}));
const nextLoginWithRedirect = jest.fn();

contextValue =
method === 'getConfiguration'
? { ...contextValue, getConfiguration: nextGetConfiguration }
: { ...contextValue, loginWithRedirect: nextLoginWithRedirect };
rerender();

expect(result.current).not.toBe(initial);
expect(
result.current.isFederatedDomain === initial.isFederatedDomain
).toBe(method !== 'getConfiguration');
expect(result.current.loginWithSSO === initial.loginWithSSO).toBe(
method !== 'loginWithRedirect'
);

await result.current.isFederatedDomain('acme.com');
expect(federatedMock).toHaveBeenCalledWith(
contextValue.getConfiguration().domain,
'acme.com',
undefined
);
await result.current.loginWithSSO('jane@acme.com');
expect(contextValue.loginWithRedirect).toHaveBeenCalledWith({
authorizationParams: { login_hint: 'jane@acme.com' },
});

const updated = result.current;
rerender();
expect(result.current).toBe(updated);
}
);

it('calls isFederatedDomain with the configured domain and email domain', async () => {
federatedMock.mockResolvedValueOnce(true);
const wrapper = createWrapper();
Expand Down Expand Up @@ -51,9 +134,7 @@ describe('useEnterpriseConnect', () => {
it('loginWithSSO calls loginWithRedirect with login_hint set from the email', async () => {
const wrapper = createWrapper();
const { result } = renderHook(() => useEnterpriseConnect(), { wrapper });
await waitFor(() =>
expect(clientMock.loginWithRedirect).not.toBeNull()
);
await waitFor(() => expect(clientMock.loginWithRedirect).not.toBeNull());

await result.current.loginWithSSO('jane@acme.com');

Expand Down
11 changes: 6 additions & 5 deletions src/use-enterprise-connect.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useContext } from 'react';
import { useCallback, useContext, useMemo } from 'react';
import {
isFederatedDomain as spaIsFederatedDomain,
IsFederatedDomainOptions,
Expand Down Expand Up @@ -43,9 +43,7 @@ export interface UseEnterpriseConnect {
* only the email domain. `loginWithSSO` is sugar over `loginWithRedirect`
* that sets `login_hint` to the provided email.
*/
const useEnterpriseConnect = (
context = Auth0Context
): UseEnterpriseConnect => {
const useEnterpriseConnect = (context = Auth0Context): UseEnterpriseConnect => {
const { getConfiguration, loginWithRedirect } = useContext(
context
) as Auth0ContextInterface;
Expand All @@ -69,7 +67,10 @@ const useEnterpriseConnect = (
[loginWithRedirect]
);

return { isFederatedDomain, loginWithSSO };
return useMemo(
() => ({ isFederatedDomain, loginWithSSO }),
[isFederatedDomain, loginWithSSO]
);
};

export default useEnterpriseConnect;