mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Custom Branding] Add custom branding settings to Global settings (#150080)
## Summary This PR registers custom branding settings from the `custom_branding` plugin. Once registered, these settings can be viewed under "Global settings". UI changes: <img width="1761" alt="Screenshot 2023-02-06 at 19 59 19" src="https://user-images.githubusercontent.com/1937956/217060900-7e56c8e9-7d3d-4ac5-96b6-8a8a85d3c1c3.png"> I also removed the client-side version of the `custom_branding` plugin, as it's not needed. With this change, it became easier to test custom branding, so I made a few changes where logo was not showing properly or image size was wrong or test subjects were missing. I am working with @gchaps on the exact wording, so that might change. ### Checklist Delete any items that are not applicable to this PR. - [X] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [X] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [X] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [X] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [X] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) ~- [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)~ - [X] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [X] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Vadim Kibana <82822460+vadimkibana@users.noreply.github.com>
This commit is contained in:
parent
4e5595b92b
commit
a7293f62b5
25 changed files with 358 additions and 52 deletions
|
@ -359,3 +359,4 @@ enabled:
|
|||
- x-pack/performance/journeys/ecommerce_dashboard_saved_search_only.ts
|
||||
- x-pack/performance/journeys/ecommerce_dashboard_tsvb_gauge_only.ts
|
||||
- x-pack/performance/journeys/dashboard_listing_page.ts
|
||||
- x-pack/test/custom_branding/config.ts
|
||||
|
|
|
@ -129,6 +129,7 @@ const AppLoadingPlaceholder: FC<{ showPlainSpinner: boolean }> = ({ showPlainSpi
|
|||
return (
|
||||
<EuiLoadingSpinner
|
||||
size={'xxl'}
|
||||
className="appContainer__loading"
|
||||
data-test-subj="appContainer-loadingSpinner"
|
||||
aria-label={i18n.translate('core.application.appContainer.loadingAriaLabel', {
|
||||
defaultMessage: 'Loading application',
|
||||
|
|
|
@ -24,6 +24,7 @@ exports[`kbnLoadingIndicator shows logo image when customLogo is set 1`] = `
|
|||
<EuiImage
|
||||
alt="logo"
|
||||
aria-label="User logo"
|
||||
data-test-subj="globalLoadingIndicator-hidden"
|
||||
size={24}
|
||||
src="customLogo"
|
||||
/>
|
||||
|
|
|
@ -104,7 +104,12 @@ export function HeaderLogo({ href, navigateToApp, loadingCount$, ...observables
|
|||
>
|
||||
<LoadingIndicator loadingCount$={loadingCount$!} customLogo={logo} />
|
||||
{customizedLogo ? (
|
||||
<img src={customizedLogo} width="200" height="84" alt="custom mark" />
|
||||
<img
|
||||
src={customizedLogo}
|
||||
className="chrHeaderLogo__mark"
|
||||
style={{ maxWidth: '200px', maxHeight: '84px' }}
|
||||
alt="custom mark"
|
||||
/>
|
||||
) : (
|
||||
<ElasticMark className="chrHeaderLogo__mark" aria-hidden={true} />
|
||||
)}
|
||||
|
|
|
@ -71,6 +71,7 @@ export class LoadingIndicator extends React.Component<LoadingIndicatorProps, { v
|
|||
const logoImage = this.props.customLogo ? (
|
||||
<EuiImage
|
||||
src={this.props.customLogo}
|
||||
data-test-subj={testSubj}
|
||||
size={24}
|
||||
alt="logo"
|
||||
aria-label={i18n.translate('core.ui.chrome.headerGlobalNav.customLogoAriaLabel', {
|
||||
|
|
|
@ -176,6 +176,7 @@ export class RenderingService {
|
|||
customBranding: {
|
||||
logo: branding?.logo,
|
||||
customizedLogo: branding?.customizedLogo,
|
||||
pageTitle: branding?.pageTitle,
|
||||
},
|
||||
csp: { warnLegacyBrowsers: http.csp.warnLegacyBrowsers },
|
||||
externalUrl: http.externalUrl,
|
||||
|
|
|
@ -23,7 +23,6 @@ pageLoadAssetSize:
|
|||
controls: 40000
|
||||
core: 435325
|
||||
crossClusterReplication: 65408
|
||||
customBranding: 16693
|
||||
customIntegrations: 22034
|
||||
dashboard: 82025
|
||||
dashboardEnhanced: 65646
|
||||
|
|
|
@ -36,6 +36,12 @@ export class SettingsPageObject extends FtrService {
|
|||
await this.testSubjects.existOrFail('managementSettingsTitle');
|
||||
}
|
||||
|
||||
async clickKibanaGlobalSettings() {
|
||||
await this.testSubjects.click('settings');
|
||||
await this.header.waitUntilLoadingHasFinished();
|
||||
await this.testSubjects.click('advancedSettingsTab-global-settings');
|
||||
}
|
||||
|
||||
async clickKibanaSavedObjects() {
|
||||
await this.testSubjects.click('objects');
|
||||
await this.savedObjects.waitTableIsLoaded();
|
||||
|
@ -134,6 +140,13 @@ export class SettingsPageObject extends FtrService {
|
|||
await this.header.waitUntilLoadingHasFinished();
|
||||
}
|
||||
|
||||
async setAdvancedSettingsImage(propertyName: string, path: string) {
|
||||
const input = await this.testSubjects.find(`advancedSetting-editField-${propertyName}`);
|
||||
await input.type(path);
|
||||
await this.testSubjects.click(`advancedSetting-saveButton`);
|
||||
await this.header.waitUntilLoadingHasFinished();
|
||||
}
|
||||
|
||||
async toggleAdvancedSettingCheckbox(propertyName: string, value?: boolean) {
|
||||
let curValue: string | undefined;
|
||||
if (value !== undefined) {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"plugin": {
|
||||
"id": "customBranding",
|
||||
"server": true,
|
||||
"browser": true,
|
||||
"browser": false,
|
||||
"requiredPlugins": [
|
||||
"licensing",
|
||||
"licenseApiGuard"
|
||||
|
|
|
@ -1,23 +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
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { AppMountParameters, CoreStart } from '@kbn/core/public';
|
||||
import { CustomBrandingApp } from './components/app';
|
||||
|
||||
export const renderApp = (
|
||||
{ notifications, http }: CoreStart,
|
||||
{ appBasePath, element }: AppMountParameters
|
||||
) => {
|
||||
ReactDOM.render(
|
||||
<CustomBrandingApp basename={appBasePath} notifications={notifications} http={http} />,
|
||||
element
|
||||
);
|
||||
|
||||
return () => ReactDOM.unmountComponentAtNode(element);
|
||||
};
|
|
@ -1,20 +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
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { CoreStart } from '@kbn/core/public';
|
||||
|
||||
interface CustomBrandingAppDeps {
|
||||
basename: string;
|
||||
notifications: CoreStart['notifications'];
|
||||
http: CoreStart['http'];
|
||||
}
|
||||
|
||||
export const CustomBrandingApp = (props: CustomBrandingAppDeps) => {
|
||||
return <div>Hello</div>;
|
||||
};
|
0
x-pack/plugins/custom_branding/public/index.ts
Executable file → Normal file
0
x-pack/plugins/custom_branding/public/index.ts
Executable file → Normal file
0
x-pack/plugins/custom_branding/public/plugin.ts
Executable file → Normal file
0
x-pack/plugins/custom_branding/public/plugin.ts
Executable file → Normal file
0
x-pack/plugins/custom_branding/public/types.ts
Executable file → Normal file
0
x-pack/plugins/custom_branding/public/types.ts
Executable file → Normal file
|
@ -20,9 +20,8 @@ import { License } from '@kbn/license-api-guard-plugin/server';
|
|||
import { CustomBranding } from '@kbn/core-custom-branding-common';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { PLUGIN } from '../common/constants';
|
||||
import type { CustomBrandingRequestHandlerContext } from './types';
|
||||
import { Dependencies } from './types';
|
||||
import { registerRoutes } from './routes';
|
||||
import { registerUiSettings } from './ui_settings';
|
||||
|
||||
const settingsKeys: Array<keyof CustomBranding> = [
|
||||
'logo',
|
||||
|
@ -49,8 +48,8 @@ export class CustomBrandingPlugin implements Plugin {
|
|||
pluginName: PLUGIN.getI18nName(i18n),
|
||||
logger: this.logger,
|
||||
});
|
||||
const router = core.http.createRouter<CustomBrandingRequestHandlerContext>();
|
||||
registerRoutes(router);
|
||||
|
||||
registerUiSettings(core);
|
||||
|
||||
const fetchFn = async (
|
||||
request: KibanaRequest,
|
||||
|
@ -95,8 +94,9 @@ export class CustomBrandingPlugin implements Plugin {
|
|||
const branding: CustomBranding = {};
|
||||
for (let i = 0; i < settingsKeys!.length; i++) {
|
||||
const key = settingsKeys[i];
|
||||
const fullKey = `customBranding:${key}`;
|
||||
const fullKey = `xpackCustomBranding:${key}`;
|
||||
const value = await uiSettingsClient.get(fullKey);
|
||||
this.logger.info(`Fetching custom branding key ${fullKey} with value ${value}`);
|
||||
if (value) {
|
||||
branding[key] = value;
|
||||
}
|
||||
|
|
145
x-pack/plugins/custom_branding/server/ui_settings.ts
Normal file
145
x-pack/plugins/custom_branding/server/ui_settings.ts
Normal file
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { CoreSetup } from '@kbn/core-lifecycle-server';
|
||||
import { UiSettingsParams } from '@kbn/core-ui-settings-common';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
|
||||
export const UI_SETTINGS_CUSTOM_LOGO = 'xpackCustomBranding:logo';
|
||||
export const UI_SETTINGS_CUSTOMIZED_LOGO = 'xpackCustomBranding:customizedLogo';
|
||||
export const UI_SETTINGS_PAGE_TITLE = 'xpackCustomBranding:pageTitle';
|
||||
export const UI_SETTINGS_FAVICON_PNG = 'xpackCustomBranding:faviconPNG';
|
||||
export const UI_SETTINGS_FAVICON_SVG = 'xpackCustomBranding:faviconSVG';
|
||||
export const PLUGIN_ID = 'Custom Branding';
|
||||
|
||||
const kbToBase64Length = (kb: number) => Math.floor((kb * 1024 * 8) / 6);
|
||||
const maxLogoSizeInBase64 = kbToBase64Length(200);
|
||||
const dataurlRegex = /^data:([a-z]+\/[a-z0-9-+.]+)(;[a-z-]+=[a-z0-9-]+)?(;([a-z0-9]+))?,/;
|
||||
const imageTypes = ['image/svg+xml', 'image/jpeg', 'image/png', 'image/gif'];
|
||||
|
||||
const isImageData = (str: string) => {
|
||||
const matches = str.match(dataurlRegex);
|
||||
|
||||
if (!matches) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const [, mimetype, , , encoding] = matches;
|
||||
const imageTypeIndex = imageTypes.indexOf(mimetype);
|
||||
if (imageTypeIndex < 0 || encoding !== 'base64') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
const validateLogoBase64String = (str: string) => {
|
||||
if (typeof str !== 'string' || !isImageData(str)) {
|
||||
return i18n.translate('xpack.customBranding.uiSettings.validate.customLogo.badFile', {
|
||||
defaultMessage: `Sorry, that file will not work. Please try a different image file.`,
|
||||
});
|
||||
}
|
||||
if (str.length > maxLogoSizeInBase64) {
|
||||
return i18n.translate('xpack.customBranding.uiSettings.validate.customLogo.tooLarge', {
|
||||
defaultMessage: `Sorry, that file is too large. The image file must be less than 200 kilobytes.`,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export const ImageSchema = schema.nullable(schema.string({ validate: validateLogoBase64String }));
|
||||
|
||||
const subscriptionLink = `
|
||||
<a href="https://www.elastic.co/subscriptions" target="_blank" rel="noopener noreferrer">
|
||||
${i18n.translate('xpack.customBranding.settings.subscriptionRequiredLink.text', {
|
||||
defaultMessage: 'Subscription required.',
|
||||
})}
|
||||
</a>
|
||||
`;
|
||||
export function registerUiSettings(core: CoreSetup<object, unknown>) {
|
||||
core.uiSettings.registerGlobal({
|
||||
[UI_SETTINGS_CUSTOM_LOGO]: {
|
||||
name: i18n.translate('xpack.customBranding.customLogoLabel', {
|
||||
defaultMessage: 'Logo icon',
|
||||
}),
|
||||
value: null,
|
||||
description: i18n.translate('xpack.customBranding.customLogoDescription', {
|
||||
defaultMessage: `Replaces the Elastic logo. Logos look best when they are no larger than 128 x 128 pixels and have a transparent background. {subscriptionLink}`,
|
||||
values: { subscriptionLink },
|
||||
}),
|
||||
sensitive: true,
|
||||
type: 'image',
|
||||
order: 1,
|
||||
requiresPageReload: true,
|
||||
schema: ImageSchema,
|
||||
category: [PLUGIN_ID],
|
||||
},
|
||||
[UI_SETTINGS_CUSTOMIZED_LOGO]: {
|
||||
name: i18n.translate('xpack.customBranding.customizedLogoLabel', {
|
||||
defaultMessage: 'Organization name',
|
||||
}),
|
||||
value: null,
|
||||
description: i18n.translate('xpack.customBranding.customizedLogoDescription', {
|
||||
defaultMessage: `Replaces the Elastic text. Images look best when they are no larger than 200 x 84 pixels and have a transparent background. {subscriptionLink}`,
|
||||
values: { subscriptionLink },
|
||||
}),
|
||||
sensitive: true,
|
||||
type: 'image',
|
||||
order: 2,
|
||||
requiresPageReload: true,
|
||||
schema: ImageSchema,
|
||||
category: [PLUGIN_ID],
|
||||
},
|
||||
[UI_SETTINGS_PAGE_TITLE]: {
|
||||
name: i18n.translate('xpack.customBranding.pageTitleLabel', {
|
||||
defaultMessage: 'Page title',
|
||||
}),
|
||||
value: null,
|
||||
description: i18n.translate('xpack.customBranding.pageTitleDescription', {
|
||||
defaultMessage: `The text that appears on browser tabs. {subscriptionLink}`,
|
||||
values: { subscriptionLink },
|
||||
}),
|
||||
sensitive: true,
|
||||
type: 'string',
|
||||
order: 3,
|
||||
requiresPageReload: true,
|
||||
schema: schema.nullable(schema.string()),
|
||||
category: [PLUGIN_ID],
|
||||
},
|
||||
[UI_SETTINGS_FAVICON_SVG]: {
|
||||
name: i18n.translate('xpack.customBranding.faviconSVGTitle', {
|
||||
defaultMessage: 'Favicon (SVG)',
|
||||
}),
|
||||
value: null,
|
||||
description: i18n.translate('xpack.customBranding.faviconSVGDescription', {
|
||||
defaultMessage: `A link to an icon that will appear on browser tabs. Recommended size is 16 x 16 pixels. {subscriptionLink}`,
|
||||
values: { subscriptionLink },
|
||||
}),
|
||||
sensitive: true,
|
||||
type: 'string',
|
||||
order: 4,
|
||||
requiresPageReload: true,
|
||||
schema: schema.nullable(schema.string()),
|
||||
category: [PLUGIN_ID],
|
||||
},
|
||||
[UI_SETTINGS_FAVICON_PNG]: {
|
||||
name: i18n.translate('xpack.customBranding.faviconPNGTitle', {
|
||||
defaultMessage: 'Favicon (PNG)',
|
||||
}),
|
||||
value: null,
|
||||
description: i18n.translate('xpack.customBranding.faviconPNGDescription', {
|
||||
defaultMessage: `An icon for use in browsers that don’t support svg. {subscriptionLink}`,
|
||||
values: { subscriptionLink },
|
||||
}),
|
||||
sensitive: true,
|
||||
type: 'string',
|
||||
order: 5,
|
||||
requiresPageReload: true,
|
||||
schema: schema.nullable(schema.string()),
|
||||
category: [PLUGIN_ID],
|
||||
},
|
||||
} as Record<string, UiSettingsParams<null>>);
|
||||
}
|
|
@ -16,6 +16,9 @@
|
|||
"@kbn/i18n",
|
||||
"@kbn/core-http-request-handler-context-server",
|
||||
"@kbn/core-custom-branding-common",
|
||||
"@kbn/core-lifecycle-server",
|
||||
"@kbn/core-ui-settings-common",
|
||||
"@kbn/config-schema",
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*",
|
||||
|
|
|
@ -324,6 +324,7 @@ exports[`LoginPage page renders as expected 1`] = `
|
|||
/>
|
||||
<span
|
||||
className="loginWelcome__logo"
|
||||
style={Object {}}
|
||||
>
|
||||
<EuiIcon
|
||||
size="xxl"
|
||||
|
@ -411,6 +412,11 @@ exports[`LoginPage page renders with custom branding 1`] = `
|
|||
/>
|
||||
<span
|
||||
className="loginWelcome__logo"
|
||||
style={
|
||||
Object {
|
||||
"padding": 0,
|
||||
}
|
||||
}
|
||||
>
|
||||
<EuiImage
|
||||
alt="logo"
|
||||
|
|
|
@ -146,12 +146,16 @@ export class LoginPage extends Component<Props, State> {
|
|||
) : (
|
||||
<EuiIcon type="logoElastic" size="xxl" />
|
||||
);
|
||||
// custom logo needs to be centered
|
||||
const logoStyle = customLogo ? { padding: 0 } : {};
|
||||
return (
|
||||
<div className="loginWelcome login-form">
|
||||
<header className="loginWelcome__header">
|
||||
<div className={contentHeaderClasses}>
|
||||
<EuiSpacer size="xxl" />
|
||||
<span className="loginWelcome__logo">{logo}</span>
|
||||
<span className="loginWelcome__logo" style={logoStyle}>
|
||||
{logo}
|
||||
</span>
|
||||
<EuiTitle size="m" className="loginWelcome__title" data-test-subj="loginWelcomeTitle">
|
||||
<h1>
|
||||
<FormattedMessage
|
||||
|
|
42
x-pack/test/custom_branding/config.ts
Normal file
42
x-pack/test/custom_branding/config.ts
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { FtrConfigProviderContext } from '@kbn/test';
|
||||
import { services, pageObjects } from './ftr_provider_context';
|
||||
|
||||
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
||||
const kibanaFunctionalConfig = await readConfigFile(
|
||||
require.resolve('../functional/config.base.js')
|
||||
);
|
||||
|
||||
return {
|
||||
testFiles: [require.resolve('./tests')],
|
||||
servers: {
|
||||
...kibanaFunctionalConfig.get('servers'),
|
||||
},
|
||||
services,
|
||||
pageObjects,
|
||||
|
||||
junit: {
|
||||
reportName: 'X-Pack Custom Branding Functional Tests',
|
||||
},
|
||||
|
||||
esTestCluster: {
|
||||
...kibanaFunctionalConfig.get('esTestCluster'),
|
||||
license: 'trial',
|
||||
serverArgs: [`xpack.license.self_generated.type='trial'`],
|
||||
},
|
||||
apps: {
|
||||
...kibanaFunctionalConfig.get('apps'),
|
||||
},
|
||||
|
||||
kbnTestServer: {
|
||||
...kibanaFunctionalConfig.get('kbnTestServer'),
|
||||
serverArgs: [...kibanaFunctionalConfig.get('kbnTestServer.serverArgs')],
|
||||
},
|
||||
};
|
||||
}
|
13
x-pack/test/custom_branding/ftr_provider_context.ts
Normal file
13
x-pack/test/custom_branding/ftr_provider_context.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { GenericFtrProviderContext } from '@kbn/test';
|
||||
import { services } from '../functional/services';
|
||||
import { pageObjects } from '../functional/page_objects';
|
||||
|
||||
export type FtrProviderContext = GenericFtrProviderContext<typeof services, typeof pageObjects>;
|
||||
export { services, pageObjects };
|
BIN
x-pack/test/custom_branding/tests/acme_logo.png
Normal file
BIN
x-pack/test/custom_branding/tests/acme_logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.2 KiB |
BIN
x-pack/test/custom_branding/tests/acme_text.png
Normal file
BIN
x-pack/test/custom_branding/tests/acme_text.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2 KiB |
14
x-pack/test/custom_branding/tests/index.ts
Normal file
14
x-pack/test/custom_branding/tests/index.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
export default function ({ loadTestFile }: FtrProviderContext) {
|
||||
describe('custom branding - functional tests', function () {
|
||||
loadTestFile(require.resolve('./settings'));
|
||||
});
|
||||
}
|
100
x-pack/test/custom_branding/tests/settings.ts
Normal file
100
x-pack/test/custom_branding/tests/settings.ts
Normal file
|
@ -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
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const esArchiver = getService('esArchiver');
|
||||
const testSubjects = getService('testSubjects');
|
||||
const find = getService('find');
|
||||
const log = getService('log');
|
||||
const PageObjects = getPageObjects(['settings', 'common', 'dashboard', 'timePicker', 'header']);
|
||||
|
||||
describe('custom branding', function describeIndexTests() {
|
||||
const resetSettings = async () => {
|
||||
const advancedSetting = await PageObjects.settings.getAdvancedSettings(
|
||||
'xpackCustomBranding:pageTitle'
|
||||
);
|
||||
if (advancedSetting !== '') {
|
||||
await PageObjects.settings.clearAdvancedSettings('xpackCustomBranding:pageTitle');
|
||||
}
|
||||
try {
|
||||
await find.byCssSelector('img[alt="xpackCustomBranding:logo"]');
|
||||
await PageObjects.settings.clearAdvancedSettings('xpackCustomBranding:logo');
|
||||
} catch (e) {
|
||||
log.debug('It is expected not to find custom branding properties set');
|
||||
}
|
||||
try {
|
||||
await find.byCssSelector('img[alt="xpackCustomBranding:customizedLogo"]');
|
||||
await PageObjects.settings.clearAdvancedSettings('xpackCustomBranding:customizedLogo');
|
||||
} catch (e) {
|
||||
log.debug('It is expected not to find custom branding properties set');
|
||||
}
|
||||
};
|
||||
|
||||
const goToSettings = async () => {
|
||||
await PageObjects.settings.navigateTo();
|
||||
await PageObjects.settings.clickKibanaGlobalSettings();
|
||||
};
|
||||
|
||||
before(async function () {
|
||||
await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional');
|
||||
await kibanaServer.uiSettings.replace({});
|
||||
await PageObjects.settings.navigateTo();
|
||||
await PageObjects.settings.clickKibanaGlobalSettings();
|
||||
// clear settings before tests start
|
||||
await resetSettings();
|
||||
});
|
||||
|
||||
after(async function () {
|
||||
await esArchiver.unload('test/functional/fixtures/es_archiver/logstash_functional');
|
||||
await PageObjects.settings.navigateTo();
|
||||
await PageObjects.settings.clickKibanaGlobalSettings();
|
||||
await resetSettings();
|
||||
});
|
||||
|
||||
beforeEach(async function () {
|
||||
await goToSettings();
|
||||
});
|
||||
|
||||
it('should allow setting custom page title through advanced settings', async function () {
|
||||
const pageTitle = 'Custom Page Title';
|
||||
const settingName = 'xpackCustomBranding:pageTitle';
|
||||
await PageObjects.settings.setAdvancedSettingsInput(settingName, pageTitle);
|
||||
|
||||
const advancedSetting = await PageObjects.settings.getAdvancedSettings(settingName);
|
||||
expect(advancedSetting).to.be(pageTitle);
|
||||
});
|
||||
|
||||
it('should allow setting custom logo through advanced settings', async function () {
|
||||
const settingName = 'xpackCustomBranding:logo';
|
||||
await PageObjects.settings.setAdvancedSettingsImage(
|
||||
settingName,
|
||||
require.resolve('./acme_logo.png')
|
||||
);
|
||||
await goToSettings();
|
||||
const img = await find.byCssSelector('img[alt="logo"]');
|
||||
const imgSrc = await img.getAttribute('src');
|
||||
expect(imgSrc.startsWith('data:image/png')).to.be(true);
|
||||
});
|
||||
|
||||
it('should allow setting custom logo text through advanced settings', async function () {
|
||||
const settingName = 'xpackCustomBranding:customizedLogo';
|
||||
await PageObjects.settings.setAdvancedSettingsImage(
|
||||
settingName,
|
||||
require.resolve('./acme_text.png')
|
||||
);
|
||||
await goToSettings();
|
||||
const logo = await testSubjects.find('logo');
|
||||
const img = await logo.findByCssSelector('.chrHeaderLogo__mark');
|
||||
const imgSrc = await img.getAttribute('src');
|
||||
expect(imgSrc.startsWith('data:image/png')).to.be(true);
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue