Skip to content

Commit ba20c6f

Browse files
Constancecee-chen
Constance
authored andcommitted
Address review feedback (elastic#14)
* Fix Prettier linting issues * Escape App Search API endpoint URLs - per PR feedback - querystring should automatically encodeURIComponent / escape query param strings * Update server plugin.ts to use getStartServices() rather than storing local references from start() - Per feedback: https://github.com/elastic/kibana/blob/master/src/core/CONVENTIONS.md#applications - Note: savedObjects.registerType needs to be outside of getStartServices, or an error is thrown - Side update to registerTelemetryUsageCollector to simplify args - Update/fix tests to account for changes
1 parent a8c3e9d commit ba20c6f

File tree

16 files changed

+63
-78
lines changed

16 files changed

+63
-78
lines changed

Diff for: x-pack/plugins/enterprise_search/public/applications/__mocks__/shallow_with_i18n.mock.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const { intl } = intlProvider.getChildContext();
2020
*
2121
* const wrapper = shallowWithIntl(<Component />);
2222
*/
23-
export const shallowWithIntl = children => {
23+
export const shallowWithIntl = (children) => {
2424
return shallow(<I18nProvider>{children}</I18nProvider>, {
2525
context: { intl },
2626
childContextTypes: { intl },

Diff for: x-pack/plugins/enterprise_search/public/applications/app_search/components/empty_states/empty_states.test.tsx

+1-4
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,7 @@ describe('NoUserState', () => {
4242
getUserName.mockImplementationOnce(() => 'dolores-abernathy');
4343
const wrapper = shallowWithIntl(<NoUserState />);
4444
const prompt = wrapper.find(EuiEmptyPrompt).dive();
45-
const description1 = prompt
46-
.find(FormattedMessage)
47-
.at(1)
48-
.dive();
45+
const description1 = prompt.find(FormattedMessage).at(1).dive();
4946

5047
expect(description1.find(EuiCode).prop('children')).toContain('dolores-abernathy');
5148
});

Diff for: x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_overview.test.tsx

+1-5
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,7 @@ describe('EngineOverview', () => {
105105
});
106106

107107
describe('pagination', () => {
108-
const getTablePagination = () =>
109-
wrapper
110-
.find(EngineTable)
111-
.first()
112-
.prop('pagination');
108+
const getTablePagination = () => wrapper.find(EngineTable).first().prop('pagination');
113109

114110
it('passes down page data from the API', () => {
115111
const pagination = getTablePagination();

Diff for: x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_table.test.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ describe('EngineTable', () => {
5151
it('contains engine links which send telemetry', () => {
5252
const engineLinks = wrapper.find(EuiLink);
5353

54-
engineLinks.forEach(link => {
54+
engineLinks.forEach((link) => {
5555
expect(link.prop('href')).toEqual('http://localhost:3002/as/engines/test-engine');
5656
link.simulate('click');
5757

Diff for: x-pack/plugins/enterprise_search/public/applications/app_search/components/engine_overview/engine_table.tsx

+6-6
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export const EngineTable: ReactFC<IEngineTableProps> = ({
3838
pagination: { totalEngines, pageIndex = 0, onPaginate },
3939
}) => {
4040
const { enterpriseSearchUrl, http } = useContext(KibanaContext) as IKibanaContext;
41-
const engineLinkProps = name => ({
41+
const engineLinkProps = (name) => ({
4242
href: `${enterpriseSearchUrl}/as/engines/${name}`,
4343
target: '_blank',
4444
onClick: () =>
@@ -56,7 +56,7 @@ export const EngineTable: ReactFC<IEngineTableProps> = ({
5656
name: i18n.translate('xpack.enterpriseSearch.appSearch.enginesOverview.table.column.name', {
5757
defaultMessage: 'Name',
5858
}),
59-
render: name => <EuiLink {...engineLinkProps(name)}>{name}</EuiLink>,
59+
render: (name) => <EuiLink {...engineLinkProps(name)}>{name}</EuiLink>,
6060
width: '30%',
6161
truncateText: true,
6262
mobileOptions: {
@@ -75,7 +75,7 @@ export const EngineTable: ReactFC<IEngineTableProps> = ({
7575
}
7676
),
7777
dataType: 'string',
78-
render: dateString => (
78+
render: (dateString) => (
7979
// e.g., January 1, 1970
8080
<FormattedDate value={new Date(dateString)} year="numeric" month="long" day="numeric" />
8181
),
@@ -89,7 +89,7 @@ export const EngineTable: ReactFC<IEngineTableProps> = ({
8989
}
9090
),
9191
dataType: 'number',
92-
render: number => <FormattedNumber value={number} />,
92+
render: (number) => <FormattedNumber value={number} />,
9393
truncateText: true,
9494
},
9595
{
@@ -101,7 +101,7 @@ export const EngineTable: ReactFC<IEngineTableProps> = ({
101101
}
102102
),
103103
dataType: 'number',
104-
render: number => <FormattedNumber value={number} />,
104+
render: (number) => <FormattedNumber value={number} />,
105105
truncateText: true,
106106
},
107107
{
@@ -113,7 +113,7 @@ export const EngineTable: ReactFC<IEngineTableProps> = ({
113113
}
114114
),
115115
dataType: 'string',
116-
render: name => (
116+
render: (name) => (
117117
<EuiLink {...engineLinkProps(name)}>
118118
<FormattedMessage
119119
id="xpack.enterpriseSearch.appSearch.enginesOverview.table.action.manage"

Diff for: x-pack/plugins/enterprise_search/public/applications/shared/kibana_breadcrumbs/generate_breadcrumbs.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export const generateBreadcrumb = ({ text, path, history }: IGenerateBreadcrumbP
2525

2626
if (path && history) {
2727
breadcrumb.href = history.createHref({ pathname: path });
28-
breadcrumb.onClick = event => {
28+
breadcrumb.onClick = (event) => {
2929
if (letBrowserHandleEvent(event)) return;
3030
event.preventDefault();
3131
history.push(path);

Diff for: x-pack/plugins/enterprise_search/public/applications/shared/kibana_breadcrumbs/set_breadcrumbs.test.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ describe('SetAppSearchBreadcrumbs', () => {
2323
jest.clearAllMocks();
2424
});
2525

26-
const mountSetAppSearchBreadcrumbs = props => {
26+
const mountSetAppSearchBreadcrumbs = (props) => {
2727
return mountWithKibanaContext(<SetAppSearchBreadcrumbs {...props} />, {
2828
http: {},
2929
enterpriseSearchUrl: 'http://localhost:3002',

Diff for: x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/eui_link.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ interface IEuiReactRouterProps {
2525
export const EuiReactRouterLink: React.FC<IEuiReactRouterProps> = ({ to, isButton, ...rest }) => {
2626
const history = useHistory();
2727

28-
const onClick = event => {
28+
const onClick = (event) => {
2929
if (letBrowserHandleEvent(event)) return;
3030

3131
// Prevent regular link behavior, which causes a browser refresh.
@@ -42,6 +42,6 @@ export const EuiReactRouterLink: React.FC<IEuiReactRouterProps> = ({ to, isButto
4242
return isButton ? <EuiButton {...props} /> : <EuiLink {...props} />;
4343
};
4444

45-
export const EuiReactRouterButton: React.FC<IEuiReactRouterProps> = props => (
45+
export const EuiReactRouterButton: React.FC<IEuiReactRouterProps> = (props) => (
4646
<EuiReactRouterLink {...props} isButton />
4747
);

Diff for: x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/link_events.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ describe('letBrowserHandleEvent', () => {
9595
});
9696
});
9797

98-
const targetValue = value => {
98+
const targetValue = (value) => {
9999
return {
100100
getAttribute: () => value,
101101
};

Diff for: x-pack/plugins/enterprise_search/public/applications/shared/react_router_helpers/link_events.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,18 @@ import { SyntheticEvent } from 'react';
1313

1414
type THandleEvent = (event: SyntheticEvent) => boolean;
1515

16-
export const letBrowserHandleEvent: THandleEvent = event =>
16+
export const letBrowserHandleEvent: THandleEvent = (event) =>
1717
event.defaultPrevented ||
1818
isModifiedEvent(event) ||
1919
!isLeftClickEvent(event) ||
2020
isTargetBlank(event);
2121

22-
const isModifiedEvent: THandleEvent = event =>
22+
const isModifiedEvent: THandleEvent = (event) =>
2323
!!(event.metaKey || event.altKey || event.ctrlKey || event.shiftKey);
2424

25-
const isLeftClickEvent: THandleEvent = event => event.button === 0;
25+
const isLeftClickEvent: THandleEvent = (event) => event.button === 0;
2626

27-
const isTargetBlank: THandleEvent = event => {
27+
const isTargetBlank: THandleEvent = (event) => {
2828
const target = event.target.getAttribute('target');
2929
return !!target && target !== '_self';
3030
};

Diff for: x-pack/plugins/enterprise_search/server/collectors/app_search/telemetry.test.ts

+12-17
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ import { registerTelemetryUsageCollector, incrementUICounter } from './telemetry
1414
describe('App Search Telemetry Usage Collector', () => {
1515
const makeUsageCollectorStub = jest.fn();
1616
const registerStub = jest.fn();
17+
const usageCollectionMock = {
18+
makeUsageCollector: makeUsageCollectorStub,
19+
registerCollector: registerStub,
20+
};
1721

1822
const savedObjectsRepoStub = {
1923
get: () => ({
@@ -29,14 +33,8 @@ describe('App Search Telemetry Usage Collector', () => {
2933
}),
3034
incrementCounter: jest.fn(),
3135
};
32-
const dependencies = {
33-
usageCollection: {
34-
makeUsageCollector: makeUsageCollectorStub,
35-
registerCollector: registerStub,
36-
},
37-
savedObjects: {
38-
createInternalRepository: jest.fn(() => savedObjectsRepoStub),
39-
},
36+
const savedObjectsMock = {
37+
createInternalRepository: jest.fn(() => savedObjectsRepoStub),
4038
};
4139

4240
beforeEach(() => {
@@ -45,7 +43,7 @@ describe('App Search Telemetry Usage Collector', () => {
4543

4644
describe('registerTelemetryUsageCollector', () => {
4745
it('should make and register the usage collector', () => {
48-
registerTelemetryUsageCollector(dependencies);
46+
registerTelemetryUsageCollector(usageCollectionMock, savedObjectsMock);
4947

5048
expect(registerStub).toHaveBeenCalledTimes(1);
5149
expect(makeUsageCollectorStub).toHaveBeenCalledTimes(1);
@@ -55,7 +53,7 @@ describe('App Search Telemetry Usage Collector', () => {
5553

5654
describe('fetchTelemetryMetrics', () => {
5755
it('should return existing saved objects data', async () => {
58-
registerTelemetryUsageCollector(dependencies);
56+
registerTelemetryUsageCollector(usageCollectionMock, savedObjectsMock);
5957
const savedObjectsCounts = await makeUsageCollectorStub.mock.calls[0][0].fetch();
6058

6159
expect(savedObjectsCounts).toEqual({
@@ -76,10 +74,9 @@ describe('App Search Telemetry Usage Collector', () => {
7674
});
7775

7876
it('should not error & should return a default telemetry object if no saved data exists', async () => {
79-
registerTelemetryUsageCollector({
80-
...dependencies,
81-
savedObjects: { createInternalRepository: () => ({}) },
82-
});
77+
const emptySavedObjectsMock = { createInternalRepository: () => ({}) };
78+
79+
registerTelemetryUsageCollector(usageCollectionMock, emptySavedObjectsMock);
8380
const savedObjectsCounts = await makeUsageCollectorStub.mock.calls[0][0].fetch();
8481

8582
expect(savedObjectsCounts).toEqual({
@@ -102,10 +99,8 @@ describe('App Search Telemetry Usage Collector', () => {
10299

103100
describe('incrementUICounter', () => {
104101
it('should increment the saved objects internal repository', async () => {
105-
const { savedObjects } = dependencies;
106-
107102
const response = await incrementUICounter({
108-
savedObjects,
103+
savedObjects: savedObjectsMock,
109104
uiAction: 'ui_clicked',
110105
metric: 'button',
111106
});

Diff for: x-pack/plugins/enterprise_search/server/collectors/app_search/telemetry.ts

+4-9
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,10 @@ import { AS_TELEMETRY_NAME, ITelemetrySavedObject } from '../../saved_objects/ap
1414
* Register the telemetry collector
1515
*/
1616

17-
interface Dependencies {
18-
savedObjects: SavedObjectsServiceStart;
19-
usageCollection: UsageCollectionSetup;
20-
}
21-
22-
export const registerTelemetryUsageCollector = ({
23-
usageCollection,
24-
savedObjects,
25-
}: Dependencies) => {
17+
export const registerTelemetryUsageCollector = (
18+
usageCollection: UsageCollectionSetup,
19+
savedObjects: SavedObjectsServiceStart
20+
) => {
2621
const telemetryUsageCollector = usageCollection.makeUsageCollector({
2722
type: 'app_search',
2823
fetch: async () => fetchTelemetryMetrics(savedObjects),

Diff for: x-pack/plugins/enterprise_search/server/plugin.ts

+12-17
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {
1010
Plugin,
1111
PluginInitializerContext,
1212
CoreSetup,
13-
CoreStart,
1413
Logger,
1514
SavedObjectsServiceStart,
1615
} from 'src/core/server';
@@ -52,26 +51,22 @@ export class EnterpriseSearchPlugin implements Plugin {
5251
/**
5352
* Bootstrap the routes, saved objects, and collector for telemetry
5453
*/
55-
registerTelemetryRoute({
56-
...dependencies,
57-
getSavedObjectsService: () => {
58-
if (!this.savedObjectsServiceStart) {
59-
throw new Error('Saved Objects Start service not available');
60-
}
61-
return this.savedObjectsServiceStart;
62-
},
63-
});
6454
savedObjects.registerType(appSearchTelemetryType);
65-
if (usageCollection) {
66-
getStartServices().then(([{ savedObjects: savedObjectsStarted }]) => {
67-
registerTelemetryUsageCollector({ usageCollection, savedObjects: savedObjectsStarted });
55+
56+
getStartServices().then(([coreStart]) => {
57+
const savedObjectsStarted = coreStart.savedObjects as SavedObjectsServiceStart;
58+
59+
registerTelemetryRoute({
60+
...dependencies,
61+
getSavedObjectsService: () => savedObjectsStarted,
6862
});
69-
}
63+
if (usageCollection) {
64+
registerTelemetryUsageCollector(usageCollection, savedObjectsStarted);
65+
}
66+
});
7067
}
7168

72-
public start({ savedObjects }: CoreStart) {
73-
this.savedObjectsServiceStart = savedObjects;
74-
}
69+
public start() {}
7570

7671
public stop() {}
7772
}

Diff for: x-pack/plugins/enterprise_search/server/routes/__mocks__/router.mock.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export class MockRouter {
3030
this.router = httpServiceMock.createRouter();
3131
};
3232

33-
public callRoute = async request => {
33+
public callRoute = async (request) => {
3434
const [_, handler] = this.router[this.method].mock.calls[0];
3535

3636
const context = {} as jest.Mocked<RequestHandlerContext>;
@@ -41,18 +41,18 @@ export class MockRouter {
4141
* Schema validation helpers
4242
*/
4343

44-
public validateRoute = request => {
44+
public validateRoute = (request) => {
4545
const [config] = this.router[this.method].mock.calls[0];
4646
const validate = config.validate as RouteValidatorConfig<{}, {}, {}>;
4747

4848
validate[this.payload].validate(request[this.payload]);
4949
};
5050

51-
public shouldValidate = request => {
51+
public shouldValidate = (request) => {
5252
expect(() => this.validateRoute(request)).not.toThrow();
5353
};
5454

55-
public shouldThrow = request => {
55+
public shouldThrow = (request) => {
5656
expect(() => this.validateRoute(request)).toThrow();
5757
};
5858
}

Diff for: x-pack/plugins/enterprise_search/server/routes/app_search/engines.test.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ describe('engine routes', () => {
4646
describe('when the underlying App Search API returns a 200', () => {
4747
beforeEach(() => {
4848
AppSearchAPI.shouldBeCalledWith(
49-
`http://localhost:3002/as/engines/collection?type=indexed&page[current]=1&page[size]=10`,
49+
`http://localhost:3002/as/engines/collection?type=indexed&page%5Bcurrent%5D=1&page%5Bsize%5D=10`,
5050
{ headers: { Authorization: AUTH_HEADER } }
5151
).andReturn({
5252
results: [{ name: 'engine1' }],
@@ -67,7 +67,7 @@ describe('engine routes', () => {
6767
describe('when the underlying App Search API redirects to /login', () => {
6868
beforeEach(() => {
6969
AppSearchAPI.shouldBeCalledWith(
70-
`http://localhost:3002/as/engines/collection?type=indexed&page[current]=1&page[size]=10`,
70+
`http://localhost:3002/as/engines/collection?type=indexed&page%5Bcurrent%5D=1&page%5Bsize%5D=10`,
7171
{ headers: { Authorization: AUTH_HEADER } }
7272
).andReturnRedirect();
7373
});
@@ -85,7 +85,7 @@ describe('engine routes', () => {
8585
describe('when the App Search URL is invalid', () => {
8686
beforeEach(() => {
8787
AppSearchAPI.shouldBeCalledWith(
88-
`http://localhost:3002/as/engines/collection?type=indexed&page[current]=1&page[size]=10`,
88+
`http://localhost:3002/as/engines/collection?type=indexed&page%5Bcurrent%5D=1&page%5Bsize%5D=10`,
8989
{ headers: { Authorization: AUTH_HEADER } }
9090
).andReturnError();
9191
});
@@ -104,7 +104,7 @@ describe('engine routes', () => {
104104
describe('when the App Search API returns invalid data', () => {
105105
beforeEach(() => {
106106
AppSearchAPI.shouldBeCalledWith(
107-
`http://localhost:3002/as/engines/collection?type=indexed&page[current]=1&page[size]=10`,
107+
`http://localhost:3002/as/engines/collection?type=indexed&page%5Bcurrent%5D=1&page%5Bsize%5D=10`,
108108
{ headers: { Authorization: AUTH_HEADER } }
109109
).andReturnInvalidData();
110110
});

Diff for: x-pack/plugins/enterprise_search/server/routes/app_search/engines.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66

77
import fetch from 'node-fetch';
8+
import querystring from 'querystring';
89
import { schema } from '@kbn/config-schema';
910

1011
import { ENGINES_PAGE_SIZE } from '../../../common/constants';
@@ -25,7 +26,13 @@ export function registerEnginesRoute({ router, config, log }) {
2526
const appSearchUrl = config.host;
2627
const { type, pageIndex } = request.query;
2728

28-
const url = `${appSearchUrl}/as/engines/collection?type=${type}&page[current]=${pageIndex}&page[size]=${ENGINES_PAGE_SIZE}`;
29+
const params = querystring.stringify({
30+
type,
31+
'page[current]': pageIndex,
32+
'page[size]': ENGINES_PAGE_SIZE,
33+
});
34+
const url = `${encodeURI(appSearchUrl)}/as/engines/collection?${params}`;
35+
2936
const enginesResponse = await fetch(url, {
3037
headers: { Authorization: request.headers.authorization },
3138
});

0 commit comments

Comments
 (0)