diff --git a/public/app/core/components/Signup/SignupPage.test.tsx b/public/app/core/components/Signup/SignupPage.test.tsx
new file mode 100644
index 00000000000..3e16b268418
--- /dev/null
+++ b/public/app/core/components/Signup/SignupPage.test.tsx
@@ -0,0 +1,119 @@
+import React from 'react';
+import { act, fireEvent, render, screen, waitFor } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+import { getRouteComponentProps } from 'app/core/navigation/__mocks__/routeProps';
+
+import { SignupPage } from './SignupPage';
+
+const postMock = jest.fn();
+jest.mock('@grafana/runtime', () => ({
+ getBackendSrv: () => ({
+ post: postMock,
+ }),
+}));
+
+jest.mock('app/core/config', () => {
+ return {
+ loginError: false,
+ buildInfo: {
+ version: 'v1.0',
+ commit: '1',
+ env: 'production',
+ edition: 'Open Source',
+ isEnterprise: false,
+ },
+ licenseInfo: {
+ stateInfo: '',
+ licenseUrl: '',
+ },
+ appSubUrl: '',
+ getConfig: () => ({
+ autoAssignOrg: false,
+ verifyEmailEnabled: true,
+ appSubUrl: '',
+ }),
+ };
+});
+
+const props = {
+ email: '',
+ code: '',
+ ...getRouteComponentProps(),
+};
+
+describe('Signup Page', () => {
+ it('renders correctly', () => {
+ render();
+ expect(screen.getByRole('heading', { name: 'Welcome to Grafana' })).toBeInTheDocument();
+
+ expect(screen.getByRole('textbox', { name: 'Your name' })).toBeInTheDocument();
+ expect(screen.getByRole('textbox', { name: 'Email' })).toBeInTheDocument();
+ expect(screen.getByRole('textbox', { name: 'Org. name' })).toBeInTheDocument();
+ expect(screen.getByRole('textbox', { name: /Email verification code/i })).toBeInTheDocument();
+
+ expect(screen.getByLabelText('Password')).toBeInTheDocument();
+ expect(screen.getByLabelText('Confirm password')).toBeInTheDocument();
+
+ expect(screen.getByRole('button', { name: 'Submit' })).toBeInTheDocument();
+
+ expect(screen.getByRole('link', { name: 'Back to login' })).toBeInTheDocument();
+ expect(screen.getByRole('link', { name: 'Back to login' })).toHaveAttribute('href', '/login');
+ });
+ it('should pass validation checks for email field', async () => {
+ render();
+
+ fireEvent.click(screen.getByRole('button', { name: 'Submit' }));
+ expect(await screen.findByText('Email is required')).toBeInTheDocument();
+
+ await act(async () => {
+ await userEvent.type(screen.getByRole('textbox', { name: 'Email' }), 'test');
+ expect(screen.queryByText('Email is invalid')).toBeInTheDocument();
+
+ await userEvent.type(screen.getByRole('textbox', { name: 'Email' }), 'test@gmail.com');
+ expect(screen.queryByText('Email is invalid')).not.toBeInTheDocument();
+ });
+ });
+ it('should pass validation checks for password and confirm password field', async () => {
+ render();
+
+ fireEvent.click(screen.getByRole('button', { name: 'Submit' }));
+ expect(await screen.findByText('Password is required')).toBeInTheDocument();
+ expect(await screen.findByText('Confirmed password is required')).toBeInTheDocument();
+
+ await act(async () => {
+ await userEvent.type(screen.getByLabelText('Password'), 'admin');
+ await userEvent.type(screen.getByLabelText('Confirm password'), 'a');
+ expect(screen.queryByText('Passwords must match!')).toBeInTheDocument();
+
+ await userEvent.type(screen.getByLabelText('Confirm password'), 'dmin');
+ expect(screen.queryByText('Passwords must match!')).not.toBeInTheDocument();
+ });
+ });
+ it('should navigate to default url if signup is successful', async () => {
+ Object.defineProperty(window, 'location', {
+ value: {
+ assign: jest.fn(),
+ },
+ });
+ postMock.mockResolvedValueOnce({ message: 'Logged in' });
+ render();
+
+ await userEvent.type(screen.getByRole('textbox', { name: 'Your name' }), 'test-user');
+ await userEvent.type(screen.getByRole('textbox', { name: 'Email' }), 'test@gmail.com');
+ await userEvent.type(screen.getByLabelText('Password'), 'admin');
+ await userEvent.type(screen.getByLabelText('Confirm password'), 'admin');
+ fireEvent.click(screen.getByRole('button', { name: 'Submit' }));
+
+ await waitFor(() =>
+ expect(postMock).toHaveBeenCalledWith('/api/user/signup/step2', {
+ code: '',
+ email: 'test@gmail.com',
+ name: 'test-user',
+ orgName: '',
+ password: 'admin',
+ username: 'test@gmail.com',
+ })
+ );
+ expect(window.location.assign).toHaveBeenCalledWith('/');
+ });
+});
diff --git a/public/app/core/components/Signup/SignupPage.tsx b/public/app/core/components/Signup/SignupPage.tsx
index 31e52133c0d..6eac404d1c6 100644
--- a/public/app/core/components/Signup/SignupPage.tsx
+++ b/public/app/core/components/Signup/SignupPage.tsx
@@ -46,9 +46,9 @@ export const SignupPage: FC = (props) => {
});
if (response.code === 'redirect-to-select-org') {
- window.location.href = getConfig().appSubUrl + '/profile/select-org?signup=1';
+ window.location.assign(getConfig().appSubUrl + '/profile/select-org?signup=1');
}
- window.location.href = getConfig().appSubUrl + '/';
+ window.location.assign(getConfig().appSubUrl + '/');
};
const defaultValues = {
@@ -63,10 +63,11 @@ export const SignupPage: FC = (props) => {
{({ errors, register, getValues }: FormAPI) => (
<>
-
+
= (props) => {
{!getConfig().autoAssignOrg && (
-
+
)}
{getConfig().verifyEmailEnabled && (
-
+
)}
= (props) => {
v === getValues().password || 'Passwords must match!',
diff --git a/public/app/core/components/Signup/VerifyEmail.tsx b/public/app/core/components/Signup/VerifyEmail.tsx
index 053936f51b7..788f4462ac8 100644
--- a/public/app/core/components/Signup/VerifyEmail.tsx
+++ b/public/app/core/components/Signup/VerifyEmail.tsx
@@ -44,10 +44,20 @@ export const VerifyEmail: FC = () => {
-
+
diff --git a/public/app/core/components/Signup/VerifyEmailPage.test.tsx b/public/app/core/components/Signup/VerifyEmailPage.test.tsx
new file mode 100644
index 00000000000..5e8783f1488
--- /dev/null
+++ b/public/app/core/components/Signup/VerifyEmailPage.test.tsx
@@ -0,0 +1,74 @@
+import React from 'react';
+import { act, fireEvent, render, screen, waitFor } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+
+import { VerifyEmailPage } from './VerifyEmailPage';
+
+const postMock = jest.fn();
+jest.mock('@grafana/runtime', () => ({
+ getBackendSrv: () => ({
+ post: postMock,
+ }),
+}));
+
+jest.mock('app/core/config', () => {
+ return {
+ buildInfo: {
+ version: 'v1.0',
+ commit: '1',
+ env: 'production',
+ edition: 'Open Source',
+ isEnterprise: false,
+ },
+ licenseInfo: {
+ stateInfo: '',
+ licenseUrl: '',
+ },
+ getConfig: () => ({
+ verifyEmailEnabled: true,
+ appSubUrl: '',
+ }),
+ };
+});
+
+describe('VerifyEmail Page', () => {
+ it('renders correctly', () => {
+ render();
+ expect(screen.getByText('Verify Email')).toBeInTheDocument();
+ expect(screen.getByRole('textbox', { name: /Email/i })).toBeInTheDocument();
+
+ expect(screen.getByRole('button', { name: 'Send verification email' })).toBeInTheDocument();
+
+ expect(screen.getByRole('link', { name: 'Back to login' })).toBeInTheDocument();
+ expect(screen.getByRole('link', { name: 'Back to login' })).toHaveAttribute('href', '/login');
+ });
+ it('should pass validation checks for email field', async () => {
+ render();
+
+ fireEvent.click(screen.getByRole('button', { name: 'Send verification email' }));
+ expect(await screen.findByText('Email is required')).toBeInTheDocument();
+
+ await act(async () => {
+ await userEvent.type(screen.getByRole('textbox', { name: /Email/i }), 'test');
+ expect(screen.queryByText('Email is invalid')).toBeInTheDocument();
+
+ await userEvent.type(screen.getByRole('textbox', { name: /Email/i }), 'test@gmail.com');
+ expect(screen.queryByText('Email is invalid')).not.toBeInTheDocument();
+ });
+ });
+ it('should show complete signup if email-verification is successful', async () => {
+ postMock.mockResolvedValueOnce({ message: 'SignUpCreated' });
+ render();
+
+ await userEvent.type(screen.getByRole('textbox', { name: /Email/i }), 'test@gmail.com');
+ fireEvent.click(screen.getByRole('button', { name: 'Send verification email' }));
+
+ await waitFor(() =>
+ expect(postMock).toHaveBeenCalledWith('/api/user/signup', {
+ email: 'test@gmail.com',
+ })
+ );
+ expect(screen.getByRole('link', { name: 'Complete Signup' })).toBeInTheDocument();
+ expect(screen.getByRole('link', { name: 'Complete Signup' })).toHaveAttribute('href', '/signup');
+ });
+});