import * as React from 'react';
import { useState, useEffect } from 'react';
import expect from 'expect';
import { screen, render, waitFor } from '@testing-library/react';
import { unstable_HistoryRouter as HistoryRouter } from 'react-router-dom';
import { QueryClientProvider, QueryClient } from 'react-query';
import { createMemoryHistory } from 'history';
import { useCheckAuth } from './useCheckAuth';
import AuthContext from './AuthContext';
import { BasenameContextProvider } from '../routing';
import { useNotify } from '../notification/useNotify';
import { AuthProvider } from '../types';
jest.mock('../notification/useNotify');
const notify = jest.fn();
useNotify.mockImplementation(() => notify);
const TestComponent = ({
params,
logoutOnFailure,
redirectTo,
disableNotification,
}: {
params?: any;
logoutOnFailure?: boolean;
redirectTo?: string;
disableNotification?: boolean;
}) => {
const [authenticated, setAuthenticated] = useState(true);
const checkAuth = useCheckAuth();
useEffect(() => {
checkAuth(params, logoutOnFailure, redirectTo, disableNotification)
.then(() => setAuthenticated(true))
.catch(error => setAuthenticated(false));
}, [params, logoutOnFailure, redirectTo, disableNotification, checkAuth]);
return
{authenticated ? 'authenticated' : 'not authenticated'}
;
};
const authProvider: AuthProvider = {
login: () => Promise.reject('bad method'),
logout: () => {
return Promise.resolve();
},
checkAuth: params => (params.token ? Promise.resolve() : Promise.reject()),
checkError: params => {
if (params instanceof Error && params.message === 'denied') {
return Promise.reject(new Error('logout'));
}
return Promise.resolve();
},
getPermissions: () => Promise.reject('not authenticated'),
};
const queryClient = new QueryClient();
describe('useCheckAuth', () => {
afterEach(() => {
notify.mockClear();
});
it('should not logout if user is authenticated', async () => {
const history = createMemoryHistory({ initialEntries: ['/'] });
render(
);
await waitFor(() => {
expect(notify).toHaveBeenCalledTimes(0);
expect(screen.queryByText('authenticated')).not.toBeNull();
expect(history.location.pathname).toBe('/');
});
});
it('should logout if user is not authenticated', async () => {
const history = createMemoryHistory({ initialEntries: ['/'] });
render(
);
await waitFor(() => {
expect(notify).toHaveBeenCalledTimes(1);
expect(screen.queryByText('authenticated')).toBeNull();
expect(history.location.pathname).toBe('/login');
});
});
it('should not logout if has no credentials and passed logoutOnFailure as false', async () => {
const history = createMemoryHistory({ initialEntries: ['/'] });
render(
);
await waitFor(() => {
expect(notify).toHaveBeenCalledTimes(0);
expect(screen.queryByText('not authenticated')).not.toBeNull();
expect(history.location.pathname).toBe('/');
});
});
it('should logout without showing a notification when disableNotification is true', async () => {
const history = createMemoryHistory({ initialEntries: ['/'] });
render(
);
await waitFor(() => {
expect(notify).toHaveBeenCalledTimes(0);
expect(screen.queryByText('authenticated')).toBeNull();
expect(history.location.pathname).toBe('/login');
});
});
it('should logout without showing a notification when authProvider returns error with message false', async () => {
const history = createMemoryHistory({ initialEntries: ['/'] });
render(
Promise.reject({ message: false }),
}}
>
);
await waitFor(() => {
expect(notify).toHaveBeenCalledTimes(0);
expect(screen.queryByText('authenticated')).toBeNull();
expect(history.location.pathname).toBe('/login');
});
});
it('should take basename into account when redirecting to login', async () => {
const history = createMemoryHistory({ initialEntries: ['/foo'] });
render(
);
await waitFor(() => {
expect(notify).toHaveBeenCalledTimes(1);
expect(screen.queryByText('authenticated')).toBeNull();
expect(history.location.pathname).toBe('/foo/login');
});
});
});