diff --git a/public/app/core/components/Login/LoginCtrl.tsx b/public/app/core/components/Login/LoginCtrl.tsx index 611572bae0a..370c62159c6 100644 --- a/public/app/core/components/Login/LoginCtrl.tsx +++ b/public/app/core/components/Login/LoginCtrl.tsx @@ -169,8 +169,12 @@ function getErrorMessage(err: FetchError ({ + ...jest.requireActual('@grafana/runtime'), __esModule: true, getBackendSrv: () => ({ post: postMock, @@ -103,4 +104,48 @@ describe('Login Page', () => { expect(screen.getByRole('link', { name: 'Sign in with Okta Test' })).toBeInTheDocument(); }); + + it('shows an error with incorrect password', async () => { + postMock.mockRejectedValueOnce({ + data: { + message: 'Invalid username or password', + messageId: 'password-auth.failed', + statusCode: 400, + }, + status: 400, + statusText: 'Bad Request', + }); + + render(); + + await userEvent.type(screen.getByLabelText('Username input field'), 'admin'); + await userEvent.type(screen.getByLabelText('Password input field'), 'test'); + await userEvent.click(screen.getByRole('button', { name: 'Login button' })); + + expect(await screen.findByRole('alert', { name: 'Invalid username or password' })).toBeInTheDocument(); + }); + + it('shows a different error with failed login attempts', async () => { + postMock.mockRejectedValueOnce({ + data: { + message: 'Invalid username or password', + messageId: 'login-attempt.blocked', + statusCode: 401, + }, + status: 401, + statusText: 'Unauthorized', + }); + + render(); + + await userEvent.type(screen.getByLabelText('Username input field'), 'admin'); + await userEvent.type(screen.getByLabelText('Password input field'), 'test'); + await userEvent.click(screen.getByRole('button', { name: 'Login button' })); + + expect( + await screen.findByRole('alert', { + name: 'You have exceeded the number of login attempts for this user. Please try again later.', + }) + ).toBeInTheDocument(); + }); }); diff --git a/public/locales/de-DE/grafana.json b/public/locales/de-DE/grafana.json index 8cb13ed4faa..5e5bc64c89d 100644 --- a/public/locales/de-DE/grafana.json +++ b/public/locales/de-DE/grafana.json @@ -192,6 +192,7 @@ }, "login": { "error": { + "blocked": "", "invalid-user-or-password": "", "unknown": "" } diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index e0a53d6cd1a..b4fbd81bd3c 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -192,6 +192,7 @@ }, "login": { "error": { + "blocked": "You have exceeded the number of login attempts for this user. Please try again later.", "invalid-user-or-password": "Invalid username or password", "unknown": "Unknown error occurred" } diff --git a/public/locales/es-ES/grafana.json b/public/locales/es-ES/grafana.json index 90daaa4131f..6f6f0799e9d 100644 --- a/public/locales/es-ES/grafana.json +++ b/public/locales/es-ES/grafana.json @@ -192,6 +192,7 @@ }, "login": { "error": { + "blocked": "", "invalid-user-or-password": "", "unknown": "" } diff --git a/public/locales/fr-FR/grafana.json b/public/locales/fr-FR/grafana.json index 98d548c5880..23343ff53ee 100644 --- a/public/locales/fr-FR/grafana.json +++ b/public/locales/fr-FR/grafana.json @@ -192,6 +192,7 @@ }, "login": { "error": { + "blocked": "", "invalid-user-or-password": "", "unknown": "" } diff --git a/public/locales/pseudo-LOCALE/grafana.json b/public/locales/pseudo-LOCALE/grafana.json index e0c1fe57614..995022e1898 100644 --- a/public/locales/pseudo-LOCALE/grafana.json +++ b/public/locales/pseudo-LOCALE/grafana.json @@ -192,6 +192,7 @@ }, "login": { "error": { + "blocked": "Ÿőū ĥävę ęχčęęđęđ ŧĥę ʼnūmþęř őƒ ľőģįʼn äŧŧęmpŧş ƒőř ŧĥįş ūşęř. Pľęäşę ŧřy äģäįʼn ľäŧęř.", "invalid-user-or-password": "Ĩʼnväľįđ ūşęřʼnämę őř päşşŵőřđ", "unknown": "Ůʼnĸʼnőŵʼn ęřřőř őččūřřęđ" } diff --git a/public/locales/zh-Hans/grafana.json b/public/locales/zh-Hans/grafana.json index 97b0d10fa9e..08db34d60e0 100644 --- a/public/locales/zh-Hans/grafana.json +++ b/public/locales/zh-Hans/grafana.json @@ -192,6 +192,7 @@ }, "login": { "error": { + "blocked": "", "invalid-user-or-password": "", "unknown": "" }