Refactor tests to follow file pattern (#36434)

This commit is contained in:
Sébastien Loix 2019-05-22 10:44:22 +08:00 committed by GitHub
parent 14b3b2f543
commit a189392c77
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 258 additions and 217 deletions

View file

@ -0,0 +1,49 @@
/*
* 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 { API_BASE_PATH } from './constants';
import { getRandomString } from './lib';
import { getAutoFollowIndexPayload } from './fixtures';
export const registerHelpers = (supertest) => {
let autoFollowPatternsCreated = [];
const loadAutoFollowPatterns = () => supertest.get(`${API_BASE_PATH}/auto_follow_patterns`);
const getAutoFollowPattern = (name) => supertest.get(`${API_BASE_PATH}/auto_follow_patterns/${name}`);
const createAutoFollowPattern = (name = getRandomString(), payload = getAutoFollowIndexPayload()) => {
autoFollowPatternsCreated.push(name);
return supertest
.post(`${API_BASE_PATH}/auto_follow_patterns`)
.set('kbn-xsrf', 'xxx')
.send({ ...payload, id: name });
};
const deleteAutoFollowPattern = (name) => {
autoFollowPatternsCreated = autoFollowPatternsCreated.filter(c => c !== name);
return supertest
.delete(`${API_BASE_PATH}/auto_follow_patterns/${name}`)
.set('kbn-xsrf', 'xxx');
};
const deleteAllAutoFollowPatterns = () => (
Promise.all(autoFollowPatternsCreated.map(deleteAutoFollowPattern))
.then(() => {
autoFollowPatternsCreated = [];
})
);
return {
loadAutoFollowPatterns,
getAutoFollowPattern,
createAutoFollowPattern,
deleteAutoFollowPattern,
deleteAllAutoFollowPatterns
};
};

View file

@ -6,109 +6,73 @@
import expect from '@kbn/expect';
import { API_BASE_PATH } from './constants';
import { initClusterHelpers, getRandomString } from './lib';
const AUTO_FOLLOW_PATTERNS_API_BASE_PATH = API_BASE_PATH + '/auto_follow_patterns';
import { getRandomString } from './lib';
import { getAutoFollowIndexPayload } from './fixtures';
import { registerHelpers as registerRemoteClustersHelpers } from './remote_clusters.helpers';
import { registerHelpers as registerAutoFollowPatternHelpers } from './auto_follow_pattern.helpers';
export default function ({ getService }) {
let autoFollowPatternsCreated = [];
const supertest = getService('supertest');
const { CLUSTER_NAME, addCluster, deleteAllClusters } = initClusterHelpers(supertest);
const deleteAutoFollowPatternRequest = (name) => (
supertest
.delete(`${AUTO_FOLLOW_PATTERNS_API_BASE_PATH}/${name}`)
.set('kbn-xsrf', 'xxx')
);
const getAutoFollowIndexPayload = () => ({
remoteCluster: CLUSTER_NAME,
leaderIndexPatterns: [ 'leader-*'],
followIndexPattern: '{{leader_index}}_follower'
});
const createAutoFollowIndexRequest = (name = getRandomString(), payload = getAutoFollowIndexPayload()) => {
autoFollowPatternsCreated.push(name);
return supertest
.post(AUTO_FOLLOW_PATTERNS_API_BASE_PATH)
.set('kbn-xsrf', 'xxx')
.send({ ...payload, id: name });
};
const cleanUp = () => (
Promise.all([deleteAllClusters(), ...autoFollowPatternsCreated.map(deleteAutoFollowPatternRequest)])
.then(() => {
autoFollowPatternsCreated = [];
})
);
const { addCluster, deleteAllClusters } = registerRemoteClustersHelpers(supertest);
const {
loadAutoFollowPatterns,
getAutoFollowPattern,
createAutoFollowPattern,
deleteAllAutoFollowPatterns
} = registerAutoFollowPatternHelpers(supertest);
describe('auto follow patterns', () => {
afterEach(() => {
return cleanUp();
});
after(() => deleteAllAutoFollowPatterns().then(deleteAllClusters));
describe('list()', () => {
it('should return an empty object when there are no auto follow patterns', async () => {
const uri = `${AUTO_FOLLOW_PATTERNS_API_BASE_PATH}`;
const { body } = await supertest
.get(uri)
.expect(200);
const { body } = await loadAutoFollowPatterns().expect(200);
expect(body).to.eql({ patterns: [] });
});
});
describe('create()', () => {
let payload;
beforeEach(() => {
payload = getAutoFollowIndexPayload();
});
describe('when remote cluster does not exist', () => {
it('should throw a 404 error when cluster is unknown', async () => {
const payload = getAutoFollowIndexPayload();
payload.remoteCluster = 'unknown-cluster';
const { body } = await createAutoFollowIndexRequest(undefined, payload).expect(404);
const { body } = await createAutoFollowPattern(undefined, payload).expect(404);
expect(body.cause[0]).to.contain('no such remote cluster');
});
it('should create an auto-follow pattern when cluster is known', async () => {
await addCluster();
const name = getRandomString();
const { body } = await createAutoFollowIndexRequest(name).expect(200);
expect(body.acknowledged).to.eql(true);
});
});
describe('get()', () => {
it('should return a 404 when the auto-follow pattern is not found', async () => {
const name = getRandomString();
const { body } = await supertest
.get(`${AUTO_FOLLOW_PATTERNS_API_BASE_PATH}/${name}`)
.expect(404);
describe('when remote cluster exists', () => {
before(() => addCluster());
expect(body.cause).not.to.be(undefined);
describe('create()', () => {
it('should create an auto-follow pattern when cluster is known', async () => {
const name = getRandomString();
const { body } = await createAutoFollowPattern(name).expect(200);
expect(body.acknowledged).to.eql(true);
});
});
it('should return an auto-follow pattern that was created', async () => {
const name = getRandomString();
const autoFollowPattern = getAutoFollowIndexPayload();
describe('get()', () => {
it('should return a 404 when the auto-follow pattern is not found', async () => {
const name = getRandomString();
const { body } = await getAutoFollowPattern(name).expect(404);
await addCluster();
await createAutoFollowIndexRequest(name, autoFollowPattern);
expect(body.cause).not.to.be(undefined);
});
const { body } = await supertest
.get(`${AUTO_FOLLOW_PATTERNS_API_BASE_PATH}/${name}`)
.expect(200);
it('should return an auto-follow pattern that was created', async () => {
const name = getRandomString();
const autoFollowPattern = getAutoFollowIndexPayload();
expect(body).to.eql({ ...autoFollowPattern, name });
await createAutoFollowPattern(name, autoFollowPattern);
const { body } = await getAutoFollowPattern(name).expect(200);
expect(body).to.eql({ ...autoFollowPattern, name });
});
});
});
});

View file

@ -6,3 +6,4 @@
export const API_BASE_PATH = '/api/cross_cluster_replication';
export const REMOTE_CLUSTERS_API_BASE_PATH = '/api/remote_clusters';
export const REMOTE_CLUSTER_NAME = 'ccr-api-integration-tests-cluster';

View file

@ -0,0 +1,23 @@
/*
* 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 { REMOTE_CLUSTER_NAME } from './constants';
import { getRandomString } from './lib';
export const getAutoFollowIndexPayload = (remoteCluster = REMOTE_CLUSTER_NAME) => ({
remoteCluster,
leaderIndexPatterns: [ 'leader-*'],
followIndexPattern: '{{leader_index}}_follower'
});
export const getFollowerIndexPayload = (
leaderIndexName = getRandomString(),
remoteCluster = REMOTE_CLUSTER_NAME,
advancedSettings = {}) => ({
remoteCluster,
leaderIndex: leaderIndexName,
...advancedSettings,
});

View file

@ -0,0 +1,55 @@
/*
* 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 { API_BASE_PATH } from './constants';
import { getRandomString } from './lib';
import { getFollowerIndexPayload } from './fixtures';
export const registerHelpers = (supertest) => {
let followerIndicesCreated = [];
const loadFollowerIndices = () => supertest.get(`${API_BASE_PATH}/follower_indices`);
const getFollowerIndex = (name) => supertest.get(`${API_BASE_PATH}/follower_indices/${name}`);
const createFollowerIndex = (name = getRandomString(), payload = getFollowerIndexPayload()) => {
followerIndicesCreated.push(name);
return supertest
.post(`${API_BASE_PATH}/follower_indices`)
.set('kbn-xsrf', 'xxx')
.send({ ...payload, name });
};
const unfollowLeaderIndex = (followerIndex) => {
const followerIndices = Array.isArray(followerIndex) ? followerIndex : [followerIndex];
const followerIndicesToEncodedString = followerIndices.map(index => encodeURIComponent(index)).join(',');
return supertest
.put(`${API_BASE_PATH}/follower_indices/${followerIndicesToEncodedString}/unfollow`)
.set('kbn-xsrf', 'xxx');
};
const unfollowAll = (indices = followerIndicesCreated) => (
unfollowLeaderIndex(indices)
.then(loadFollowerIndices)
.then(({ body }) => {
if (body.indices.length) {
// There are still some index left to delete. Call recursively
// until all follower indices are removed.
return unfollowAll(body.indices.map(i => i.name));
}
followerIndicesCreated = [];
})
);
return {
loadFollowerIndices,
getFollowerIndex,
createFollowerIndex,
unfollowAll,
};
};

View file

@ -7,73 +7,36 @@
import expect from '@kbn/expect';
import { FOLLOWER_INDEX_ADVANCED_SETTINGS } from '../../../../../plugins/cross_cluster_replication/common/constants';
import { API_BASE_PATH } from './constants';
import { initClusterHelpers, initElasticsearchIndicesHelpers, getRandomString } from './lib';
const FOLLOWER_INDICES_API_BASE_PATH = API_BASE_PATH + '/follower_indices';
import { getFollowerIndexPayload } from './fixtures';
import { registerHelpers as registerElasticSearchHelpers, getRandomString } from './lib';
import { registerHelpers as registerRemoteClustersHelpers } from './remote_clusters.helpers';
import { registerHelpers as registerFollowerIndicesnHelpers } from './follower_indices.helpers';
export default function ({ getService }) {
let followerIndicesCreated = [];
const supertest = getService('supertest');
const es = getService('es');
const { CLUSTER_NAME, addCluster, deleteAllClusters } = initClusterHelpers(supertest);
const { createIndex, deleteAllIndices } = initElasticsearchIndicesHelpers(es);
const { addCluster, deleteAllClusters } = registerRemoteClustersHelpers(supertest);
const {
loadFollowerIndices,
getFollowerIndex,
createFollowerIndex,
unfollowAll,
} = registerFollowerIndicesnHelpers(supertest);
const getFollowerIndexPayload = (leaderIndexName = getRandomString(), remoteCluster = CLUSTER_NAME, advancedSettings = {}) => ({
remoteCluster,
leaderIndex: leaderIndexName,
...advancedSettings,
});
const { createIndex, deleteAllIndices } = registerElasticSearchHelpers(es);
const createFollowerIndexRequest = (name = getRandomString(), payload = getFollowerIndexPayload()) => {
followerIndicesCreated.push(name);
return supertest
.post(FOLLOWER_INDICES_API_BASE_PATH)
.set('kbn-xsrf', 'xxx')
.send({ ...payload, name });
};
const deleteFollowerIndicesCreated = () => {
const ids = followerIndicesCreated.map(_id => encodeURIComponent(_id)).join(',');
return supertest
.put(`${FOLLOWER_INDICES_API_BASE_PATH}/${ids}/unfollow`)
.set('kbn-xsrf', 'xxx')
.then(() => supertest.get(FOLLOWER_INDICES_API_BASE_PATH))
.then(({ body }) => {
if (body.indices.length) {
// There are still some index left to delete. Call recursively
// until all follower indices are removed.
followerIndicesCreated = body.indices.map(i => i.name);
return deleteFollowerIndicesCreated();
}
followerIndicesCreated = [];
});
};
const cleanUp = () => (
Promise.all([
deleteAllClusters(),
deleteAllIndices(),
deleteFollowerIndicesCreated()
]).catch(err => {
console.log('ERROR cleaning up...');
console.log(err);
})
);
// Flaky tests; possible race condition with ES.
describe('follower indices', () => {
before(() => addCluster());
after(() => cleanUp());
after(() => Promise.all([
deleteAllIndices(),
unfollowAll().then(deleteAllClusters)
]));
describe('list()', () => {
it('should return an empty array when there are no follower indices', async () => {
const { body } = await supertest
.get(FOLLOWER_INDICES_API_BASE_PATH)
.expect(200);
const { body } = await loadFollowerIndices().expect(200);
expect(body).to.eql({ indices: [] });
});
@ -84,13 +47,13 @@ export default function ({ getService }) {
const payload = getFollowerIndexPayload();
payload.remoteCluster = 'unknown-cluster';
const { body } = await createFollowerIndexRequest(undefined, payload).expect(404);
const { body } = await createFollowerIndex(undefined, payload).expect(404);
expect(body.cause[0]).to.contain('no such remote cluster');
});
it('should throw a 404 error trying to follow an unknown index', async () => {
const payload = getFollowerIndexPayload();
const { body } = await createFollowerIndexRequest(undefined, payload).expect(404);
const { body } = await createFollowerIndex(undefined, payload).expect(404);
expect(body.cause[0]).to.contain('no such index');
});
@ -99,7 +62,7 @@ export default function ({ getService }) {
const leaderIndex = await createIndex();
const payload = getFollowerIndexPayload(leaderIndex);
const { body } = await createFollowerIndexRequest(undefined, payload).expect(200);
const { body } = await createFollowerIndex(undefined, payload).expect(200);
// There is a race condition in which Elasticsearch can respond without acknowledging,
// i.e. `body .follow_index_shards_acked` is sometimes true and sometimes false.
@ -111,9 +74,7 @@ export default function ({ getService }) {
describe('get()', () => {
it('should return a 404 when the follower index does not exist', async () => {
const name = getRandomString();
const { body } = await supertest
.get(`${FOLLOWER_INDICES_API_BASE_PATH}/${name}`)
.expect(404);
const { body } = await getFollowerIndex(name).expect(404);
expect(body.cause[0]).to.contain('no such index');
});
@ -123,11 +84,9 @@ export default function ({ getService }) {
const name = getRandomString();
const payload = getFollowerIndexPayload(leaderIndex);
await createFollowerIndexRequest(name, payload).expect(200);
await createFollowerIndex(name, payload);
const { body } = await supertest
.get(`${FOLLOWER_INDICES_API_BASE_PATH}/${name}`)
.expect(200);
const { body } = await getFollowerIndex(name).expect(200);
expect(body.leaderIndex).to.eql(leaderIndex);
expect(body.remoteCluster).to.eql(payload.remoteCluster);
@ -137,29 +96,29 @@ export default function ({ getService }) {
describe('Advanced settings', () => {
it('hard-coded values should match Elasticsearch default values', async () => {
/**
* To make sure that the hard-coded values in the client match the default
* from Elasticsearch, we will create a follower index without any advanced settings.
* When we then retrieve the follower index it will have all the advanced settings
* coming from ES. We can then compare those settings with our hard-coded values.
*/
* To make sure that the hard-coded values in the client match the default
* from Elasticsearch, we will create a follower index without any advanced settings.
* When we then retrieve the follower index it will have all the advanced settings
* coming from ES. We can then compare those settings with our hard-coded values.
*/
const leaderIndex = await createIndex();
const name = getRandomString();
const payload = getFollowerIndexPayload(leaderIndex);
await createFollowerIndexRequest(name, payload).expect(200);
await createFollowerIndex(name, payload);
const { body } = await supertest.get(`${FOLLOWER_INDICES_API_BASE_PATH}/${name}`);
const { body } = await getFollowerIndex(name);
// We "only" check the settings if the follower index is in "active" state.
// It can happen that a race condition returns the index as "paused". In this case
// no advanced settings value is returned by ES.
if (body.status === 'active') {
Object.entries(FOLLOWER_INDEX_ADVANCED_SETTINGS).forEach(([key, value]) => {
expect(value).to.eql(body[key]);
});
} else {
expect(true).eql(true);
if (body.status !== 'active') {
return;
}
Object.entries(FOLLOWER_INDEX_ADVANCED_SETTINGS).forEach(([key, value]) => {
expect(value).to.eql(body[key]);
});
});
});
});

View file

@ -1,56 +0,0 @@
/*
* 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 { getRandomString } from './random';
import { REMOTE_CLUSTERS_API_BASE_PATH } from '../constants';
const CLUSTER_NAME = `test-${getRandomString()}`;
/**
* Helpers for the CCR application to easily create and delete
* Remote clusters for the tests.
* @param {Supertest} supertest The supertest instance
*/
export const initClusterHelpers = (supertest) => {
let clusters = [];
const addCluster = (name = CLUSTER_NAME) => {
clusters.push(name);
return (
supertest
.post(`${REMOTE_CLUSTERS_API_BASE_PATH}`)
.set('kbn-xsrf', 'xxx')
.send({
'name': name,
'seeds': [
'localhost:9300'
],
'skipUnavailable': true,
})
);
};
const deleteCluster = (name = CLUSTER_NAME) => {
clusters = clusters.filter(c => c !== name);
return (
supertest
.delete(`${REMOTE_CLUSTERS_API_BASE_PATH}/${name}`)
.set('kbn-xsrf', 'xxx')
);
};
const deleteAllClusters = () => (
Promise.all(clusters.map(deleteCluster)).then(() => {
clusters = [];
})
);
return ({
CLUSTER_NAME,
addCluster,
deleteCluster,
deleteAllClusters,
});
};

View file

@ -10,7 +10,7 @@ import { getRandomString } from './random';
* during our tests.
* @param {ElasticsearchClient} es The Elasticsearch client instance
*/
export const initElasticsearchIndicesHelpers = (es) => {
export const registerHelpers = (es) => {
let indicesCreated = [];
const createIndex = (index = getRandomString()) => {

View file

@ -5,12 +5,8 @@
*/
export {
initClusterHelpers
} from './clusters';
export {
initElasticsearchIndicesHelpers
} from './es_index';
registerHelpers
} from './elasticsearch';
export {
getRandomString,

View file

@ -0,0 +1,50 @@
/*
* 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 { REMOTE_CLUSTER_NAME, REMOTE_CLUSTERS_API_BASE_PATH } from './constants';
/**
* Helpers for the CCR application to easily create and delete
* Remote clusters for the tests.
* @param {Supertest} supertest The supertest instance
*/
export const registerHelpers = (supertest) => {
let remoteClustersCreated = [];
const addCluster = (name = REMOTE_CLUSTER_NAME) => {
remoteClustersCreated.push(name);
return supertest
.post(`${REMOTE_CLUSTERS_API_BASE_PATH}`)
.set('kbn-xsrf', 'xxx')
.send({
'name': name,
'seeds': [
'localhost:9300'
],
'skipUnavailable': true,
});
};
const deleteCluster = (name = REMOTE_CLUSTER_NAME) => {
remoteClustersCreated = remoteClustersCreated.filter(c => c !== name);
return supertest
.delete(`${REMOTE_CLUSTERS_API_BASE_PATH}/${name}`)
.set('kbn-xsrf', 'xxx');
};
const deleteAllClusters = () => (
Promise.all(remoteClustersCreated.map(deleteCluster)).then(() => {
remoteClustersCreated = [];
})
);
return ({
addCluster,
deleteCluster,
deleteAllClusters,
});
};