mirror of
https://github.com/grafana/grafana.git
synced 2025-02-12 00:25:46 -06:00
Admin: Fixes so form values are filled in from backend (#30544)
* Admin: Fixes so form values are filled in from backend * Chore: tidy up the imports
This commit is contained in:
parent
16f5d60d17
commit
a8056e2c9d
127
public/app/features/users/SignupInvited.test.tsx
Normal file
127
public/app/features/users/SignupInvited.test.tsx
Normal file
@ -0,0 +1,127 @@
|
||||
import React from 'react';
|
||||
import * as redux from 'react-redux';
|
||||
import { render, screen, waitFor, within } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
|
||||
import SignupInvitedPage from './SignupInvited';
|
||||
import { backendSrv } from '../../core/services/backend_srv';
|
||||
|
||||
jest.mock('app/core/core', () => ({
|
||||
contextSrv: {
|
||||
user: { orgName: 'Invited to Org Name' },
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('@grafana/runtime', () => ({
|
||||
...((jest.requireActual('@grafana/runtime') as unknown) as object),
|
||||
getBackendSrv: () => backendSrv,
|
||||
}));
|
||||
|
||||
const defaultGet = {
|
||||
email: 'some.user@localhost',
|
||||
name: 'Some User',
|
||||
invitedBy: 'Invited By User',
|
||||
username: 'someuser',
|
||||
};
|
||||
|
||||
async function setupTestContext({ get = defaultGet }: { get?: typeof defaultGet | null } = {}) {
|
||||
jest.clearAllMocks();
|
||||
|
||||
const reduxSpy = jest.spyOn(redux, 'useSelector');
|
||||
reduxSpy.mockReturnValue('some code');
|
||||
|
||||
const getSpy = jest.spyOn(backendSrv, 'get');
|
||||
getSpy.mockResolvedValue(get);
|
||||
|
||||
const postSpy = jest.spyOn(backendSrv, 'post');
|
||||
postSpy.mockResolvedValue([]);
|
||||
|
||||
render(<SignupInvitedPage />);
|
||||
|
||||
await waitFor(() => expect(getSpy).toHaveBeenCalled());
|
||||
expect(getSpy).toHaveBeenCalledTimes(1);
|
||||
|
||||
return { getSpy, postSpy };
|
||||
}
|
||||
|
||||
describe('SignupInvitedPage', () => {
|
||||
describe('when initialized but invite data has not been retrieved yet', () => {
|
||||
it('then it should not render', async () => {
|
||||
await setupTestContext({ get: null });
|
||||
|
||||
expect(screen.queryByText(/email/i)).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when initialized and invite data has been retrieved', () => {
|
||||
it('then the greeting should be correct', async () => {
|
||||
await setupTestContext();
|
||||
|
||||
expect(
|
||||
screen.getByRole('heading', {
|
||||
name: /hello some user\./i,
|
||||
})
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('then the invited by should be correct', async () => {
|
||||
await setupTestContext();
|
||||
|
||||
const view = screen.getByText(
|
||||
/has invited you to join grafana and the organization please complete the following and choose a password to accept your invitation and continue:/i
|
||||
);
|
||||
|
||||
expect(within(view).getByText(/invited by user/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('then the organization invited to should be correct', async () => {
|
||||
await setupTestContext();
|
||||
|
||||
const view = screen.getByText(
|
||||
/has invited you to join grafana and the organization please complete the following and choose a password to accept your invitation and continue:/i
|
||||
);
|
||||
|
||||
expect(within(view).getByText(/invited to org name/i)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('then the form should include form data', async () => {
|
||||
await setupTestContext();
|
||||
|
||||
expect(screen.getByPlaceholderText(/email@example\.com/i)).toHaveValue('some.user@localhost');
|
||||
expect(screen.getByPlaceholderText(/name \(optional\)/i)).toHaveValue('Some User');
|
||||
expect(screen.getByPlaceholderText(/username/i)).toHaveValue('some.user@localhost');
|
||||
expect(screen.getByPlaceholderText(/password/i)).toHaveValue('');
|
||||
});
|
||||
});
|
||||
|
||||
describe('when user submits the form and the required fields are not filled in', () => {
|
||||
it('then required fields should show error messages and nothing should be posted', async () => {
|
||||
const { postSpy } = await setupTestContext({ get: { email: '', invitedBy: '', name: '', username: '' } });
|
||||
|
||||
userEvent.click(screen.getByRole('button', { name: /sign up/i }));
|
||||
|
||||
await waitFor(() => expect(screen.getByText(/email is required/i)).toBeInTheDocument());
|
||||
expect(screen.getByText(/username is required/i)).toBeInTheDocument();
|
||||
expect(screen.getByText(/password is required/i)).toBeInTheDocument();
|
||||
expect(postSpy).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when user submits the form and the required fields are filled in', () => {
|
||||
it('then correct form data should be posted', async () => {
|
||||
const { postSpy } = await setupTestContext();
|
||||
|
||||
await userEvent.type(screen.getByPlaceholderText(/password/i), 'pass@word1');
|
||||
userEvent.click(screen.getByRole('button', { name: /sign up/i }));
|
||||
|
||||
await waitFor(() => expect(postSpy).toHaveBeenCalledTimes(1));
|
||||
expect(postSpy).toHaveBeenCalledWith('/api/user/invite/complete', {
|
||||
email: 'some.user@localhost',
|
||||
name: 'Some User',
|
||||
username: 'some.user@localhost',
|
||||
password: 'pass@word1',
|
||||
inviteCode: 'some code',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -1,23 +1,13 @@
|
||||
import React, { FC, useState } from 'react';
|
||||
import { hot } from 'react-hot-loader';
|
||||
import { connect, MapDispatchToProps, MapStateToProps } from 'react-redux';
|
||||
import { StoreState } from 'app/types';
|
||||
import { updateLocation } from 'app/core/actions';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { getBackendSrv } from '@grafana/runtime';
|
||||
import { Button, Field, Form, Input } from '@grafana/ui';
|
||||
import { useAsync } from 'react-use';
|
||||
|
||||
import { StoreState } from 'app/types';
|
||||
import Page from 'app/core/components/Page/Page';
|
||||
import { contextSrv } from 'app/core/core';
|
||||
import { getConfig } from 'app/core/config';
|
||||
import { UrlQueryValue } from '@grafana/data';
|
||||
|
||||
interface ConnectedProps {
|
||||
code?: UrlQueryValue;
|
||||
}
|
||||
|
||||
interface DispatchProps {
|
||||
updateLocation: typeof updateLocation;
|
||||
}
|
||||
|
||||
interface FormModel {
|
||||
email: string;
|
||||
@ -38,12 +28,13 @@ const navModel = {
|
||||
},
|
||||
};
|
||||
|
||||
const SingupInvitedPageUnconnected: FC<DispatchProps & ConnectedProps> = ({ code }) => {
|
||||
export const SignupInvitedPage: FC = () => {
|
||||
const code = useSelector((state: StoreState) => state.location.routeParams.code);
|
||||
const [initFormModel, setInitFormModel] = useState<FormModel>();
|
||||
const [greeting, setGreeting] = useState<string>();
|
||||
const [invitedBy, setInvitedBy] = useState<string>();
|
||||
useAsync(async () => {
|
||||
const invite = await getBackendSrv().get('/api/user/invite/' + code);
|
||||
const invite = await getBackendSrv().get(`/api/user/invite/${code}`);
|
||||
setInitFormModel({
|
||||
email: invite.email,
|
||||
name: invite.name,
|
||||
@ -52,13 +43,17 @@ const SingupInvitedPageUnconnected: FC<DispatchProps & ConnectedProps> = ({ code
|
||||
|
||||
setGreeting(invite.name || invite.email || invite.username);
|
||||
setInvitedBy(invite.invitedBy);
|
||||
}, []);
|
||||
}, [code]);
|
||||
|
||||
const onSubmit = async (formData: FormModel) => {
|
||||
await getBackendSrv().post('/api/user/invite/complete', { ...formData, inviteCode: code });
|
||||
window.location.href = getConfig().appSubUrl + '/';
|
||||
};
|
||||
|
||||
if (!initFormModel) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Page navModel={navModel}>
|
||||
<Page.Contents>
|
||||
@ -110,12 +105,4 @@ const SingupInvitedPageUnconnected: FC<DispatchProps & ConnectedProps> = ({ code
|
||||
);
|
||||
};
|
||||
|
||||
const mapStateToProps: MapStateToProps<ConnectedProps, {}, StoreState> = (state: StoreState) => ({
|
||||
code: state.location.routeParams.code,
|
||||
});
|
||||
|
||||
const mapDispatchToProps: MapDispatchToProps<DispatchProps, {}> = {
|
||||
updateLocation,
|
||||
};
|
||||
|
||||
export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(SingupInvitedPageUnconnected));
|
||||
export default SignupInvitedPage;
|
||||
|
Loading…
Reference in New Issue
Block a user