diff --git a/frontend/app/components/auth/auth.spec.tsx b/frontend/app/components/auth/auth.spec.tsx index 7f76b47403..5a2d205eeb 100644 --- a/frontend/app/components/auth/auth.spec.tsx +++ b/frontend/app/components/auth/auth.spec.tsx @@ -2,12 +2,13 @@ import '@testing-library/jest-dom'; import { h } from 'preact'; import { fireEvent, render, waitFor } from '@testing-library/preact'; -import { Provider, User } from 'common/types'; +import { OAuthProvider, User } from 'common/types'; import { StaticStore } from 'common/static-store'; import Auth from './auth'; import * as utils from './auth.utils'; import * as api from './auth.api'; +import { getProviderData } from './components/oauth.utils'; jest.mock('react-redux', () => ({ useDispatch: () => jest.fn(), @@ -31,23 +32,23 @@ describe('', () => { }); it('should close dropdown by click on button', () => { - const { container } = render(); + const { container, getByText } = render(); expect(container.querySelector('.auth-dropdown')).not.toBeInTheDocument(); - fireEvent.click(container.querySelector('.auth-button')!); + fireEvent.click(getByText('Sign In')); expect(container.querySelector('.auth-dropdown')).toBeInTheDocument(); - fireEvent.click(container.querySelector('.auth-button')!); + fireEvent.click(getByText('Sign In')); expect(container.querySelector('.auth-dropdown')).not.toBeInTheDocument(); }); it('should close dropdown by click outside of it', () => { - const { container } = render(); + const { container, getByText } = render(); expect(container.querySelector('.auth-dropdown')).not.toBeInTheDocument(); - fireEvent.click(container.querySelector('.auth-button')!); + fireEvent.click(getByText('Sign In')); expect(container.querySelector('.auth-dropdown')).toBeInTheDocument(); fireEvent.click(document); @@ -55,11 +56,11 @@ describe('', () => { }); it('should close dropdown by message from parent', async () => { - const { container } = render(); + const { container, getByText } = render(); expect(container.querySelector('.auth-dropdown')).not.toBeInTheDocument(); - fireEvent.click(container.querySelector('.auth-button')!); + fireEvent.click(getByText('Sign In')); expect(container.querySelector('.auth-dropdown')).toBeInTheDocument(); window.postMessage('{"clickOutside": true}', '*'); @@ -74,61 +75,66 @@ describe('', () => { [['facebook', 'google', 'microsoft']], [['facebook', 'google', 'microsoft', 'yandex']], [['facebook', 'google', 'microsoft', 'yandex', 'twitter']], - ] as [Provider[]][])('should renders with %j providers', (providers) => { + ] as [OAuthProvider[]][])('should renders with %j providers', async (providers) => { StaticStore.config.auth_providers = providers; - const { container } = render(); + const { container, getByText, getByTitle, queryByPlaceholderText, queryByText } = render(); - expect(container.querySelector('.auth-dropdown')).toBeNull(); + expect(container.querySelector('.auth-dropdown')).not.toBeInTheDocument(); - fireEvent.click(container.querySelector('.auth-button')!); + expect(getByText('Sign In')).toHaveClass('auth-button'); + fireEvent.click(getByText('Sign In')); expect(container.querySelector('.auth-dropdown')).toBeInTheDocument(); - expect(container.querySelectorAll('.oauth-button')).toHaveLength(providers.length); - expect(container.querySelector('[name="username"]')).not.toBeInTheDocument(); - expect(container.querySelector('.auth-submit')).not.toBeInTheDocument(); + providers.forEach((p) => { + const { name } = getProviderData(p, 'light'); + expect(getByTitle(`Sign In with ${name}`)).toBeInTheDocument(); + }); + expect(queryByPlaceholderText('Username')).not.toBeInTheDocument(); + expect(queryByText('Submit')).not.toBeInTheDocument(); }); it('should render email provider', () => { StaticStore.config.auth_providers = ['email']; - const { container } = render(); + const { getByText, getByPlaceholderText } = render(); - fireEvent.click(container.querySelector('.auth-button')!); - expect(container.querySelector('.auth-dropdown')).toBeInTheDocument(); - expect(container.querySelector('.auth-form-title')?.innerHTML).toContain('email'); - expect(container.querySelector('[name="username"]')).toBeInTheDocument(); - expect(container.querySelector('[name="email"]')).toBeInTheDocument(); - expect(container.querySelector('.auth-submit')).toBeInTheDocument(); + fireEvent.click(getByText('Sign In')); + expect(getByText('email')).toHaveClass('auth-form-title'); + expect(getByPlaceholderText('Username')).toHaveClass('auth-input-username'); + expect(getByPlaceholderText('Email Address')).toHaveClass('auth-input-email'); + expect(getByText('Submit')).toHaveClass('auth-submit'); }); it('should render anonymous provider', () => { StaticStore.config.auth_providers = ['anonymous']; - const { container } = render(); + const { getByText, getByPlaceholderText } = render(); - fireEvent.click(container.querySelector('.auth-button')!); - expect(container.querySelector('.auth-dropdown')).toBeInTheDocument(); - expect(container.querySelector('.auth-form-title')?.innerHTML).toContain('anonymous'); - expect(container.querySelector('[name="username"]')).toBeInTheDocument(); - expect(container.querySelector('.auth-submit')).toBeInTheDocument(); + fireEvent.click(getByText('Sign In')); + expect(getByText('anonymous')).toHaveClass('auth-form-title'); + expect(getByPlaceholderText('Username')).toHaveClass('auth-input-username'); + expect(getByText('Submit')).toHaveClass('auth-submit'); }); it('should render tabs with two form providers', () => { StaticStore.config.auth_providers = ['email', 'anonymous']; - const { container } = render(); - - fireEvent.click(container.querySelector('.auth-button')!); - expect(container.querySelector('.auth-dropdown')).toBeInTheDocument(); - expect(container.querySelector('[for="form-provider-anonymous"]')).toBeInTheDocument(); - expect(container.querySelector('[for="form-provider-email"]')).toBeInTheDocument(); - expect(container.querySelector('[name="username"]')).toBeInTheDocument(); - expect(container.querySelector('.auth-submit')).toBeInTheDocument(); - - fireEvent.click(container.querySelector('[for="form-provider-email"]')!); - expect(container.querySelector('[name="username"]')).toBeInTheDocument(); - expect(container.querySelector('[name="email"]')).toBeInTheDocument(); - expect(container.querySelector('.auth-submit')).toBeInTheDocument(); + const { getByText, getByLabelText, getByPlaceholderText, getByDisplayValue } = render(); + + fireEvent.click(getByText('Sign In')); + expect(getByDisplayValue('email')).toHaveAttribute('id', 'form-provider-email'); + expect(getByText('email')).toHaveAttribute('for', 'form-provider-email'); + expect(getByText('email')).toHaveClass('auth-tabs-item'); + expect(getByDisplayValue('anonymous')).toHaveAttribute('id', 'form-provider-anonymous'); + expect(getByText('anonym')).toHaveAttribute('for', 'form-provider-anonymous'); + expect(getByText('anonym')).toHaveClass('auth-tabs-item'); + expect(getByPlaceholderText('Username')).toHaveClass('auth-input-username'); + expect(getByText('Submit')).toHaveClass('auth-submit'); + + fireEvent.click(getByLabelText('email')); + expect(getByPlaceholderText('Username')).toHaveClass('auth-input-username'); + expect(getByPlaceholderText('Email Address')).toHaveClass('auth-input-email'); + expect(getByText('Submit')).toHaveClass('auth-submit'); }); it('should send email and then verify forms', async () => { @@ -137,27 +143,28 @@ describe('', () => { jest.spyOn(api, 'verifyEmailSignin').mockImplementationOnce(async () => ({} as User)); jest.spyOn(utils, 'getTokenInvalidReason').mockImplementationOnce(() => null); - const { container } = render(); + const { getByText, getByPlaceholderText, getByTitle, getByRole } = render(); - fireEvent.click(container.querySelector('.auth-button')!); - fireEvent.change(container.querySelector('[name="username"]')!, { target: { value: 'username' } }); - fireEvent.change(container.querySelector('[name="email"]')!, { + fireEvent.click(getByText('Sign In')); + fireEvent.change(getByPlaceholderText('Username'), { target: { value: 'username' } }); + fireEvent.change(getByPlaceholderText('Email Address'), { target: { value: 'email@email.com' }, }); - fireEvent.click(container.querySelector('.auth-submit')!); + fireEvent.click(getByText('Submit')); - expect(container.querySelector('.spinner')).toBeInTheDocument(); + expect(getByRole('presentation')).toHaveClass('spinner'); await waitFor(() => expect(api.emailSignin).toBeCalled()); expect(api.emailSignin).toBeCalledWith('email@email.com', 'username'); - expect(container.querySelector('.auth-back-button')).toBeInTheDocument(); - expect(container.querySelector('.auth-close-button')).toBeInTheDocument(); - expect(container.querySelector('[name="token"]')).toBeInTheDocument(); + expect(getByText('Back')).toHaveClass('auth-back-button'); + expect(getByTitle('Close sign-in dropdown')).toHaveClass('auth-close-button'); + expect(getByPlaceholderText('Token')).toHaveClass('auth-token-textatea'); - fireEvent.change(container.querySelector('[name="token"]')!, { + fireEvent.change(getByPlaceholderText('Token'), { target: { value: 'token' }, }); - fireEvent.click(container.querySelector('.auth-submit')!); + + fireEvent.click(getByText('Submit')); await waitFor(() => expect(api.verifyEmailSignin).toBeCalled()); expect(api.verifyEmailSignin).toBeCalledWith('token'); @@ -167,43 +174,41 @@ describe('', () => { StaticStore.config.auth_providers = ['email']; jest.spyOn(api, 'emailSignin').mockImplementationOnce(async () => null); - const { container, getByText } = render(); + const { getByText, getByTitle, getByPlaceholderText } = render(); - fireEvent.click(container.querySelector('.auth-button')!); - - fireEvent.change(container.querySelector('[name="username"]')!, { target: { value: 'username' } }); - fireEvent.change(container.querySelector('[name="email"]')!, { + fireEvent.click(getByText('Sign In')); + fireEvent.change(getByPlaceholderText('Username'), { target: { value: 'username' } }); + fireEvent.change(getByPlaceholderText('Email Address'), { target: { value: 'email@email.com' }, }); - fireEvent.click(container.querySelector('.auth-submit')!); + fireEvent.click(getByText('Submit')); await waitFor(() => expect(api.emailSignin).toBeCalled()); - expect(container.querySelector('.auth-back-button')).toBeInTheDocument(); - expect(container.querySelector('.auth-close-button')).toBeInTheDocument(); - expect(container.querySelector('[name="token"]')).toBeInTheDocument(); + expect(getByText('Back')).toHaveClass('auth-back-button'); + expect(getByTitle('Close sign-in dropdown')).toHaveClass('auth-close-button'); + expect(getByPlaceholderText('Token')).toHaveClass('auth-token-textatea'); - fireEvent.change(container.querySelector('[name="token"]')!, { - target: { value: 'token' }, - }); - fireEvent.click(container.querySelector('.auth-submit')!); + fireEvent.change(getByPlaceholderText('Token'), { target: { value: 'token' } }); + fireEvent.click(getByText('Submit')); await waitFor(() => expect(utils.getTokenInvalidReason).toBeCalled()); expect(utils.getTokenInvalidReason).toBeCalledWith('token'); await waitFor(() => expect(getByText('Token is invalid')).toBeInTheDocument()); - expect(getByText('Token is invalid').getAttribute('class')).toContain('auth-error'); + expect(getByText('Token is invalid')).toHaveClass('auth-error'); }); it('should send anonym form', async () => { StaticStore.config.auth_providers = ['anonymous']; jest.spyOn(api, 'anonymousSignin').mockImplementationOnce(async () => ({} as User)); - const { container } = render(); + const { getByText, getByPlaceholderText, getByRole } = render(); - fireEvent.click(container.querySelector('.auth-button')!); - fireEvent.change(container.querySelector('[name="username"]')!, { target: { value: 'username' } }); - fireEvent.click(container.querySelector('.auth-submit')!); - expect(container.querySelector('.spinner')).toBeInTheDocument(); + fireEvent.click(getByText('Sign In')); + fireEvent.change(getByPlaceholderText('Username'), { target: { value: 'username' } }); + fireEvent.click(getByText('Submit')); + expect(getByRole('presentation')).toHaveClass('spinner'); + expect(getByRole('presentation')).toHaveAttribute('aria-label', 'Loading...'); await waitFor(() => expect(api.anonymousSignin).toBeCalled()); }); });