Fix advanced settings API integration tests on cloud (#84110) (#84208)

This PR fixes the advanced settings feature controls API integration tests for cloud and moves some deployment helper methods to a separate service.
This commit is contained in:
Robert Oskamp 2020-11-24 16:03:31 +01:00 committed by GitHub
parent 30ca396a63
commit 532a9daab2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 159 additions and 100 deletions

View file

@ -0,0 +1,78 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { get } from 'lodash';
import fetch from 'node-fetch';
// @ts-ignore not TS yet
import getUrl from '../../../src/test_utils/get_url';
import { FtrProviderContext } from '../ftr_provider_context';
export function DeploymentProvider({ getService }: FtrProviderContext) {
const config = getService('config');
return {
/**
* Returns Kibana host URL
*/
getHostPort() {
return getUrl.baseUrl(config.get('servers.kibana'));
},
/**
* Returns ES host URL
*/
getEsHostPort() {
return getUrl.baseUrl(config.get('servers.elasticsearch'));
},
/**
* Helper to detect an OSS licensed Kibana
* Useful for functional testing in cloud environment
*/
async isOss() {
const baseUrl = this.getEsHostPort();
const username = config.get('servers.elasticsearch.username');
const password = config.get('servers.elasticsearch.password');
const response = await fetch(baseUrl + '/_xpack', {
method: 'get',
headers: {
'Content-Type': 'application/json',
Authorization: 'Basic ' + Buffer.from(username + ':' + password).toString('base64'),
},
});
return response.status !== 200;
},
async isCloud(): Promise<boolean> {
const baseUrl = this.getHostPort();
const username = config.get('servers.kibana.username');
const password = config.get('servers.kibana.password');
const response = await fetch(baseUrl + '/api/stats?extended', {
method: 'get',
headers: {
'Content-Type': 'application/json',
Authorization: 'Basic ' + Buffer.from(username + ':' + password).toString('base64'),
},
});
const data = await response.json();
return get(data, 'usage.cloud.is_cloud_enabled', false);
},
};
}

View file

@ -17,6 +17,7 @@
* under the License.
*/
import { DeploymentProvider } from './deployment';
import { LegacyEsProvider } from './legacy_es';
import { ElasticsearchProvider } from './elasticsearch';
import { EsArchiverProvider } from './es_archiver';
@ -26,6 +27,7 @@ import { RandomnessProvider } from './randomness';
import { SecurityServiceProvider } from './security';
export const services = {
deployment: DeploymentProvider,
legacyEs: LegacyEsProvider,
es: ElasticsearchProvider,
esArchiver: EsArchiverProvider,

View file

@ -29,6 +29,7 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide
const browser = getService('browser');
const PageObjects = getPageObjects(['common']);
const log = getService('log');
const deployment = getService('deployment');
describe('TODO app', () => {
describe("TODO app with browser history (platform's ScopedHistory)", async () => {
@ -36,7 +37,7 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide
let base: string;
before(async () => {
base = await PageObjects.common.getHostPort();
base = await deployment.getHostPort();
await PageObjects.common.navigateToApp(appId, { insertTimestamp: false });
});

View file

@ -34,6 +34,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
const browser = getService('browser');
const fieldName = 'clientip';
const deployment = getService('deployment');
const clickFieldAndCheckUrl = async (fieldLink: WebElementWrapper) => {
const fieldValue = await fieldLink.getVisibleText();
@ -42,7 +43,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
expect(windowHandlers.length).to.equal(2);
await browser.switchToWindow(windowHandlers[1]);
const currentUrl = await browser.getCurrentUrl();
const fieldUrl = common.getHostPort() + '/app/' + fieldValue;
const fieldUrl = deployment.getHostPort() + '/app/' + fieldValue;
expect(currentUrl).to.equal(fieldUrl);
};

View file

@ -27,13 +27,14 @@ export default function ({ getService, getPageObjects }) {
const PageObjects = getPageObjects(['common', 'discover', 'share', 'timePicker']);
const browser = getService('browser');
const toasts = getService('toasts');
const deployment = getService('deployment');
// FLAKY: https://github.com/elastic/kibana/issues/80104
describe.skip('shared links', function describeIndexTests() {
let baseUrl;
async function setup({ storeStateInSessionStorage }) {
baseUrl = PageObjects.common.getHostPort();
baseUrl = deployment.getHostPort();
log.debug('baseUrl = ' + baseUrl);
// browsers don't show the ':port' if it's 80 or 443 so we have to
// remove that part so we can get a match in the tests.

View file

@ -22,7 +22,8 @@ import { FtrProviderContext } from '../../ftr_provider_context';
export default function ({ getService, getPageObjects }: FtrProviderContext) {
const globalNav = getService('globalNav');
const PageObjects = getPageObjects(['common', 'newsfeed']);
const deployment = getService('deployment');
const PageObjects = getPageObjects(['newsfeed']);
describe('Newsfeed', () => {
before(async () => {
@ -48,7 +49,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
it('shows all news from newsfeed', async () => {
const objects = await PageObjects.newsfeed.getNewsfeedList();
if (await PageObjects.common.isOss()) {
if (await deployment.isOss()) {
expect(objects).to.eql([
'21 June 2019\nYou are functionally testing the newsfeed widget with fixtures!\nSee test/common/fixtures/plugins/newsfeed/newsfeed_simulation\nGeneric feed-viewer could go here',
'21 June 2019\nStaging too!\nHello world\nGeneric feed-viewer could go here',

View file

@ -44,6 +44,7 @@ export default function ({ getService, getPageObjects }) {
const inspector = getService('inspector');
const testSubjects = getService('testSubjects');
const filterBar = getService('filterBar');
const deployment = getService('deployment');
const PageObjects = getPageObjects([
'common',
'header',
@ -202,7 +203,7 @@ export default function ({ getService, getPageObjects }) {
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName);
await PageObjects.header.waitUntilLoadingHasFinished();
if (await PageObjects.common.isOss()) {
if (await deployment.isOss()) {
// OSS renders a vertical bar chart and we check the data in the Inspect panel
const expectedChartValues = [
['14', '31'],
@ -318,7 +319,7 @@ export default function ({ getService, getPageObjects }) {
it('should visualize scripted field in vertical bar chart', async function () {
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName2);
await PageObjects.header.waitUntilLoadingHasFinished();
if (await PageObjects.common.isOss()) {
if (await deployment.isOss()) {
// OSS renders a vertical bar chart and we check the data in the Inspect panel
await inspector.open();
await inspector.expectTableData([
@ -414,7 +415,7 @@ export default function ({ getService, getPageObjects }) {
it('should visualize scripted field in vertical bar chart', async function () {
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName2);
await PageObjects.header.waitUntilLoadingHasFinished();
if (await PageObjects.common.isOss()) {
if (await deployment.isOss()) {
// OSS renders a vertical bar chart and we check the data in the Inspect panel
await inspector.open();
await inspector.expectTableData([
@ -514,7 +515,7 @@ export default function ({ getService, getPageObjects }) {
await PageObjects.discover.clickFieldListItemVisualize(scriptedPainlessFieldName2);
await PageObjects.header.waitUntilLoadingHasFinished();
if (await PageObjects.common.isOss()) {
if (await deployment.isOss()) {
// OSS renders a vertical bar chart and we check the data in the Inspect panel
await inspector.open();
await inspector.setTablePageSize(50);

View file

@ -22,14 +22,15 @@ import expect from '@kbn/expect';
import { FtrProviderContext } from '../../ftr_provider_context';
export default function ({ getService, getPageObjects }: FtrProviderContext) {
const deployment = getService('deployment');
const log = getService('log');
const PageObjects = getPageObjects(['common', 'visualize']);
const PageObjects = getPageObjects(['visualize']);
let isOss = true;
describe('chart types', function () {
before(async function () {
log.debug('navigateToApp visualize');
isOss = await PageObjects.common.isOss();
isOss = await deployment.isOss();
await PageObjects.visualize.navigateToNewVisualization();
});

View file

@ -20,12 +20,12 @@
import { FtrProviderContext } from '../../ftr_provider_context.d';
import { UI_SETTINGS } from '../../../../src/plugins/data/common';
export default function ({ getService, getPageObjects, loadTestFile }: FtrProviderContext) {
export default function ({ getService, loadTestFile }: FtrProviderContext) {
const browser = getService('browser');
const log = getService('log');
const esArchiver = getService('esArchiver');
const kibanaServer = getService('kibanaServer');
const PageObjects = getPageObjects(['common']);
const deployment = getService('deployment');
let isOss = true;
describe('visualize app', () => {
@ -39,7 +39,7 @@ export default function ({ getService, getPageObjects, loadTestFile }: FtrProvid
defaultIndex: 'logstash-*',
[UI_SETTINGS.FORMAT_BYTES_DEFAULT_PATTERN]: '0,0.[000]b',
});
isOss = await PageObjects.common.isOss();
isOss = await deployment.isOss();
});
describe('', function () {

View file

@ -19,7 +19,6 @@
import { delay } from 'bluebird';
import expect from '@kbn/expect';
import { get } from 'lodash';
// @ts-ignore
import fetch from 'node-fetch';
import { FtrProviderContext } from '../ftr_provider_context';
@ -48,20 +47,6 @@ export function CommonPageProvider({ getService, getPageObjects }: FtrProviderCo
}
class CommonPage {
/**
* Returns Kibana host URL
*/
public getHostPort() {
return getUrl.baseUrl(config.get('servers.kibana'));
}
/**
* Returns ES host URL
*/
public getEsHostPort() {
return getUrl.baseUrl(config.get('servers.elasticsearch'));
}
/**
* Logins to Kibana as default user and navigates to provided app
* @param appUrl Kibana URL
@ -449,39 +434,6 @@ export function CommonPageProvider({ getService, getPageObjects }: FtrProviderCo
return await body.getVisibleText();
}
/**
* Helper to detect an OSS licensed Kibana
* Useful for functional testing in cloud environment
*/
async isOss() {
const baseUrl = this.getEsHostPort();
const username = config.get('servers.elasticsearch.username');
const password = config.get('servers.elasticsearch.password');
const response = await fetch(baseUrl + '/_xpack', {
method: 'get',
headers: {
'Content-Type': 'application/json',
Authorization: 'Basic ' + Buffer.from(username + ':' + password).toString('base64'),
},
});
return response.status !== 200;
}
async isCloud(): Promise<boolean> {
const baseUrl = this.getHostPort();
const username = config.get('servers.kibana.username');
const password = config.get('servers.kibana.password');
const response = await fetch(baseUrl + '/api/stats?extended', {
method: 'get',
headers: {
'Content-Type': 'application/json',
Authorization: 'Basic ' + Buffer.from(username + ':' + password).toString('base64'),
},
});
const data = await response.json();
return get(data, 'usage.cloud.is_cloud_enabled', false);
}
async waitForSaveModalToClose() {
log.debug('Waiting for save modal to close');
await retry.try(async () => {

View file

@ -23,6 +23,7 @@ export function HomePageProvider({ getService, getPageObjects }: FtrProviderCont
const testSubjects = getService('testSubjects');
const retry = getService('retry');
const find = getService('find');
const deployment = getService('deployment');
const PageObjects = getPageObjects(['common']);
let isOss = true;
@ -82,7 +83,7 @@ export function HomePageProvider({ getService, getPageObjects }: FtrProviderCont
async launchSampleDashboard(id: string) {
await this.launchSampleDataSet(id);
isOss = await PageObjects.common.isOss();
isOss = await deployment.isOss();
if (!isOss) {
await find.clickByLinkText('Dashboard');
}

View file

@ -28,6 +28,7 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide
const testSubjects = getService('testSubjects');
const find = getService('find');
const retry = getService('retry');
const deployment = getService('deployment');
const loadingScreenNotShown = async () =>
expect(await testSubjects.exists('kbnLoadingMessage')).to.be(false);
@ -55,7 +56,7 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide
};
const navigateTo = async (path: string) =>
await browser.navigateTo(`${PageObjects.common.getHostPort()}${path}`);
await browser.navigateTo(`${deployment.getHostPort()}${path}`);
describe('ui applications', function describeIndexTests() {
before(async () => {

View file

@ -32,15 +32,15 @@ declare global {
}
}
export default function ({ getService, getPageObjects }: PluginFunctionalProviderContext) {
const PageObjects = getPageObjects(['common']);
export default function ({ getService }: PluginFunctionalProviderContext) {
const appsMenu = getService('appsMenu');
const browser = getService('browser');
const deployment = getService('deployment');
const find = getService('find');
const testSubjects = getService('testSubjects');
const navigateTo = async (path: string) =>
await browser.navigateTo(`${PageObjects.common.getHostPort()}${path}`);
await browser.navigateTo(`${deployment.getHostPort()}${path}`);
const navigateToApp = async (title: string) => {
await appsMenu.clickLink(title);
return browser.execute(() => {

View file

@ -19,15 +19,14 @@
import expect from '@kbn/expect';
import { PluginFunctionalProviderContext } from '../../services';
export default function ({ getService, getPageObjects }: PluginFunctionalProviderContext) {
const PageObjects = getPageObjects(['common']);
export default function ({ getService }: PluginFunctionalProviderContext) {
const browser = getService('browser');
const deployment = getService('deployment');
const testSubjects = getService('testSubjects');
describe.skip('top nav', function describeIndexTests() {
before(async () => {
const url = `${PageObjects.common.getHostPort()}/app/kbn_tp_top_nav/`;
const url = `${deployment.getHostPort()}/app/kbn_tp_top_nav/`;
await browser.get(url);
});

View file

@ -13,6 +13,27 @@ export default function featureControlsTests({ getService }: FtrProviderContext)
const supertest: SuperTest<any> = getService('supertestWithoutAuth');
const security = getService('security');
const spaces = getService('spaces');
const deployment = getService('deployment');
async function expectTelemetryResponse(result: any, expectSuccess: boolean) {
if ((await deployment.isCloud()) === true) {
// Cloud deployments don't allow to change the opt-in status
expectTelemetryCloud400(result);
} else {
if (expectSuccess === true) {
expectResponse(result);
} else {
expect403(result);
}
}
}
const expectTelemetryCloud400 = (result: any) => {
expect(result.error).to.be(undefined);
expect(result.response).not.to.be(undefined);
expect(result.response).to.have.property('statusCode', 400);
expect(result.response.body.message).to.be('{"error":"Not allowed to change Opt-in Status."}');
};
const expect403 = (result: any) => {
expect(result.error).to.be(undefined);
@ -21,16 +42,9 @@ export default function featureControlsTests({ getService }: FtrProviderContext)
};
const expectResponse = (result: any) => {
if (result.response && result.response.statusCode === 400) {
// expect a change of telemetry settings to fail in cloud environment
expect(result.response.body.message).to.be(
'{"error":"Not allowed to change Opt-in Status."}'
);
} else {
expect(result.error).to.be(undefined);
expect(result.response).not.to.be(undefined);
expect(result.response).to.have.property('statusCode', 200);
}
expect(result.error).to.be(undefined);
expect(result.response).not.to.be(undefined);
expect(result.response).to.have.property('statusCode', 200);
};
async function saveAdvancedSetting(username: string, password: string, spaceId?: string) {
@ -83,7 +97,7 @@ export default function featureControlsTests({ getService }: FtrProviderContext)
expectResponse(regularSettingResult);
const telemetryResult = await saveTelemetrySetting(username, password);
expectResponse(telemetryResult);
expectTelemetryResponse(telemetryResult, true);
} finally {
await security.role.delete(roleName);
await security.user.delete(username);
@ -115,7 +129,7 @@ export default function featureControlsTests({ getService }: FtrProviderContext)
expect403(regularSettingResult);
const telemetryResult = await saveTelemetrySetting(username, password);
expect403(telemetryResult);
expectTelemetryResponse(telemetryResult, false);
} finally {
await security.role.delete(roleName);
await security.user.delete(username);
@ -189,7 +203,7 @@ export default function featureControlsTests({ getService }: FtrProviderContext)
expectResponse(regularSettingResult);
const telemetryResult = await saveTelemetrySetting(username, password, space1Id);
expectResponse(telemetryResult);
expectTelemetryResponse(telemetryResult, true);
});
it(`user_1 can only save telemetry in space_2`, async () => {
@ -197,7 +211,7 @@ export default function featureControlsTests({ getService }: FtrProviderContext)
expect403(regularSettingResult);
const telemetryResult = await saveTelemetrySetting(username, password, space2Id);
expectResponse(telemetryResult);
expectTelemetryResponse(telemetryResult, true);
});
it(`user_1 can't save either settings or telemetry in space_3`, async () => {
@ -205,7 +219,7 @@ export default function featureControlsTests({ getService }: FtrProviderContext)
expect403(regularSettingResult);
const telemetryResult = await saveTelemetrySetting(username, password, space3Id);
expect403(telemetryResult);
expectTelemetryResponse(telemetryResult, false);
});
});
});

View file

@ -8,6 +8,7 @@ import expect from '@kbn/expect';
import { getLifecycleMethods } from '../_get_lifecycle_methods';
export default function ({ getService, getPageObjects }) {
const deployment = getService('deployment');
const setupMode = getService('monitoringSetupMode');
const PageObjects = getPageObjects(['common', 'console']);
@ -39,7 +40,7 @@ export default function ({ getService, getPageObjects }) {
});
it('should not show metricbeat migration if cloud', async () => {
const isCloud = await PageObjects.common.isCloud();
const isCloud = await deployment.isCloud();
expect(await setupMode.doesMetricbeatMigrationTooltipAppear()).to.be(!isCloud);
});

View file

@ -18,6 +18,7 @@ export function SecurityPageProvider({ getService, getPageObjects }: FtrProvider
const userMenu = getService('userMenu');
const comboBox = getService('comboBox');
const supertest = getService('supertestWithoutAuth');
const deployment = getService('deployment');
const PageObjects = getPageObjects(['common', 'header', 'error']);
interface LoginOptions {
@ -248,7 +249,7 @@ export function SecurityPageProvider({ getService, getPageObjects }: FtrProvider
}
log.debug('Redirecting to /logout to force the logout');
const url = PageObjects.common.getHostPort() + '/logout';
const url = deployment.getHostPort() + '/logout';
await browser.get(url);
log.debug('Waiting on the login form to appear');
await waitForLoginPage();

View file

@ -7,12 +7,12 @@
import expect from '@kbn/expect';
import { FtrProviderContext } from '../ftr_provider_context';
export function StatusPagePageProvider({ getService, getPageObjects }: FtrProviderContext) {
export function StatusPagePageProvider({ getService }: FtrProviderContext) {
const retry = getService('retry');
const log = getService('log');
const browser = getService('browser');
const find = getService('find');
const { common } = getPageObjects(['common']);
const deployment = getService('deployment');
class StatusPage {
async initTests() {
@ -21,7 +21,7 @@ export function StatusPagePageProvider({ getService, getPageObjects }: FtrProvid
async navigateToPage() {
return await retry.try(async () => {
const url = common.getHostPort() + '/status';
const url = deployment.getHostPort() + '/status';
log.info(`StatusPage:navigateToPage(): ${url}`);
await browser.get(url);
});

View file

@ -4,10 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/
export function MonitoringNoDataProvider({ getService, getPageObjects }) {
export function MonitoringNoDataProvider({ getService }) {
const deployment = getService('deployment');
const testSubjects = getService('testSubjects');
const retry = getService('retry');
const PageObjects = getPageObjects(['common']);
return new (class NoData {
async enableMonitoring() {
@ -15,7 +15,7 @@ export function MonitoringNoDataProvider({ getService, getPageObjects }) {
// so the UI does not give the user a choice between the two collection
// methods. So if we're on cloud, do not try and switch to internal collection
// as it's already the default
if (!(await PageObjects.common.isCloud())) {
if (!(await deployment.isCloud())) {
await testSubjects.click('useInternalCollection');
}
await testSubjects.click('enableCollectionEnabled');

View file

@ -12,6 +12,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const browser = getService('browser');
const security = getService('security');
const deployment = getService('deployment');
const PageObjects = getPageObjects(['security', 'common']);
describe('Authentication provider hint', function () {
@ -39,7 +40,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});
beforeEach(async () => {
await browser.get(`${PageObjects.common.getHostPort()}/login`);
await browser.get(`${deployment.getHostPort()}/login`);
await PageObjects.security.loginSelector.verifyLoginSelectorIsVisible();
});

View file

@ -13,6 +13,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
const testSubjects = getService('testSubjects');
const browser = getService('browser');
const security = getService('security');
const deployment = getService('deployment');
const PageObjects = getPageObjects(['security', 'common']);
describe('Basic functionality', function () {
@ -33,7 +34,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});
beforeEach(async () => {
await browser.get(`${PageObjects.common.getHostPort()}/login`);
await browser.get(`${deployment.getHostPort()}/login`);
await PageObjects.security.loginSelector.verifyLoginSelectorIsVisible();
});

View file

@ -12,6 +12,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const find = getService('find');
const browser = getService('browser');
const deployment = getService('deployment');
const PageObjects = getPageObjects(['common']);
describe('URL capture', function () {
@ -31,13 +32,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});
afterEach(async () => {
await browser.get(PageObjects.common.getHostPort() + '/logout');
await browser.get(deployment.getHostPort() + '/logout');
await PageObjects.common.waitUntilUrlIncludes('logged_out');
});
it('can login preserving original URL', async () => {
await browser.get(
PageObjects.common.getHostPort() + '/app/management/security/users#some=hash-value'
deployment.getHostPort() + '/app/management/security/users#some=hash-value'
);
await find.byCssSelector(

View file

@ -12,6 +12,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const find = getService('find');
const browser = getService('browser');
const deployment = getService('deployment');
const PageObjects = getPageObjects(['common']);
describe('URL capture', function () {
@ -31,13 +32,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});
afterEach(async () => {
await browser.get(PageObjects.common.getHostPort() + '/logout');
await browser.get(deployment.getHostPort() + '/logout');
await PageObjects.common.waitUntilUrlIncludes('logged_out');
});
it('can login preserving original URL', async () => {
await browser.get(
PageObjects.common.getHostPort() + '/app/management/security/users#some=hash-value'
deployment.getHostPort() + '/app/management/security/users#some=hash-value'
);
await find.byCssSelector(