Skip to content

Commit

Permalink
Account for disabledShareUrl prop for rendered sharing options (elast…
Browse files Browse the repository at this point in the history
…ic#206592)

## Summary

Closes elastic#201980.

This PR adds logic to honor the `disabledShareUrl` prop. For the user
this means that in instances where the user doesn't have permissions to
create a share url, the link tab doesn't get rendered to such user.

## How to test

- Create a simple user and a custom role. Assign only Read capabilities
to Visualize Library
- Now sign up with that user, create a new lens visualization and try to
share it
- The share Link tab is not visible.

<!--

### Checklist

Check the PR satisfies following conditions.

Reviewers should verify this PR satisfies this list as well.

- [ ] 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/src/platform/packages/shared/kbn-i18n/README.md)
- [ ]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [ ] [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
- [ ] 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)
- [ ] This was checked for breaking HTTP API changes, and any breaking
changes have been approved by the breaking-change committee. The
`release_note:breaking` label should be applied in these situations.
- [ ] [Flaky Test
Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was
used on any tests changed
- [ ] The PR description includes the appropriate Release Notes section,
and the correct `release_note:*` label is applied per the
[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)

### Identify risks

Does this PR introduce any risks? For example, consider risks like hard
to test bugs, performance regression, potential of data loss.

Describe the risk, its severity, and mitigation for each identified
risk. Invite stakeholders and evaluate how to proceed before merging.

- [ ] [See some risk
examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx)
- [ ] ...

-->

(cherry picked from commit 44b756c)
  • Loading branch information
eokoneyo committed Jan 15, 2025
1 parent 8e0b526 commit e9c1a2d
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

import React from 'react';
import { ShareMenuTabs } from './share_tabs';
import { ShareMenuProvider } from './context';
import { ShareMenuProvider, type IShareContext } from './context';
import { mountWithIntl } from '@kbn/test-jest-helpers';
import { KibanaLocation, LocatorGetUrlParams, UrlService } from '../../common/url_service';
import {
Expand Down Expand Up @@ -48,7 +48,9 @@ const service = new UrlService<BrowserShortUrlClientFactoryCreateParams, Browser
locators,
}),
});
const mockShareContext = {

const mockShareContext: IShareContext = {
shareMenuItems: [],
allowEmbed: true,
allowShortUrl: true,
anonymousAccess: { getCapabilities: jest.fn(), getState: jest.fn() },
Expand All @@ -62,66 +64,81 @@ const mockShareContext = {
toasts: toastsServiceMock.createStartContract(),
i18n: i18nServiceMock.createStartContract(),
};

const mockGenerateExport = jest.fn();
const mockGenerateExportUrl = jest.fn().mockImplementation(() => 'generated-export-url');
const CSV = 'CSV' as const;
const PNG = 'PNG' as const;

describe('Share modal tabs', () => {
it('should render export tab when there are share menu items that are not disabled', async () => {
const testItem = [
{
shareMenuItem: { name: 'test', disabled: false },
label: CSV,
generateExport: mockGenerateExport,
generateExportUrl: mockGenerateExportUrl,
},
];
const wrapper = mountWithIntl(
<ShareMenuProvider shareContext={{ ...mockShareContext, shareMenuItems: testItem }}>
<ShareMenuTabs />
</ShareMenuProvider>
);
expect(wrapper.find('[data-test-subj="export"]').exists()).toBeTruthy();
describe('link tab', () => {
it('should not render the link tab when the disableShareUrl prop is true', async () => {
const wrapper = mountWithIntl(
<ShareMenuProvider shareContext={{ ...mockShareContext, disabledShareUrl: true }}>
<ShareMenuTabs />
</ShareMenuProvider>
);
expect(wrapper.find('[data-test-subj="link"]').exists()).toBeFalsy();
});
});
it('should not render export tab when the license is disabled', async () => {
const testItems = [
{
shareMenuItem: { name: 'test', disabled: true },
label: CSV,
generateExport: mockGenerateExport,
generateExportUrl: mockGenerateExportUrl,
},
];

const wrapper = mountWithIntl(
<ShareMenuProvider shareContext={{ ...mockShareContext, shareMenuItems: testItems }}>
<ShareMenuTabs />
</ShareMenuProvider>
);
describe('export tab', () => {
it('should render export tab when there are share menu items that are not disabled', async () => {
const testItem = [
{
shareMenuItem: { name: 'test', disabled: false },
label: CSV,
generateExport: mockGenerateExport,
generateExportUrl: mockGenerateExportUrl,
},
];
const wrapper = mountWithIntl(
<ShareMenuProvider shareContext={{ ...mockShareContext, shareMenuItems: testItem }}>
<ShareMenuTabs />
</ShareMenuProvider>
);
expect(wrapper.find('[data-test-subj="export"]').exists()).toBeTruthy();
});
it('should not render export tab when the license is disabled', async () => {
const testItems = [
{
shareMenuItem: { name: 'test', disabled: true },
label: CSV,
generateExport: mockGenerateExport,
generateExportUrl: mockGenerateExportUrl,
},
];

expect(wrapper.find('[data-test-subj="export"]').exists()).toBeFalsy();
});
const wrapper = mountWithIntl(
<ShareMenuProvider shareContext={{ ...mockShareContext, shareMenuItems: testItems }}>
<ShareMenuTabs />
</ShareMenuProvider>
);

expect(wrapper.find('[data-test-subj="export"]').exists()).toBeFalsy();
});

it('should render export tab is at least one is not disabled', async () => {
const testItem = [
{
shareMenuItem: { name: 'test', disabled: false },
label: CSV,
generateExport: mockGenerateExport,
generateExportUrl: mockGenerateExportUrl,
},
{
shareMenuItem: { name: 'test', disabled: true },
label: PNG,
generateExport: mockGenerateExport,
generateExportUrl: mockGenerateExportUrl,
},
];
const wrapper = mountWithIntl(
<ShareMenuProvider shareContext={{ ...mockShareContext, shareMenuItems: testItem }}>
<ShareMenuTabs />
</ShareMenuProvider>
);
expect(wrapper.find('[data-test-subj="export"]').exists()).toBeTruthy();
it('would render the export tab when there is at least one export type which is not disabled', async () => {
const testItem = [
{
shareMenuItem: { name: 'test', disabled: false },
label: CSV,
generateExport: mockGenerateExport,
generateExportUrl: mockGenerateExportUrl,
},
{
shareMenuItem: { name: 'test', disabled: true },
label: PNG,
generateExport: mockGenerateExport,
generateExportUrl: mockGenerateExportUrl,
},
];
const wrapper = mountWithIntl(
<ShareMenuProvider shareContext={{ ...mockShareContext, shareMenuItems: testItem }}>
<ShareMenuTabs />
</ShareMenuProvider>
);
expect(wrapper.find('[data-test-subj="export"]').exists()).toBeTruthy();
});
});
});
16 changes: 11 additions & 5 deletions src/platform/plugins/shared/share/public/components/share_tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,15 @@ export const ShareMenu: FC<{ shareContext: IShareContext }> = ({ shareContext })
export const ShareMenuTabs = () => {
const shareContext = useShareTabsContext();

const { allowEmbed, objectTypeMeta, onClose, shareMenuItems, anchorElement } = shareContext;
const { allowEmbed, objectTypeMeta, onClose, shareMenuItems, anchorElement, disabledShareUrl } =
shareContext;

const tabs: Array<IModalTabDeclaration<any>> = [linkTab];
const tabs: Array<IModalTabDeclaration<any>> = [];

// do not show the link tab if the share url is disabled
if (!disabledShareUrl) {
tabs.push(linkTab);
}

const enabledItems = shareMenuItems.filter(({ shareMenuItem }) => !shareMenuItem?.disabled);

Expand All @@ -40,15 +46,15 @@ export const ShareMenuTabs = () => {
tabs.push(embedTab);
}

return (
return Boolean(tabs.length) ? (
<TabbedModal
tabs={tabs}
modalWidth={498}
onClose={onClose}
modalTitle={objectTypeMeta.title}
defaultSelectedTabId="link"
defaultSelectedTabId={tabs[0].id}
anchorElement={anchorElement}
data-test-subj="shareContextModal"
/>
);
) : null;
};

0 comments on commit e9c1a2d

Please sign in to comment.