From 7c3de89df5a9c1a06f621878779314602a2d02ee Mon Sep 17 00:00:00 2001
From: Joe Portner <5295965+jportner@users.noreply.github.com>
Date: Fri, 28 Feb 2020 11:51:35 -0500
Subject: [PATCH] Improve LoginPage unit tests
Uses a single test for the entire page, and more focused tests for
each permutation of BasicLoginForm/DisabledLoginForm. This greatly
reduces the snapshot size.
Also adds tests for API calls.
---
.../__snapshots__/login_page.test.tsx.snap | 722 +++---------------
.../authentication/login/login_page.test.tsx | 171 ++++-
2 files changed, 231 insertions(+), 662 deletions(-)
diff --git a/x-pack/plugins/security/public/authentication/login/__snapshots__/login_page.test.tsx.snap b/x-pack/plugins/security/public/authentication/login/__snapshots__/login_page.test.tsx.snap
index 87bfba689ca8a..c1b8202e2f3f3 100644
--- a/x-pack/plugins/security/public/authentication/login/__snapshots__/login_page.test.tsx.snap
+++ b/x-pack/plugins/security/public/authentication/login/__snapshots__/login_page.test.tsx.snap
@@ -1,582 +1,120 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`LoginPage disabled form states renders as expected when a connection to ES is not available 1`] = `
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- }
- title={
-
- }
- />
-
-
-
-
+
+ }
+ title={
+
+ }
+/>
`;
exports[`LoginPage disabled form states renders as expected when an unknown loginState layout is provided 1`] = `
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- }
- title={
-
- }
- />
-
-
-
-
+
+ }
+ title={
+
+ }
+/>
`;
-exports[`LoginPage disabled form states renders as expected when loginAssistanceMessage is set 1`] = `
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-`;
-
-exports[`LoginPage disabled form states renders as expected when secure cookies are required but not present 1`] = `
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- }
- title={
-
- }
- />
-
-
-
-
+exports[`LoginPage disabled form states renders as expected when secure connection is required but not present 1`] = `
+
+ }
+ title={
+
+ }
+/>
`;
exports[`LoginPage disabled form states renders as expected when xpack is not available 1`] = `
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- }
- title={
-
- }
- />
-
-
-
-
+
+ }
+ title={
+
+ }
+/>
`;
exports[`LoginPage enabled form state renders as expected 1`] = `
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
`;
exports[`LoginPage enabled form state renders as expected when info message is set 1`] = `
+
+`;
+
+exports[`LoginPage enabled form state renders as expected when loginAssistanceMessage is set 1`] = `
+
+`;
+
+exports[`LoginPage page renders as expected 1`] = `
@@ -637,66 +175,10 @@ exports[`LoginPage enabled form state renders as expected when info message is s
diff --git a/x-pack/plugins/security/public/authentication/login/login_page.test.tsx b/x-pack/plugins/security/public/authentication/login/login_page.test.tsx
index ac17dfa5870ef..294434cd08ebc 100644
--- a/x-pack/plugins/security/public/authentication/login/login_page.test.tsx
+++ b/x-pack/plugins/security/public/authentication/login/login_page.test.tsx
@@ -11,6 +11,7 @@ import { nextTick } from 'test_utils/enzyme_helpers';
import { LoginState } from './login_state';
import { LoginPage } from './login_page';
import { coreMock } from '../../../../../../src/core/public/mocks';
+import { DisabledLoginForm, BasicLoginForm } from './components';
const createLoginState = (options?: Partial) => {
return {
@@ -21,14 +22,63 @@ const createLoginState = (options?: Partial) => {
};
describe('LoginPage', () => {
+ // mock a minimal subset of the HttpSetup
+ const httpMock = {
+ get: jest.fn(),
+ addLoadingCountSource: jest.fn(),
+ } as any;
+ const resetHttpMock = () => {
+ httpMock.get.mockReset();
+ httpMock.addLoadingCountSource.mockReset();
+ };
+
+ beforeAll(() => {
+ Object.defineProperty(window, 'location', {
+ value: { href: 'http://some-host/bar', protocol: 'http' },
+ writable: true,
+ });
+ });
+
+ beforeEach(() => {
+ resetHttpMock();
+ });
+
+ afterAll(() => {
+ delete (window as any).location;
+ });
+
+ describe('page', () => {
+ it('renders as expected', async () => {
+ const coreStartMock = coreMock.createStart();
+ httpMock.get.mockResolvedValue(createLoginState());
+
+ const wrapper = shallow(
+
+ );
+
+ await act(async () => {
+ await nextTick();
+ wrapper.update();
+ resetHttpMock(); // so the calls don't show in the BasicLoginForm snapshot
+ });
+
+ expect(wrapper).toMatchSnapshot();
+ });
+ });
+
describe('disabled form states', () => {
- it('renders as expected when secure cookies are required but not present', async () => {
+ it('renders as expected when secure connection is required but not present', async () => {
const coreStartMock = coreMock.createStart();
- coreStartMock.http.get.mockResolvedValue(createLoginState());
+ httpMock.get.mockResolvedValue(createLoginState());
const wrapper = shallow(
{
wrapper.update();
});
- expect(coreStartMock.http.get).toHaveBeenCalledTimes(1);
- expect(coreStartMock.http.get).toHaveBeenCalledWith('/internal/security/login_state');
-
- expect(wrapper).toMatchSnapshot();
+ expect(wrapper.find(DisabledLoginForm)).toMatchSnapshot();
});
it('renders as expected when a connection to ES is not available', async () => {
const coreStartMock = coreMock.createStart();
- coreStartMock.http.get.mockResolvedValue(
- createLoginState({ layout: 'error-es-unavailable' })
- );
+ httpMock.get.mockResolvedValue(createLoginState({ layout: 'error-es-unavailable' }));
const wrapper = shallow(
{
wrapper.update();
});
- expect(wrapper).toMatchSnapshot();
+ expect(wrapper.find(DisabledLoginForm)).toMatchSnapshot();
});
it('renders as expected when xpack is not available', async () => {
const coreStartMock = coreMock.createStart();
- coreStartMock.http.get.mockResolvedValue(
- createLoginState({ layout: 'error-xpack-unavailable' })
- );
+ httpMock.get.mockResolvedValue(createLoginState({ layout: 'error-xpack-unavailable' }));
const wrapper = shallow(
{
wrapper.update();
});
- expect(wrapper).toMatchSnapshot();
+ expect(wrapper.find(DisabledLoginForm)).toMatchSnapshot();
});
it('renders as expected when an unknown loginState layout is provided', async () => {
const coreStartMock = coreMock.createStart();
- coreStartMock.http.get.mockResolvedValue(
+ httpMock.get.mockResolvedValue(
createLoginState({ layout: 'error-asdf-asdf-unknown' as any })
);
const wrapper = shallow(
{
wrapper.update();
});
- expect(wrapper).toMatchSnapshot();
+ expect(wrapper.find(DisabledLoginForm)).toMatchSnapshot();
});
+ });
- it('renders as expected when loginAssistanceMessage is set', async () => {
+ describe('enabled form state', () => {
+ it('renders as expected', async () => {
const coreStartMock = coreMock.createStart();
- coreStartMock.http.get.mockResolvedValue(createLoginState());
+ httpMock.get.mockResolvedValue(createLoginState());
const wrapper = shallow(
);
@@ -131,31 +176,66 @@ describe('LoginPage', () => {
await act(async () => {
await nextTick();
wrapper.update();
+ resetHttpMock(); // so the calls don't show in the BasicLoginForm snapshot
});
- expect(wrapper).toMatchSnapshot();
+ expect(wrapper.find(BasicLoginForm)).toMatchSnapshot();
});
- });
- describe('enabled form state', () => {
- beforeAll(() => {
- Object.defineProperty(window, 'location', {
- value: { href: 'http://some-host/bar', protocol: 'http' },
- writable: true,
+ it('renders as expected when info message is set', async () => {
+ const coreStartMock = coreMock.createStart();
+ httpMock.get.mockResolvedValue(createLoginState());
+ window.location.href = 'http://some-host/bar?msg=SESSION_EXPIRED';
+
+ const wrapper = shallow(
+
+ );
+
+ await act(async () => {
+ await nextTick();
+ wrapper.update();
+ resetHttpMock(); // so the calls don't show in the BasicLoginForm snapshot
});
+
+ expect(wrapper.find(BasicLoginForm)).toMatchSnapshot();
});
- afterAll(() => {
- delete (window as any).location;
+ it('renders as expected when loginAssistanceMessage is set', async () => {
+ const coreStartMock = coreMock.createStart();
+ httpMock.get.mockResolvedValue(createLoginState());
+
+ const wrapper = shallow(
+
+ );
+
+ await act(async () => {
+ await nextTick();
+ wrapper.update();
+ resetHttpMock(); // so the calls don't show in the BasicLoginForm snapshot
+ });
+
+ expect(wrapper.find(BasicLoginForm)).toMatchSnapshot();
});
+ });
- it('renders as expected', async () => {
+ describe('API calls', () => {
+ it('GET login_state success', async () => {
const coreStartMock = coreMock.createStart();
- coreStartMock.http.get.mockResolvedValue(createLoginState());
+ httpMock.get.mockResolvedValue(createLoginState());
const wrapper = shallow(
{
wrapper.update();
});
- expect(wrapper).toMatchSnapshot();
+ expect(httpMock.addLoadingCountSource).toHaveBeenCalledTimes(1);
+ expect(httpMock.get).toHaveBeenCalledTimes(1);
+ expect(httpMock.get).toHaveBeenCalledWith('/internal/security/login_state');
+ expect(coreStartMock.fatalErrors.add).not.toHaveBeenCalled();
});
- it('renders as expected when info message is set', async () => {
+ it('GET login_state failure', async () => {
const coreStartMock = coreMock.createStart();
- coreStartMock.http.get.mockResolvedValue(createLoginState());
- window.location.href = 'http://some-host/bar?msg=SESSION_EXPIRED';
+ const error = Symbol();
+ httpMock.get.mockRejectedValue(error);
const wrapper = shallow(
{
wrapper.update();
});
- expect(wrapper).toMatchSnapshot();
+ expect(httpMock.addLoadingCountSource).toHaveBeenCalledTimes(1);
+ expect(httpMock.get).toHaveBeenCalledTimes(1);
+ expect(httpMock.get).toHaveBeenCalledWith('/internal/security/login_state');
+ expect(coreStartMock.fatalErrors.add).toHaveBeenCalledTimes(1);
+ expect(coreStartMock.fatalErrors.add).toHaveBeenCalledWith(error);
});
});
});