Skip to content

Commit

Permalink
extract convertToNavLink, add more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
pgayvallet committed Feb 13, 2020
1 parent 19823a8 commit a817d84
Show file tree
Hide file tree
Showing 4 changed files with 270 additions and 55 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

160 changes: 160 additions & 0 deletions src/core/server/legacy/plugins/get_nav_links.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,5 +123,165 @@ describe('getNavLinks', () => {
);
}).toThrowErrorMatchingInlineSnapshot(`"Unknown plugin id \\"notExistingPlugin\\""`);
});

it('uses all known properties of the navlink', () => {
const navlinks = getNavLinks(
createLegacyExports({
uiAppSpecs: [
{
id: 'app-a',
title: 'AppA',
category: {
label: 'My Category',
},
order: 42,
url: '/some-custom-url',
subUrlBase: '/some-custom-url/sub',
disableSubUrlTracking: true,
icon: 'fa-snowflake',
euiIconType: 'euiIcon',
linkToLastSubUrl: true,
hidden: false,
tooltip: 'My tooltip',
},
],
}),
[]
);
expect(navlinks.length).toBe(1);
expect(navlinks[0]).toEqual({
id: 'app-a',
title: 'AppA',
category: {
label: 'My Category',
},
order: 42,
url: '/some-custom-url',
subUrlBase: '/some-custom-url/sub',
disableSubUrlTracking: true,
icon: 'fa-snowflake',
euiIconType: 'euiIcon',
linkToLastSubUrl: true,
hidden: false,
disabled: false,
tooltip: 'My tooltip',
});
});
});

describe('generating from navLinkSpecs', () => {
it('generates navlinks from legacy navLink specs', () => {
const navlinks = getNavLinks(
createLegacyExports({
navLinkSpecs: [
{
id: 'link-a',
title: 'AppA',
url: '/some-custom-url',
},
{
id: 'link-b',
disableSubUrlTracking: true,
},
],
}),
createPluginSpecs('pluginA')
);

expect(navlinks.length).toEqual(2);
expect(navlinks[0]).toEqual(
expect.objectContaining({
id: 'link-a',
title: 'AppA',
url: '/some-custom-url',
hidden: false,
disabled: false,
})
);
expect(navlinks[1]).toEqual(
expect.objectContaining({
id: 'link-b',
title: 'link-b',
url: '/app/link-b',
disableSubUrlTracking: true,
})
);
});

it('uses all known properties of the navlink', () => {
const navlinks = getNavLinks(
createLegacyExports({
navLinkSpecs: [
{
id: 'link-a',
title: 'AppA',
category: {
label: 'My Second Cat',
},
order: 72,
url: '/some-other-custom',
subUrlBase: '/some-other-custom/sub',
disableSubUrlTracking: true,
icon: 'fa-corn',
euiIconType: 'euiIconBis',
linkToLastSubUrl: false,
hidden: false,
tooltip: 'My other tooltip',
},
],
}),
[]
);
expect(navlinks.length).toBe(1);
expect(navlinks[0]).toEqual({
id: 'link-a',
title: 'AppA',
category: {
label: 'My Second Cat',
},
order: 72,
url: '/some-other-custom',
subUrlBase: '/some-other-custom/sub',
disableSubUrlTracking: true,
icon: 'fa-corn',
euiIconType: 'euiIconBis',
linkToLastSubUrl: false,
hidden: false,
disabled: false,
tooltip: 'My other tooltip',
});
});
});

describe('generating from both apps and navlinks', () => {
const navlinks = getNavLinks(
createLegacyExports({
uiAppSpecs: [
{
id: 'app-a',
title: 'AppA',
},
{
id: 'app-b',
title: 'AppB',
},
],
navLinkSpecs: [
{
id: 'link-a',
title: 'AppA',
url: '/some-custom-url',
},
{
id: 'link-b',
disableSubUrlTracking: true,
},
],
}),
[]
);

expect(navlinks.length).toBe(4);
expect(navlinks).toMatchSnapshot();
});
});
89 changes: 39 additions & 50 deletions src/core/server/legacy/plugins/get_nav_links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,62 +17,51 @@
* under the License.
*/

import { LegacyUiExports, LegacyNavLink, LegacyPluginSpec } from '../types';
import {
LegacyUiExports,
LegacyNavLink,
LegacyPluginSpec,
LegacyNavLinkSpec,
LegacyAppSpec,
} from '../types';

const REMOVE_FROM_ARRAY: LegacyNavLink[] = [];

function getUiAppsNavLinks({ uiAppSpecs = [] }: LegacyUiExports, pluginSpecs: LegacyPluginSpec[]) {
return uiAppSpecs.flatMap(spec => {
if (!spec) {
return REMOVE_FROM_ARRAY;
}
function convertToNavLink(spec: LegacyNavLinkSpec | LegacyAppSpec): LegacyNavLink {
if (!spec.id) {
throw new Error('Every app must specify an id');
}
return {
id: spec.id,
category: spec.category,
title: spec.title ?? spec.id,
order: typeof spec.order === 'number' ? spec.order : 0,
url: spec.url ?? `/app/${spec.id}`,
subUrlBase: spec.subUrlBase ?? spec.url,
disableSubUrlTracking: spec.disableSubUrlTracking,
icon: spec.icon,
euiIconType: spec.euiIconType,
linkToLastSubUrl: spec.linkToLastSubUrl ?? false,
hidden: spec.hidden ?? false,
disabled: spec.disabled ?? false,
tooltip: spec.tooltip ?? '',
};
}

const id = spec.id;
function isHidden(app: LegacyAppSpec) {
return app.listed === false || app.hidden === true;
}

if (!id) {
throw new Error('Every app must specify an id');
}
export function getNavLinks(uiExports: LegacyUiExports, pluginSpecs: LegacyPluginSpec[]) {
const navLinkSpecs = uiExports.navLinkSpecs || [];
const appSpecs = (uiExports.uiAppSpecs || []).filter(
app => app !== undefined && !isHidden(app)
) as LegacyAppSpec[];

if (spec.pluginId && !pluginSpecs.some(plugin => plugin.getId() === spec.pluginId)) {
const pluginIds = (pluginSpecs || []).map(spec => spec.getId());
appSpecs.forEach(spec => {
if (spec.pluginId && !pluginIds.includes(spec.pluginId)) {
throw new Error(`Unknown plugin id "${spec.pluginId}"`);
}

const listed = typeof spec.listed === 'boolean' ? spec.listed : true;

if (spec.hidden || !listed) {
return REMOVE_FROM_ARRAY;
}

return {
id,
category: spec.category,
title: spec.title,
order: typeof spec.order === 'number' ? spec.order : 0,
icon: spec.icon,
euiIconType: spec.euiIconType,
url: spec.url || `/app/${id}`,
linkToLastSubUrl: spec.linkToLastSubUrl,
};
});
}

export function getNavLinks(uiExports: LegacyUiExports, pluginSpecs: LegacyPluginSpec[]) {
return (uiExports.navLinkSpecs || [])
.map<LegacyNavLink>(spec => ({
id: spec.id,
category: spec.category,
title: spec.title,
order: typeof spec.order === 'number' ? spec.order : 0,
url: spec.url,
subUrlBase: spec.subUrlBase || spec.url,
disableSubUrlTracking: spec.disableSubUrlTracking,
icon: spec.icon,
euiIconType: spec.euiIconType,
linkToLastSub: 'linkToLastSubUrl' in spec ? spec.linkToLastSubUrl : false,
hidden: 'hidden' in spec ? spec.hidden : false,
disabled: 'disabled' in spec ? spec.disabled : false,
tooltip: spec.tooltip || '',
}))
.concat(getUiAppsNavLinks(uiExports, pluginSpecs))
.sort((a, b) => a.order - b.order);
return [...navLinkSpecs, ...appSpecs].map(convertToNavLink).sort((a, b) => a.order - b.order);
}
10 changes: 5 additions & 5 deletions src/core/server/legacy/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,16 +131,16 @@ export type VarsReplacer = (
* @internal
* @deprecated
*/
export type LegacyNavLinkSpec = Record<string, unknown> & ChromeNavLink;
export type LegacyNavLinkSpec = Partial<ChromeNavLink>;

/**
* @internal
* @deprecated
*/
export type LegacyAppSpec = Pick<
ChromeNavLink,
'title' | 'order' | 'icon' | 'euiIconType' | 'url' | 'linkToLastSubUrl' | 'hidden' | 'category'
> & { pluginId?: string; id?: string; listed?: boolean };
export type LegacyAppSpec = Partial<ChromeNavLink> & {
pluginId?: string;
listed?: boolean;
};

/**
* @internal
Expand Down

0 comments on commit a817d84

Please sign in to comment.