diff --git a/ui/src/Pages/LoginPage/InitialSetupPage.test.tsx b/ui/src/Pages/LoginPage/InitialSetupPage.test.tsx new file mode 100644 index 00000000..e1a6f226 --- /dev/null +++ b/ui/src/Pages/LoginPage/InitialSetupPage.test.tsx @@ -0,0 +1,77 @@ +import React from 'react' +import { MockedProvider } from '@apollo/client/testing' +import { render, screen, waitFor } from '@testing-library/react' +import { unstable_HistoryRouter as HistoryRouter } from 'react-router-dom' +import { createMemoryHistory } from 'history' +import * as authentication from '../../helpers/authentication' +import InitialSetupPage from './InitialSetupPage' +import { mockInitialSetupGraphql } from './loginTestHelpers' + +jest.mock('../../helpers/authentication.ts') + +const authToken = authentication.authToken as jest.Mock< + ReturnType +> + +describe('Initial setup page', () => { + test('Render initial setup form', async () => { + authToken.mockImplementation(() => null) + + const history = createMemoryHistory({ + initialEntries: ['/initialSetup'], + }) + + render( + + + + + + ) + + expect(screen.getByLabelText('Username')).toBeInTheDocument() + expect(screen.getByLabelText('Password')).toBeInTheDocument() + expect(screen.getByLabelText('Photo path')).toBeInTheDocument() + expect(screen.getByDisplayValue('Setup Photoview')).toBeInTheDocument() + }) + + test('Redirect if auth token is present', async () => { + authToken.mockImplementation(() => 'some-token') + + const history = createMemoryHistory({ + initialEntries: ['/initialSetup'], + }) + + render( + + + + + + ) + + await waitFor(() => { + expect(history.location.pathname).toBe('/') + }) + }) + + test('Redirect if not initial setup', async () => { + authToken.mockImplementation(() => null) + + const history = createMemoryHistory({ + initialEntries: ['/initialSetup'], + }) + + render( + + + + + + ) + + await waitFor(() => { + expect(history.location.pathname).toBe('/') + }) + }) +}) diff --git a/ui/src/Pages/LoginPage/InitialSetupPage.tsx b/ui/src/Pages/LoginPage/InitialSetupPage.tsx index 80b10c3c..b0b1722a 100644 --- a/ui/src/Pages/LoginPage/InitialSetupPage.tsx +++ b/ui/src/Pages/LoginPage/InitialSetupPage.tsx @@ -1,9 +1,9 @@ -import React from 'react' +import React, { useEffect } from 'react' import { gql, useQuery, useMutation } from '@apollo/client' import { useNavigate } from 'react-router-dom' import { Container } from './loginUtilities' -import { checkInitialSetupQuery, login } from './loginUtilities' +import { INITIAL_SETUP_QUERY, login } from './loginUtilities' import { authToken } from '../../helpers/authentication' import { useTranslation } from 'react-i18next' import { CheckInitialSetup } from './__generated__/CheckInitialSetup' @@ -45,19 +45,18 @@ const InitialSetupPage = () => { formState: { errors: formErrors }, } = useForm() - if (authToken()) { - navigate('/') - return null - } + useEffect(() => { + if (authToken()) navigate('/') + }, []) - const { data: initialSetupData } = useQuery( - checkInitialSetupQuery - ) + const { data: initialSetupData } = + useQuery(INITIAL_SETUP_QUERY) - if (initialSetupData?.siteInfo?.initialSetup) { - navigate('/') - return null - } + const notInitialSetup = initialSetupData?.siteInfo?.initialSetup === false + + useEffect(() => { + if (notInitialSetup) navigate('/') + }, [notInitialSetup]) const [authorize, { loading: authorizeLoading, data: authorizationData }] = useMutation(initialSetupMutation, { @@ -80,6 +79,10 @@ const InitialSetupPage = () => { }) }) + if (authToken() || notInitialSetup) { + return null + } + let errorMessage = null if (authorizationData && !authorizationData.initialSetupWizard.success) { errorMessage = authorizationData.initialSetupWizard.status diff --git a/ui/src/Pages/LoginPage/LoginPage.test.tsx b/ui/src/Pages/LoginPage/LoginPage.test.tsx new file mode 100644 index 00000000..1b4bfdeb --- /dev/null +++ b/ui/src/Pages/LoginPage/LoginPage.test.tsx @@ -0,0 +1,78 @@ +import { render, screen, waitFor } from '@testing-library/react' +import React from 'react' +import LoginPage from './LoginPage' +import * as authentication from '../../helpers/authentication' +import { unstable_HistoryRouter as HistoryRouter } from 'react-router-dom' +import { createMemoryHistory } from 'history' +import { MockedProvider } from '@apollo/client/testing' +import { mockInitialSetupGraphql } from './loginTestHelpers' + +jest.mock('../../helpers/authentication.ts') + +const authToken = authentication.authToken as jest.Mock< + ReturnType +> + +describe('Login page redirects', () => { + test('Auth token redirect', async () => { + authToken.mockImplementation(() => 'some-token') + + const history = createMemoryHistory({ + initialEntries: ['/login'], + }) + + render( + + + + + + ) + + await waitFor(() => { + expect(history.location.pathname).toBe('/') + }) + }) + + test('Initial setup redirect', async () => { + authToken.mockImplementation(() => null) + + const history = createMemoryHistory({ + initialEntries: ['/login'], + }) + + render( + + + + + + ) + + await waitFor(() => { + expect(history.location.pathname).toBe('/initialSetup') + }) + }) +}) + +describe('Login page', () => { + test('Render login form', async () => { + authToken.mockImplementation(() => null) + + const history = createMemoryHistory({ + initialEntries: ['/login'], + }) + + render( + + + + + + ) + + expect(screen.getByLabelText('Username')).toBeInTheDocument() + expect(screen.getByLabelText('Password')).toBeInTheDocument() + expect(screen.getByDisplayValue('Sign in')).toBeInTheDocument() + }) +}) diff --git a/ui/src/Pages/LoginPage/LoginPage.tsx b/ui/src/Pages/LoginPage/LoginPage.tsx index 2af22abe..485a5105 100644 --- a/ui/src/Pages/LoginPage/LoginPage.tsx +++ b/ui/src/Pages/LoginPage/LoginPage.tsx @@ -1,7 +1,7 @@ -import React from 'react' +import React, { useEffect } from 'react' import { useQuery, gql, useMutation } from '@apollo/client' import { useForm } from 'react-hook-form' -import { checkInitialSetupQuery, login } from './loginUtilities' +import { INITIAL_SETUP_QUERY, login } from './loginUtilities' import { authToken } from '../../helpers/authentication' import { useTranslation } from 'react-i18next' @@ -69,8 +69,6 @@ const LoginForm = () => { }) } - console.log('errors', formErrors) - const errorMessage = data && !data.authorizeUser.success ? data.authorizeUser.status : null @@ -130,16 +128,19 @@ const LoginPage = () => { const navigate = useNavigate() const { data: initialSetupData } = useQuery( - checkInitialSetupQuery + INITIAL_SETUP_QUERY, + { variables: {} } ) - if (authToken()) { - navigate('/') - return null - } + useEffect(() => { + if (authToken()) navigate('/') + }, []) - if (initialSetupData?.siteInfo?.initialSetup) { - navigate('initialSetup') + useEffect(() => { + if (initialSetupData?.siteInfo?.initialSetup) navigate('/initialSetup') + }, [initialSetupData?.siteInfo?.initialSetup]) + + if (authToken() || initialSetupData?.siteInfo?.initialSetup) { return null } diff --git a/ui/src/Pages/LoginPage/loginTestHelpers.ts b/ui/src/Pages/LoginPage/loginTestHelpers.ts new file mode 100644 index 00000000..cde4ecfb --- /dev/null +++ b/ui/src/Pages/LoginPage/loginTestHelpers.ts @@ -0,0 +1,15 @@ +import { INITIAL_SETUP_QUERY } from './loginUtilities' + +export const mockInitialSetupGraphql = (initial: boolean) => ({ + request: { + query: INITIAL_SETUP_QUERY, + variables: {}, + }, + result: { + data: { + siteInfo: { + initialSetup: initial, + }, + }, + }, +}) diff --git a/ui/src/Pages/LoginPage/loginUtilities.tsx b/ui/src/Pages/LoginPage/loginUtilities.tsx index f27397f1..4f754032 100644 --- a/ui/src/Pages/LoginPage/loginUtilities.tsx +++ b/ui/src/Pages/LoginPage/loginUtilities.tsx @@ -2,7 +2,7 @@ import { gql } from '@apollo/client' import { saveTokenCookie } from '../../helpers/authentication' import styled from 'styled-components' -export const checkInitialSetupQuery = gql` +export const INITIAL_SETUP_QUERY = gql` query CheckInitialSetup { siteInfo { initialSetup