Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,16 @@

import sinon from 'sinon';

import { initTestBed, registerHttpRequestMockHelpers, nextTick } from './test_helpers';
import { nextTick } from '../../../../test_utils';
import { FollowerIndexAdd } from '../../public/app/sections/follower_index_add';
import { AutoFollowPatternAdd } from '../../public/app/sections/auto_follow_pattern_add';
import { RemoteClustersFormField } from '../../public/app/components';

import { INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE } from '../../../../../src/legacy/ui/public/index_patterns';
import routing from '../../public/app/services/routing';

import { registerHttpRequestMockHelpers } from './test_helpers';
import { FollowerIndexFormPageObject } from './follower_index_form.page_object';

jest.mock('ui/chrome', () => ({
addBasePath: (path) => path || 'api/cross_cluster_replication',
breadcrumbs: { set: () => {} },
Expand All @@ -27,22 +29,9 @@ jest.mock('ui/index_patterns', () => {
return { INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE, validateIndexPattern, ILLEGAL_CHARACTERS, CONTAINS_SPACES };
});

const testBedOptions = {
memoryRouter: {
onRouter: (router) => routing.reactRouter = router
}
};

describe('Create Follower index', () => {
let followerIndexPage;
let server;
let find;
let exists;
let component;
let getUserActions;
let form;
let getFormErrorsMessages;
let clickSaveForm;
let toggleAdvancedSettings;
let setLoadRemoteClustersResponse;

beforeEach(() => {
Expand All @@ -59,92 +48,83 @@ describe('Create Follower index', () => {

// Mock all HTTP Requests that have not been handled previously
server.respondWith([200, {}, '']);
});

describe('on component mount', () => {
beforeEach(() => {
({ find, exists } = initTestBed(FollowerIndexAdd, undefined, testBedOptions));
followerIndexPage = new FollowerIndexFormPageObject(FollowerIndexAdd, {}, {
memoryRouter: {
onRouter: (router) => routing.reactRouter = router
}
});
});

describe('on component mount', () => {
test('should display a "loading remote clusters" indicator', () => {
expect(exists('remoteClustersLoading')).toBe(true);
expect(find('remoteClustersLoading').text()).toBe('Loading remote clusters…');
expect(followerIndexPage.getLoadingRemoteClusters().length).toBe(1);
expect(followerIndexPage.getLoadingRemoteClusters().text()).toBe('Loading remote clusters…');
});

test('should have a link to the documentation', () => {
expect(exists('followerIndexDocsButton')).toBe(true);
expect(followerIndexPage.getDocsButton().length).toBe(1);
});
});

describe('when remote clusters are loaded', () => {
beforeEach(async () => {
({ find, exists, component, getUserActions, getFormErrorsMessages } = initTestBed(FollowerIndexAdd, undefined, testBedOptions));

({ clickSaveForm } = getUserActions('followerIndexForm'));

await nextTick(); // We need to wait next tick for the mock server response to comes in
component.update();
followerIndexPage.component.update();
});

test('should display the Follower index form', async () => {
expect(exists('ccrFollowerIndexForm')).toBe(true);
expect(followerIndexPage.getForm().length).toBe(1);
});

test('should display errors and disable the save button when clicking "save" without filling the form', () => {
expect(exists('followerIndexFormError')).toBe(false);
expect(find('ccrFollowerIndexFormSubmitButton').props().disabled).toBe(false);
expect(followerIndexPage.getFormError().length).toBe(0);
expect(followerIndexPage.getSaveFormButton().props().disabled).toBe(false);

clickSaveForm();
followerIndexPage.clickSave();

expect(exists('followerIndexFormError')).toBe(true);
expect(getFormErrorsMessages()).toEqual([
expect(followerIndexPage.getFormError().length).toBe(1);
expect(followerIndexPage.getFormErrorMessages()).toEqual([
'Leader index is required.',
'Name is required.'
]);
expect(find('ccrFollowerIndexFormSubmitButton').props().disabled).toBe(true);
expect(followerIndexPage.getSaveFormButton().props().disabled).toBe(true);
});
});

describe('form validation', () => {
beforeEach(async () => {
({ component, form, getUserActions, getFormErrorsMessages, exists, find } = initTestBed(FollowerIndexAdd, undefined, testBedOptions));

({ clickSaveForm, toggleAdvancedSettings } = getUserActions('followerIndexForm'));

await nextTick(); // We need to wait next tick for the mock server response to comes in
component.update();
followerIndexPage.component.update();
});

describe('remote cluster', () => {
// The implementation of the remote cluster "Select" + validation is
// done inside the <RemoteClustersFormField /> component. The same component that we use in the <AutoFollowPatternAdd /> section.
// To avoid copy/pasting the same tests here, we simply make sure that both sections use the <RemoteClustersFormField />
test('should use the same <RemoteClustersFormField /> component as the <AutoFollowPatternAdd /> section', async () => {
const { component: autoFollowPatternAddComponent } = initTestBed(AutoFollowPatternAdd, undefined, testBedOptions);
await nextTick();
autoFollowPatternAddComponent.update();

const remoteClusterFormFieldFollowerIndex = component.find(RemoteClustersFormField);
const remoteClusterFormFieldAutoFollowPattern = autoFollowPatternAddComponent.find(RemoteClustersFormField);

test('uses a <RemoteClustersFormField /> component', async () => {
// TODO: Create an AutoFollowPatternPageObject and compare against the RemoteClustersFormField
// that it instantiates.
const remoteClusterFormFieldFollowerIndex = followerIndexPage.component.find(RemoteClustersFormField);
expect(remoteClusterFormFieldFollowerIndex.length).toBe(1);
expect(remoteClusterFormFieldAutoFollowPattern.length).toBe(1);
});
});

describe('leader index', () => {
test('should not allow spaces', () => {
form.setInputValue('ccrFollowerIndexFormLeaderIndexInput', 'with space');
clickSaveForm();
expect(getFormErrorsMessages()).toContain('Spaces are not allowed in the leader index.');
followerIndexPage.setLeaderIndex('with space');
followerIndexPage.clickSave();
expect(followerIndexPage.getFormErrorMessages())
.toContain('Spaces are not allowed in the leader index.');
});

test('should not allow invalid characters', () => {
clickSaveForm(); // Make all errors visible
followerIndexPage.clickSave(); // Make all errors visible

const expectInvalidChar = (char) => {
form.setInputValue('ccrFollowerIndexFormLeaderIndexInput', `with${char}`);
expect(getFormErrorsMessages()).toContain(`Remove the characters ${char} from your leader index.`);
followerIndexPage.setLeaderIndex(`with${char}`);
expect(followerIndexPage.getFormErrorMessages())
.toContain(`Remove the characters ${char} from your leader index.`);
};

return INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE.reduce((promise, char) => {
Expand All @@ -155,23 +135,26 @@ describe('Create Follower index', () => {

describe('follower index', () => {
test('should not allow spaces', () => {
form.setInputValue('ccrFollowerIndexFormFollowerIndexInput', 'with space');
clickSaveForm();
expect(getFormErrorsMessages()).toContain('Spaces are not allowed in the name.');
followerIndexPage.setFollowerIndex('with space');
followerIndexPage.clickSave();
expect(followerIndexPage.getFormErrorMessages())
.toContain('Spaces are not allowed in the name.');
});

test('should not allow a "." (period) as first character', () => {
form.setInputValue('ccrFollowerIndexFormFollowerIndexInput', '.withDot');
clickSaveForm();
expect(getFormErrorsMessages()).toContain(`Name can't begin with a period.`);
followerIndexPage.setFollowerIndex('.withDot');
followerIndexPage.clickSave();
expect(followerIndexPage.getFormErrorMessages())
.toContain(`Name can't begin with a period.`);
});

test('should not allow invalid characters', () => {
clickSaveForm(); // Make all errors visible
followerIndexPage.clickSave(); // Make all errors visible

const expectInvalidChar = (char) => {
form.setInputValue('ccrFollowerIndexFormFollowerIndexInput', `with${char}`);
expect(getFormErrorsMessages()).toContain(`Remove the characters ${char} from your name.`);
followerIndexPage.setFollowerIndex(`with${char}`);
expect(followerIndexPage.getFormErrorMessages())
.toContain(`Remove the characters ${char} from your name.`);
};

return INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE.reduce((promise, char) => {
Expand All @@ -191,7 +174,7 @@ describe('Create Follower index', () => {
// Keep track of the request count made until this point
const totalRequests = server.requests.length;

form.setInputValue('ccrFollowerIndexFormFollowerIndexInput', 'index-name');
followerIndexPage.setFollowerIndex('index-name');
await nextTick(550); // we need to wait as there is a debounce of 500ms on the http validation

expect(server.requests.length).toBe(totalRequests + 1);
Expand All @@ -202,11 +185,12 @@ describe('Create Follower index', () => {
const indexName = 'index-name';
setGetClusterIndicesResponse([{ name: indexName }]);

form.setInputValue('ccrFollowerIndexFormFollowerIndexInput', indexName);
followerIndexPage.setFollowerIndex(indexName);
await nextTick(550);
component.update();
followerIndexPage.component.update();

expect(getFormErrorsMessages()).toContain('An index with the same name already exists.');
expect(followerIndexPage.getFormErrorMessages())
.toContain('An index with the same name already exists.');
});
});
});
Expand Down Expand Up @@ -258,15 +242,15 @@ describe('Create Follower index', () => {
test('should have a toggle to activate advanced settings', () => {
const expectDoesNotExist = (testSubject) => {
try {
expect(exists(testSubject)).toBe(false);
expect(followerIndexPage.find(testSubject).length).toBe(0);
} catch {
throw new Error(`The advanced field "${testSubject}" exists.`);
throw new Error(`The advanced field "${testSubject}" .`);
}
};

const expectDoesExist = (testSubject) => {
try {
expect(exists(testSubject)).toBe(true);
expect(followerIndexPage.find(testSubject).length).toBe(1);
} catch {
throw new Error(`The advanced field "${testSubject}" does not exist.`);
}
Expand All @@ -275,26 +259,26 @@ describe('Create Follower index', () => {
// Make sure no advanced settings is visible
Object.keys(advancedSettingsInputFields).forEach(expectDoesNotExist);

toggleAdvancedSettings();
followerIndexPage.setAdvancedSettingsVisible();

// Make sure no advanced settings is visible
// Make sure all advanced settings are visible
Object.keys(advancedSettingsInputFields).forEach(expectDoesExist);
});

test('should set the correct default value for each advanced setting', () => {
toggleAdvancedSettings();
followerIndexPage.setAdvancedSettingsVisible();

Object.entries(advancedSettingsInputFields).forEach(([testSubject, data]) => {
expect(find(testSubject).props().value).toBe(data.default);
expect(followerIndexPage.find(testSubject).props().value).toBe(data.default);
});
});

test('should set number input field for numeric advanced settings', () => {
toggleAdvancedSettings();
followerIndexPage.setAdvancedSettingsVisible();

Object.entries(advancedSettingsInputFields).forEach(([testSubject, data]) => {
if (data.type === 'number') {
expect(find(testSubject).props().type).toBe('number');
expect(followerIndexPage.find(testSubject).props().type).toBe('number');
}
});
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import sinon from 'sinon';

import { nextTick } from '../../../../test_utils';
import { FollowerIndexAdd } from '../../public/app/sections/follower_index_add';
// import { RemoteClustersFormField } from '../../public/app/components';

// import { INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE } from '../../../../../src/legacy/ui/public/index_patterns';
import routing from '../../public/app/services/routing';

import { registerHttpRequestMockHelpers } from './test_helpers';
import { setup } from './follower_index_form.page_object_v2';

jest.mock('ui/chrome', () => ({
addBasePath: (path) => path || 'api/cross_cluster_replication',
breadcrumbs: { set: () => {} },
}));

jest.mock('ui/index_patterns', () => {
const { INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE } =
jest.requireActual('../../../../../src/legacy/ui/public/index_patterns/constants');
const { validateIndexPattern, ILLEGAL_CHARACTERS, CONTAINS_SPACES } =
jest.requireActual('../../../../../src/legacy/ui/public/index_patterns/validate/validate_index_pattern');
return { INDEX_PATTERN_ILLEGAL_CHARACTERS_VISIBLE, validateIndexPattern, ILLEGAL_CHARACTERS, CONTAINS_SPACES };
});

describe('Create Follower index', () => {
let server;
let setLoadRemoteClustersResponse;
let exists;
let find;
let component;
let form;
let actions;

beforeEach(() => {
server = sinon.fakeServer.create();
server.respondImmediately = true;

// Register helpers to mock Http Requests
({
setLoadRemoteClustersResponse,
} = registerHttpRequestMockHelpers(server));

// Set "default" mock responses by not providing any arguments
setLoadRemoteClustersResponse();

// Mock all HTTP Requests that have not been handled previously
server.respondWith([200, {}, '']);

({ component, exists, find, form, actions } = setup(FollowerIndexAdd, {}, {
memoryRouter: {
onRouter: (router) => routing.reactRouter = router
}
}));
});

describe('on component mount', () => {
test('should display a "loading remote clusters" indicator', () => {
expect(exists('loadingRemoteClusters')).toBe(true);
expect(find('loadingRemoteClusters').text()).toBe('Loading remote clusters…');
});

test('should have a link to the documentation', () => {
expect(exists('docsButton')).toBe(true);
});
});

describe('when remote clusters are loaded', () => {
beforeEach(async () => {
await nextTick(); // We need to wait next tick for the mock server response to comes in
component.update();
});

test('should display the Follower index form', async () => {
expect(exists('form')).toBe(true);
});

test('should display errors and disable the save button when clicking "save" without filling the form', () => {
expect(form.getErrorsMessages().length).toBe(0);
expect(find('saveFormButton').props().disabled).toBe(false);

actions.clickSave();

expect(exists('formError')).toBe(true);
expect(form.getErrorsMessages()).toEqual([
'Leader index is required.',
'Name is required.'
]);
expect(find('saveFormButton').props().disabled).toBe(true);
});
});

// ....
});
Loading