Skip to content

Commit

Permalink
[Enterprise Search] Update the browser/document title on plugin navig…
Browse files Browse the repository at this point in the history
…ation (#74392)

* Rename kibana_breadcrumbs to kibana_chrome

- in anticipation of upcoming refactor where SetPageChrome now handles document title as well as Kibana breadcrumbs
+ cleanup exports

* Add generate_title helpers

- will be used by new set_chrome helper

* Add setDocTitle context + behavior to set_chrome

+ refactor set_chrome.test.tsx:
  - add title tests
  - add SetWorkplaceSearchChrome test to increase coverage
  - clean up inner/outer call in favor of simpler mocks/imports
  - simplify isRoot tests

* Update plugins to set product titles
- on mount but before render

* Copy feedback - change pipe separator to hyphen

- to match ' - Elastic'

* Add functional tests confirming that document titles updated
  • Loading branch information
Constance committed Aug 10, 2020
1 parent 7e55da5 commit 697cd64
Show file tree
Hide file tree
Showing 25 changed files with 243 additions and 96 deletions.
8 changes: 8 additions & 0 deletions test/functional/services/common/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,14 @@ export async function BrowserProvider({ getService }: FtrProviderContext) {
return currentWithoutTime;
}

/**
* Gets the page/document title of the focused window/frame.
* https://www.selenium.dev/selenium/docs/api/javascript/module/selenium-webdriver/chrome_exports_Driver.html#getTitle
*/
public async getTitle() {
return await driver.getTitle();
}

/**
* Navigates the focused window/frame to a new URL.
* https://seleniumhq.github.io/selenium/docs/api/javascript/module/selenium-webdriver/chrome_exports_Driver.html#get
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ import { httpServiceMock } from 'src/core/public/mocks';
export const mockKibanaContext = {
http: httpServiceMock.createSetupContract(),
setBreadcrumbs: jest.fn(),
setDocTitle: jest.fn(),
enterpriseSearchUrl: 'http://localhost:3002',
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { EuiPage, EuiPageBody, EuiPageContent, EuiEmptyPrompt, EuiButton } from
import { FormattedMessage } from '@kbn/i18n/react';

import { sendTelemetry } from '../../../shared/telemetry';
import { SetAppSearchBreadcrumbs as SetBreadcrumbs } from '../../../shared/kibana_breadcrumbs';
import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
import { KibanaContext, IKibanaContext } from '../../../index';

import { EngineOverviewHeader } from '../engine_overview_header';
Expand All @@ -33,7 +33,7 @@ export const EmptyState: React.FC = () => {

return (
<EuiPage restrictWidth>
<SetBreadcrumbs isRoot />
<SetPageChrome isRoot />

<EuiPageBody>
<EngineOverviewHeader />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import React from 'react';
import { EuiPage, EuiPageBody, EuiPageContent } from '@elastic/eui';

import { ErrorStatePrompt } from '../../../shared/error_state';
import { SetAppSearchBreadcrumbs as SetBreadcrumbs } from '../../../shared/kibana_breadcrumbs';
import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
import { SendAppSearchTelemetry as SendTelemetry } from '../../../shared/telemetry';
import { EngineOverviewHeader } from '../engine_overview_header';

Expand All @@ -17,7 +17,7 @@ import './empty_states.scss';
export const ErrorState: React.FC = () => {
return (
<EuiPage restrictWidth>
<SetBreadcrumbs isRoot />
<SetPageChrome isRoot />
<SendTelemetry action="error" metric="cannot_connect" />

<EuiPageBody>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@
import React from 'react';
import { EuiPage, EuiPageBody, EuiPageContent, EuiSpacer, EuiLoadingContent } from '@elastic/eui';

import { SetAppSearchBreadcrumbs as SetBreadcrumbs } from '../../../shared/kibana_breadcrumbs';
import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
import { EngineOverviewHeader } from '../engine_overview_header';

import './empty_states.scss';

export const LoadingState: React.FC = () => {
return (
<EuiPage restrictWidth>
<SetBreadcrumbs isRoot />
<SetPageChrome isRoot />

<EuiPageBody>
<EngineOverviewHeader />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';

import { SetAppSearchBreadcrumbs as SetBreadcrumbs } from '../../../shared/kibana_breadcrumbs';
import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
import { SendAppSearchTelemetry as SendTelemetry } from '../../../shared/telemetry';
import { LicenseContext, ILicenseContext, hasPlatinumLicense } from '../../../shared/licensing';
import { KibanaContext, IKibanaContext } from '../../../index';
Expand Down Expand Up @@ -93,7 +93,7 @@ export const EngineOverview: React.FC = () => {

return (
<EuiPage restrictWidth className="engineOverview">
<SetBreadcrumbs isRoot />
<SetPageChrome isRoot />
<SendTelemetry action="viewed" metric="engines_overview" />

<EuiPageBody>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import React from 'react';
import { shallow } from 'enzyme';

import { SetAppSearchBreadcrumbs as SetBreadcrumbs } from '../../../shared/kibana_breadcrumbs';
import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
import { SetupGuide as SetupGuideLayout } from '../../../shared/setup_guide';
import { SetupGuide } from './';

Expand All @@ -16,6 +16,6 @@ describe('SetupGuide', () => {
const wrapper = shallow(<SetupGuide />);

expect(wrapper.find(SetupGuideLayout)).toHaveLength(1);
expect(wrapper.find(SetBreadcrumbs)).toHaveLength(1);
expect(wrapper.find(SetPageChrome)).toHaveLength(1);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { i18n } from '@kbn/i18n';

import { APP_SEARCH_PLUGIN } from '../../../../../common/constants';
import { SetupGuide as SetupGuideLayout } from '../../../shared/setup_guide';
import { SetAppSearchBreadcrumbs as SetBreadcrumbs } from '../../../shared/kibana_breadcrumbs';
import { SetAppSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
import { SendAppSearchTelemetry as SendTelemetry } from '../../../shared/telemetry';
import GettingStarted from '../../assets/getting_started.png';

Expand All @@ -22,7 +22,7 @@ export const SetupGuide: React.FC = () => (
standardAuthLink="https://swiftype.com/documentation/app-search/self-managed/security#standard"
elasticsearchNativeAuthLink="https://swiftype.com/documentation/app-search/self-managed/security#elasticsearch-native-realm"
>
<SetBreadcrumbs
<SetPageChrome
text={i18n.translate('xpack.enterpriseSearch.setupGuide.title', {
defaultMessage: 'Setup Guide',
})}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export interface IKibanaContext {
enterpriseSearchUrl?: string;
http: HttpSetup;
setBreadcrumbs(crumbs: ChromeBreadcrumb[]): void;
setDocTitle(title: string): void;
}

export const KibanaContext = React.createContext({});
Expand All @@ -41,6 +42,7 @@ export const renderApp = (
http: core.http,
enterpriseSearchUrl: config.host,
setBreadcrumbs: core.chrome.setBreadcrumbs,
setDocTitle: core.chrome.docTitle.change,
}}
>
<LicenseProvider license$={plugins.licensing.license$}>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { generateBreadcrumb } from './generate_breadcrumbs';
import { appSearchBreadcrumbs, enterpriseSearchBreadcrumbs, workplaceSearchBreadcrumbs } from './';
import {
generateBreadcrumb,
appSearchBreadcrumbs,
enterpriseSearchBreadcrumbs,
workplaceSearchBreadcrumbs,
} from './generate_breadcrumbs';

import { mockHistory as mockHistoryUntyped } from '../../__mocks__';
const mockHistory = mockHistoryUntyped as any;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* 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 {
generateTitle,
enterpriseSearchTitle,
appSearchTitle,
workplaceSearchTitle,
} from './generate_title';

describe('generateTitle', () => {
it('creates a hyphen separated string from an array of page titles', () => {
const title = generateTitle(['Curations', 'some Engine', 'App Search']);
expect(title).toEqual('Curations - some Engine - App Search');
});
});

describe('enterpriseSearchTitle', () => {
it('automatically appends the Enterprise Search product onto the pages array', () => {
const title = enterpriseSearchTitle(['Setup Guide']);
expect(title).toEqual('Setup Guide - Enterprise Search');
});

it('can be mixed and matched', () => {
const title = enterpriseSearchTitle([appSearchTitle(['Some Page'])]);
expect(title).toEqual('Some Page - App Search - Enterprise Search');
});

it('falls back to product name', () => {
const title = enterpriseSearchTitle();
expect(title).toEqual('Enterprise Search');
});
});

describe('appSearchTitle', () => {
it('automatically appends the App Search product onto the pages array', () => {
const title = appSearchTitle(['Engines']);
expect(title).toEqual('Engines - App Search');
});

it('falls back to product name', () => {
const title = appSearchTitle();
expect(title).toEqual('App Search');
});
});

describe('workplaceSearchTitle', () => {
it('automatically appends the Workplace Search product onto the pages array', () => {
const title = workplaceSearchTitle(['Sources']);
expect(title).toEqual('Sources - Workplace Search');
});

it('falls back to product name', () => {
const title = workplaceSearchTitle();
expect(title).toEqual('Workplace Search');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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 {
ENTERPRISE_SEARCH_PLUGIN,
APP_SEARCH_PLUGIN,
WORKPLACE_SEARCH_PLUGIN,
} from '../../../../common/constants';

/**
* Generate a document title that generally follows our breadcrumb trails
* https://github.com/elastic/kibana/blob/master/docs/development/core/public/kibana-plugin-core-public.chromedoctitle.md
*/

export type TTitle = string[];

/**
* Given an array of page titles, return a final formatted document title
* @param pages - e.g., ['Curations', 'some Engine', 'App Search']
* @returns - e.g., 'Curations | some Engine | App Search'
*/
export const generateTitle = (pages: TTitle) => pages.join(' - ');

/**
* Product-specific helpers
*/

export const enterpriseSearchTitle = (page: TTitle = []) =>
generateTitle([...page, ENTERPRISE_SEARCH_PLUGIN.NAME]);

export const appSearchTitle = (page: TTitle = []) =>
generateTitle([...page, APP_SEARCH_PLUGIN.NAME]);

export const workplaceSearchTitle = (page: TTitle = []) =>
generateTitle([...page, WORKPLACE_SEARCH_PLUGIN.NAME]);
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,4 @@
* you may not use this file except in compliance with the Elastic License.
*/

export {
enterpriseSearchBreadcrumbs,
appSearchBreadcrumbs,
workplaceSearchBreadcrumbs,
} from './generate_breadcrumbs';
export { SetAppSearchBreadcrumbs, SetWorkplaceSearchBreadcrumbs } from './set_breadcrumbs';
export { SetAppSearchChrome, SetWorkplaceSearchChrome } from './set_chrome';
Loading

0 comments on commit 697cd64

Please sign in to comment.