import * as React from 'react'; import expect from 'expect'; import { waitFor, render, screen } from '@testing-library/react'; import { QueryClient } from '@tanstack/react-query'; import { NoAuthProvider, NoAuthProviderGetPermissions, WithAuthProviderAndGetPermissions, } from './usePermissions.stories'; import { AuthProvider } from '../types'; describe('usePermissions', () => { it('should return a loading state on mount with an authProvider that supports permissions', async () => { let resolveGetPermissions; const authProvider = { login: () => Promise.reject('bad method'), logout: () => Promise.reject('bad method'), checkAuth: () => Promise.reject('bad method'), checkError: () => Promise.reject('bad method'), getPermissions: () => { return new Promise(resolve => { resolveGetPermissions = resolve; }); }, }; render( ); expect(screen.queryByText('LOADING')).not.toBeNull(); expect(screen.queryByText('PERMISSIONS: ')).toBeNull(); resolveGetPermissions('admin'); await screen.findByText('PERMISSIONS: admin'); }); it('should return immediately without an authProvider', async () => { render(); expect(screen.queryByText('LOADING')).toBeNull(); expect(screen.queryByText('PERMISSIONS: ')).toBeNull(); }); it('should return immediately without an authProvider that supports permissions', async () => { render(); expect(screen.queryByText('LOADING')).toBeNull(); expect(screen.queryByText('PERMISSIONS: ')).toBeNull(); }); it('should return the permissions after a tick', async () => { const authProvider = { login: () => Promise.reject('bad method'), logout: () => Promise.reject('bad method'), checkAuth: () => Promise.reject('bad method'), checkError: () => Promise.reject('bad method'), getPermissions: () => Promise.resolve('admin'), }; render( ); await screen.findByText('PERMISSIONS: admin'); expect(screen.queryByText('LOADING')).toBeNull(); }); it('should return an error after a tick if the auth.getPermissions call fails and checkError resolves', async () => { const authProvider = { login: () => Promise.reject('bad method'), logout: () => Promise.reject('bad method'), checkAuth: () => Promise.reject('bad method'), checkError: () => Promise.resolve(), getPermissions: () => Promise.reject('not good'), }; render( ); await screen.findByText('ERROR'); expect(screen.queryByText('LOADING')).toBeNull(); }); it('should call logout when the auth.getPermissions call fails and checkError rejects', async () => { const authProvider = { login: () => Promise.reject('bad method'), logout: jest.fn(() => Promise.resolve()), checkAuth: () => Promise.reject('bad method'), checkError: () => Promise.reject(), getPermissions: () => Promise.reject('not good'), }; render( ); await waitFor(() => { expect(screen.queryByText('LOADING')).toBeNull(); }); expect(authProvider.logout).toHaveBeenCalled(); }); it('should abort the request if the query is canceled', async () => { const abort = jest.fn(); const authProvider: AuthProvider = { login: () => Promise.reject('bad method'), logout: jest.fn(() => Promise.resolve()), checkAuth: () => Promise.reject('bad method'), checkError: () => Promise.reject(), getPermissions: jest.fn( ({ signal }) => new Promise(() => { signal.addEventListener('abort', () => { abort(signal.reason); }); }) ), }; const queryClient = new QueryClient(); render( ); await waitFor(() => { expect(authProvider.getPermissions).toHaveBeenCalled(); }); queryClient.cancelQueries({ queryKey: ['auth', 'getPermissions'], }); await waitFor(() => { expect(abort).toHaveBeenCalled(); }); }); });