Skip to content

Commit

Permalink
add back in refactored tests
Browse files Browse the repository at this point in the history
  • Loading branch information
dauglyon committed Dec 6, 2024
1 parent 6a2bcfe commit 8af0e80
Show file tree
Hide file tree
Showing 6 changed files with 538 additions and 3 deletions.
48 changes: 48 additions & 0 deletions src/features/login/LogInContinue.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -245,4 +245,52 @@ describe('Login Continue', () => {
expect(Login).toHaveBeenCalled();
});
});

it('handles new user signup flow', async () => {
// getLoginChoice - return create data instead of login data
fetchMock.mockResponseOnce(
JSON.stringify({
login: [],
create: [
{
id: 'newuserid',
provider: 'google',
username: '[email protected]',
},
],
})
);

const Signup = jest.fn(() => <></>);
const store = createTestStore();
render(
<Provider store={store}>
<ThemeProvider theme={theme}>
<MemoryRouter initialEntries={['/login/continue']}>
<Routes>
<Route path={'/login/continue'} element={<LogInContinue />} />
<Route path={'/signup/2'} Component={Signup} />
</Routes>
</MemoryRouter>
</ThemeProvider>
</Provider>
);

await waitFor(() => {
// Check that login data was set in store
expect(store.getState().signup.loginData).toEqual({
login: [],
create: [
{
id: 'newuserid',
provider: 'google',
username: '[email protected]',
},
],
});
});
await waitFor(() => {
expect(window.location.pathname === '/signup/2');
});
});
});
145 changes: 145 additions & 0 deletions src/features/signup/AccountInformation.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import { render, screen, fireEvent } from '@testing-library/react';
import { AccountInformation } from './AccountInformation';
import { Provider } from 'react-redux';
import { BrowserRouter } from 'react-router-dom';
import * as authService from '../../common/api/authService';
import { createTestStore } from '../../app/store';

jest.mock('react-hot-toast');
jest.mock('../../common/api/authService');
const mockNavigate = jest.fn();
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useNavigate: () => mockNavigate,
}));

const createMockStore = () => {
return createTestStore({
signup: {
loginData: {
provider: 'Google',
creationallowed: true,
expires: 0,
login: [],
create: [
{
provemail: '[email protected]',
availablename: 'testName',
id: 'someid',
provfullname: 'Myfull Name',
provusername: 'someUsername',
},
],
},
account: {
username: 'testuser',
email: '[email protected]',
display: 'Test User',
policyids: [],
},
},
});
};

const renderWithProviders = (
ui: React.ReactElement,
{ store = createMockStore() } = {}
) => {
return render(
<Provider store={store}>
<BrowserRouter>{ui}</BrowserRouter>
</Provider>
);
};

describe('AccountInformation', () => {
beforeEach(() => {
(authService.loginUsernameSuggest.useQuery as jest.Mock).mockReturnValue({
currentData: { availablename: 'testuser' },
isFetching: false,
});
});

it('renders the form with initial values', () => {
renderWithProviders(<AccountInformation />);

expect(screen.getByText('Create a new KBase Account')).toBeInTheDocument();
expect(screen.getByLabelText('Full Name')).toBeInTheDocument();
expect(screen.getByLabelText('Email')).toBeInTheDocument();
expect(screen.getByLabelText('KBase Username')).toBeInTheDocument();
expect(screen.getByLabelText('Organization')).toBeInTheDocument();
expect(screen.getByLabelText('Department')).toBeInTheDocument();
});

it('displays login provider information', () => {
renderWithProviders(<AccountInformation />);

expect(
screen.getByText(/You have signed in with your/)
).toBeInTheDocument();
expect(screen.getByText('Google')).toBeInTheDocument();
expect(screen.getByText('[email protected]')).toBeInTheDocument();
});

it('validates username availability', async () => {
renderWithProviders(<AccountInformation />);

const usernameInput = screen.getByLabelText('KBase Username');
fireEvent.change(usernameInput, { target: { value: 'sh' } });

expect(screen.getByText('Username is too short.')).toBeInTheDocument();

(authService.loginUsernameSuggest.useQuery as jest.Mock).mockReturnValue({
currentData: { availablename: 'testuser2' },
isFetching: false,
});

fireEvent.change(usernameInput, { target: { value: 'takenname' } });
expect(screen.getByText(/Username is not available/)).toBeInTheDocument();
});

it('handles form submission', async () => {
renderWithProviders(<AccountInformation />);

fireEvent.change(screen.getByLabelText('Organization'), {
target: { value: 'Test Org' },
});
fireEvent.change(screen.getByLabelText('Department'), {
target: { value: 'Test Dept' },
});

fireEvent.click(screen.getByText('Continue to use policies'));

expect(mockNavigate).toHaveBeenCalledWith('/signup/3');
});

it('handles optional text input for "Other" referral source', async () => {
const store = createMockStore();
renderWithProviders(<AccountInformation />, { store });

const response = 'Found through blog post';

const otherCheckbox = screen.getByLabelText('Other...');
fireEvent.click(otherCheckbox);

const otherTextField = screen.getByRole('textbox', { name: '' });
fireEvent.change(otherTextField, {
target: { value: 'Found through blog post' },
});

fireEvent.change(screen.getByLabelText('Organization'), {
target: { value: 'Test Org' },
});
fireEvent.change(screen.getByLabelText('Department'), {
target: { value: 'Test Dept' },
});

fireEvent.click(screen.getByText('Continue to use policies'));

expect(
store.getState().signup.profile?.surveydata.referralSources.response[
'other'
] === response
);
});
});
3 changes: 2 additions & 1 deletion src/features/signup/ProviderSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
Typography,
} from '@mui/material';
import { FC } from 'react';
import { LOGIN_ROUTE } from '../../app/Routes';
import { LoginButtons, makeLoginURLs } from '../login/LogIn';
import classes from './SignUp.module.scss';

Expand Down Expand Up @@ -42,7 +43,7 @@ export const ProviderSelect: FC = () => {
</form>
<Box className={classes['separator']} />
<Typography>
Already have an account? <Link>Log in</Link>
Already have an account? <Link href={LOGIN_ROUTE}>Log in</Link>
</Typography>
<Typography>
<Link
Expand Down
183 changes: 183 additions & 0 deletions src/features/signup/SignUp.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { act } from 'react-dom/test-utils';
import { gravatarHash, SignUp, useDoSignup } from './SignUp';
import { loginCreate } from '../../common/api/authService';
import { setUserProfile } from '../../common/api/userProfileApi';
import { BrowserRouter, useNavigate, useParams } from 'react-router-dom';
import { Provider } from 'react-redux';
import { createTestStore } from '../../app/store';
import { ThemeProvider } from '@mui/material';
import { theme } from '../../theme';

jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useNavigate: jest.fn(),
useParams: jest.fn(),
}));

const mockNavigate = jest.fn();
const mockScrollTo = jest.fn();

const renderWithProviders = (
ui: React.ReactElement,
{ store = createTestStore() } = {}
) => {
return render(
<Provider store={store}>
<ThemeProvider theme={theme}>
<BrowserRouter>
<main style={{ height: '100vh' }}>{ui}</main>
</BrowserRouter>
</ThemeProvider>
</Provider>
);
};

describe('SignUp', () => {
beforeEach(() => {
(useNavigate as jest.Mock).mockReturnValue(mockNavigate);
(useParams as jest.Mock).mockReturnValue({ step: '1' });
Element.prototype.scrollTo = mockScrollTo;
});

it('renders signup steps', () => {
renderWithProviders(<SignUp />);
expect(screen.getByText('Sign up for KBase')).toBeInTheDocument();
expect(
screen.getByText('Sign up with a supported provider')
).toBeInTheDocument();
expect(screen.getByText('Account information')).toBeInTheDocument();
expect(screen.getByText('KBase use policies')).toBeInTheDocument();
});

it('navigates between steps when clicking previous steps', async () => {
(useParams as jest.Mock).mockReturnValue({ step: '3' });
renderWithProviders(<SignUp />);

const step1 = screen.getByText('Sign up with a supported provider');
await userEvent.click(step1);
expect(mockNavigate).toHaveBeenCalledWith('/signup/1');
expect(mockScrollTo).toHaveBeenCalledWith(0, 0);
});
});

describe('useDoSignup', () => {
const mockLoginCreateMutation = jest.fn();
const mockSetUserProfileMutation = jest.fn();

beforeEach(() => {
jest.spyOn(loginCreate, 'useMutation').mockReturnValue([
mockLoginCreateMutation,
{
isUninitialized: false,
isSuccess: true,
data: { token: { token: 'someToken' } },
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any,
]);
jest.spyOn(setUserProfile, 'useMutation').mockReturnValue([
mockSetUserProfileMutation,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
{ isUninitialized: true } as any,
]);
(useNavigate as jest.Mock).mockReturnValue(mockNavigate);
});

it('calls login create and set user profile mutations', async () => {
const mockStore = createTestStore({
signup: {
loginData: {
create: [
{
id: '123',
availablename: '',
provemail: '',
provfullname: '',
provusername: '',
},
],
creationallowed: true,
expires: 0,
login: [],
provider: 'Google',
},
account: {
username: 'testuser',
display: 'Test User',
email: '[email protected]',
policyids: [],
},
profile: {
userdata: {
avatarOption: 'gravatar',
department: '',
gravatarDefault: 'identicon',
organization: '',
},
surveydata: {
referralSources: {
question: '',
response: {},
},
},
},
},
});

let doSignup: (policyIds: string[]) => void;
act(() => {
const TestComponent = () => {
[doSignup] = useDoSignup();
return null;
};
renderWithProviders(<TestComponent />, {
store: mockStore,
});
});

await act(async () => {
doSignup(['policy1']);
});

expect(mockLoginCreateMutation).toHaveBeenCalledWith({
id: '123',
user: 'testuser',
display: 'Test User',
email: '[email protected]',
policyids: ['policy1'],
linkall: false,
});

expect(mockSetUserProfileMutation).toHaveBeenCalledWith([
{
profile: {
user: {
username: 'testuser',
realname: 'Test User',
},
profile: {
metadata: expect.any(Object),
preferences: {},
synced: {
gravatarHash: gravatarHash('[email protected]'),
},
userdata: {
avatarOption: 'gravatar',
department: '',
gravatarDefault: 'identicon',
organization: '',
},
surveydata: {
referralSources: {
question: '',
response: {},
},
},
},
},
},
'someToken',
]);
});
});
Loading

0 comments on commit 8af0e80

Please sign in to comment.