box-ui-elements-test
Version:
Box UI Elements
633 lines (545 loc) • 24.7 kB
JavaScript
import React from 'react';
import sinon from 'sinon';
import { ANYONE_IN_COMPANY, ANYONE_WITH_LINK, CAN_EDIT, CAN_VIEW_DOWNLOAD } from '../constants';
import { SharedLinkSectionBase as SharedLinkSection } from '../SharedLinkSection';
const sandbox = sinon.sandbox.create();
describe('features/unified-share-modal/SharedLinkSection', () => {
const intl = { formatMessage: jest.fn().mockImplementation(message => message.defaultMessage) };
const defaultItem = {
grantedPermissions: {
itemShare: true,
},
};
const getWrapper = (props = {}) =>
shallow(
<SharedLinkSection
autofocusSharedLink={false}
changeSharedLinkAccessLevel={sandbox.stub()}
changeSharedLinkPermissionLevel={sandbox.stub()}
intl={intl}
item={defaultItem}
itemType="file"
onDismissTooltip={() => {}}
showSharedLinkSettingsCallout
tooltips={{}}
{...props}
/>,
);
test('should render default component with shared link', () => {
expect(
getWrapper({
sharedLink: {
accessLevel: 'peopleInYourCompany',
canChangeAccessLevel: true,
enterpriseName: 'Box',
expirationTimestamp: 0,
url: 'https://example.com/shared-link',
},
}),
).toMatchSnapshot();
});
test('should render default component with no sharedLink', () => {
expect(
getWrapper({
sharedLink: {
url: '',
},
}),
).toMatchSnapshot();
});
test('should render GuideTooltip with isShown set to true if canShow is true', () => {
const wrapper = getWrapper({
isAllowEditSharedLinkForFileEnabled: true,
sharedLink: {
accessLevel: ANYONE_WITH_LINK,
canChangeAccessLevel: false,
enterpriseName: 'Box',
expirationTimestamp: 0,
isEditSettingAvailable: true,
permissionLevel: CAN_EDIT,
url: 'https://example.com/shared-link',
},
sharedLinkEditTooltipTargetingApi: {
canShow: true,
onComplete: jest.fn(),
onShow: jest.fn(),
},
});
expect(wrapper.find('GuideTooltip').props().isShown).toBe(true);
});
test('should call onClose when GuideTooltip is dismissed', () => {
const onClose = jest.fn();
const wrapper = getWrapper({
isAllowEditSharedLinkForFileEnabled: true,
sharedLink: {
accessLevel: ANYONE_WITH_LINK,
canChangeAccessLevel: false,
enterpriseName: 'Box',
expirationTimestamp: 0,
isEditSettingAvailable: true,
permissionLevel: CAN_EDIT,
url: 'https://example.com/shared-link',
},
sharedLinkEditTooltipTargetingApi: {
canShow: true,
onClose,
onShow: jest.fn(),
},
});
wrapper
.find('GuideTooltip')
.dive()
.simulate('dismiss');
expect(onClose).toHaveBeenCalledTimes(1);
});
test.each`
permissionLevel | testID
${CAN_EDIT} | ${'shared-link-editable-publicly-available-message'}
${CAN_VIEW_DOWNLOAD} | ${'shared-link-publicly-available-message'}
`(
'should render correct message based on permissionLevel and when accessLevel is ANYONE_WITH_LINK',
({ testID, permissionLevel }) => {
const wrapper = getWrapper({
sharedLink: {
accessLevel: ANYONE_WITH_LINK,
canChangeAccessLevel: false,
enterpriseName: 'Box',
expirationTimestamp: 0,
url: 'https://example.com/shared-link',
permissionLevel,
},
});
expect(wrapper.find(`[data-testid="${testID}"]`).length).toEqual(1);
},
);
test('should render a default component when there is a shared link but user lacks permission to toggle off', () => {
const wrapper = getWrapper({
sharedLink: {
accessLevel: 'peopleInYourCompany',
canChangeAccessLevel: false,
enterpriseName: 'Box',
expirationTimestamp: 0,
url: 'https://example.com/shared-link',
},
});
expect(wrapper).toMatchSnapshot();
});
test('should render default components with proper tooltip state while submitting request', () => {
const wrapper = getWrapper({
sharedLink: { url: '' },
submitting: true,
});
expect(wrapper).toMatchSnapshot();
});
test('should match snapshot when shared link expiration is set', () => {
const wrapper = getWrapper({
sharedLink: {
accessLevel: 'peopleInYourCompany',
canChangeAccessLevel: true,
enterpriseName: 'Box',
expirationTimestamp: 1519404618000,
url: 'https://example.com/shared-link',
},
});
expect(wrapper).toMatchSnapshot();
});
test('should render settings link when handler is provided and shared link is enabled', () => {
const wrapper = getWrapper({
onSettingsClick: jest.fn(),
sharedLink: {
accessLevel: 'peopleInYourCompany',
canChangeAccessLevel: true,
enterpriseName: 'Box',
expirationTimestamp: 0,
url: 'https://example.com/shared-link',
},
trackingProps: {
sharedLinkSettingsButtonProps: {
'data-resin-target': 'settings',
},
},
});
const btn = wrapper.find('.shared-link-settings-btn');
btn.simulate('click');
expect(btn).toMatchSnapshot();
});
test('should not render settings link when handler not provided', () => {
const wrapper = getWrapper({
sharedLink: {
accessLevel: 'peopleInYourCompany',
canChangeAccessLevel: true,
enterpriseName: 'Box',
expirationTimestamp: 0,
url: 'https://example.com/shared-link',
},
onSettingsClick: undefined,
});
expect(wrapper.find('.shared-link-settings-btn').length).toBe(0);
});
test('should render proper dropdown override when viewing an editable box note', () => {
const wrapper = getWrapper({
item: {
accessLevel: 'peopleInYourCompany',
description: 'some description',
extension: 'boxnote',
id: 12345,
name: 'text.boxnote',
type: 'file',
...defaultItem,
},
sharedLink: {
isEditAllowed: true,
url: 'http://example.com/s/abc',
isNewSharedLink: false,
},
});
expect(wrapper).toMatchSnapshot();
});
test('should render without SharedLinkPermissionMenu if access level is "people in item"', () => {
const wrapper = getWrapper({
sharedLink: {
accessLevel: 'peopleInThisItem',
canChangeAccessLevel: true,
enterpriseName: 'Box',
expirationTimestamp: 0,
url: 'https://example.com/shared-link',
},
});
expect(wrapper).toMatchSnapshot();
});
[
{
isDownloadSettingAvailable: true,
},
{
isDownloadSettingAvailable: false,
},
].forEach(({ isDownloadSettingAvailable }) => {
test('should render proper list of permission options based on the the download setting availability', () => {
const wrapper = getWrapper({
sharedLink: {
accessLevel: 'peopleInYourCompany',
canChangeAccessLevel: true,
enterpriseName: 'Box',
isDownloadSettingAvailable,
expirationTimestamp: 0,
url: 'https://example.com/shared-link',
},
});
expect(wrapper).toMatchSnapshot();
});
});
[
{
isEditSettingAvailable: true,
},
{
isEditSettingAvailable: false,
},
].forEach(({ isEditSettingAvailable }) => {
test('should render proper list of permission options based on the the edit setting availability', () => {
const wrapper = getWrapper({
sharedLink: {
accessLevel: 'peopleInYourCompany',
canChangeAccessLevel: true,
enterpriseName: 'Box',
isEditSettingAvailable,
expirationTimestamp: 0,
url: 'https://example.com/shared-link',
},
});
expect(wrapper).toMatchSnapshot();
});
});
test('should render disabled create shared link message when item share is false and url is empty', () => {
const sharedLink = { url: '', canChangeAccessLevel: true };
const item = { grantedPermissions: { itemShare: false } };
const wrapper = getWrapper({ sharedLink, item });
const tooltip = wrapper.find('.usm-disabled-message-tooltip');
expect(tooltip).toMatchSnapshot();
});
test('should render disabled remove shared link message when url is not empty and canChangeAccessLevel is false', () => {
const sharedLink = { url: 'https://example.com/shared-link', canChangeAccessLevel: false };
const wrapper = getWrapper({ sharedLink });
const tooltip = wrapper.find('.usm-disabled-message-tooltip');
expect(tooltip).toMatchSnapshot();
});
test.each`
config | emailButtonExists | description
${undefined} | ${true} | ${'should render email shared link button when config is undefined'}
${{ foo: 'bar' }} | ${true} | ${'should render email shared link button when config does not contain showEmailSharedLinkForm'}
${{ showEmailSharedLinkForm: true }} | ${true} | ${'should render email shared link button when config.showEmailSharedLinkForm is true'}
${{ showEmailSharedLinkForm: false }} | ${false} | ${'should not render email shared link button when config.showEmailSharedLinkForm is false'}
`('$description', ({ config, emailButtonExists }) => {
const sharedLink = { url: 'https://example.com/shared-link' };
const wrapper = getWrapper({ config, sharedLink });
expect(wrapper.exists('.email-shared-link-btn')).toBe(emailButtonExists);
});
test('should have aria-label and role on shared link expiration badge when expiration timestamp exists', () => {
// Set an expiration timestamp so that Toggle is rendered with expiration icon
const sharedLink = {
expirationTimestamp: 1,
url: 'https://example.com/shared-link',
};
const wrapper = getWrapper({ sharedLink });
const toggle = wrapper.find('Toggle');
// The aria-label attr is on a span, which is contained within the label of the Toggle component
const spanLabel = toggle.dive().find('.shared-link-expiration-badge');
expect(spanLabel.prop('aria-label')).toBe('Expires');
expect(spanLabel.prop('role')).toBe('img');
});
describe('componentDidMount()', () => {
test('should attempt shared link creation when component is mounted with initial, empty shared link data', () => {
const sharedLink = { url: '', isNewSharedLink: false };
const addSharedLink = jest.fn();
const wrapper = getWrapper({
addSharedLink,
submitting: false,
autoCreateSharedLink: true,
sharedLink,
});
expect(addSharedLink).toBeCalledTimes(1);
expect(wrapper.state().isAutoCreatingSharedLink).toBe(true);
});
test('should note attempt shared link creation when component is mounted with a shared link', () => {
const sharedLink = { url: 'sftp://example.org/', isNewSharedLink: false };
const addSharedLink = jest.fn();
const wrapper = getWrapper({
addSharedLink,
submitting: false,
autoCreateSharedLink: true,
sharedLink,
});
expect(addSharedLink).toBeCalledTimes(0);
expect(wrapper.state().isAutoCreatingSharedLink).toBe(false);
});
});
describe('componentDidUpdate()', () => {
afterEach(() => {
global.navigator.clipboard = undefined;
});
test('should render correct shared link message when permissionLevel is elevated to CAN_EDIT and accessLevel is ANYONE_IN_COMPANY', () => {
const sharedLink = {
accessLevel: ANYONE_IN_COMPANY,
url: 'http://example.com/',
isNewSharedLink: false,
permissionLevel: CAN_VIEW_DOWNLOAD,
};
const wrapper = getWrapper({ sharedLink });
wrapper.setProps({
sharedLink: {
accessLevel: ANYONE_IN_COMPANY,
url: 'http://example.com/',
isNewSharedLink: false,
permissionLevel: CAN_EDIT,
},
});
expect(
wrapper.find(`[data-testid="shared-link-elevated-editable-company-available-message"]`).length,
).toEqual(1);
});
test.each`
accessLevel | should
${ANYONE_IN_COMPANY} | ${'updated to a non CAN_EDIT permission'}
${ANYONE_WITH_LINK} | ${'accessLevel is updated to a non ANYONE_IN_COMPANY access level'}
`(
'should no longer show warning message after permissionLevel is elevated to CAN_EDIT and then $should',
({ accessLevel }) => {
const sharedLink = {
accessLevel: ANYONE_IN_COMPANY,
url: 'http://example.com/',
isNewSharedLink: false,
permissionLevel: CAN_VIEW_DOWNLOAD,
};
const wrapper = getWrapper({ sharedLink });
wrapper.setProps({
sharedLink: {
accessLevel: ANYONE_IN_COMPANY,
url: 'http://example.com/',
isNewSharedLink: false,
permissionLevel: CAN_EDIT,
},
});
expect(
wrapper.find(`[data-testid="shared-link-elevated-editable-company-available-message"]`).length,
).toEqual(1);
wrapper.setProps({
sharedLink: {
accessLevel,
url: 'http://example.com/',
isNewSharedLink: false,
permissionLevel: CAN_VIEW_DOWNLOAD,
},
});
expect(
wrapper.find(`[data-testid="shared-link-elevated-editable-company-available-message"]`).length,
).toEqual(0);
},
);
test('should call addSharedLink when modal is triggered to create a URL', () => {
const sharedLink = { url: '', isNewSharedLink: false };
const addSharedLink = jest.fn();
const wrapper = getWrapper({
addSharedLink,
submitting: true,
autoCreateSharedLink: true,
sharedLink,
});
expect(wrapper.state().isAutoCreatingSharedLink).toBe(false);
wrapper.setProps({ submitting: false });
expect(addSharedLink).toBeCalledTimes(1);
expect(wrapper.state().isAutoCreatingSharedLink).toBe(true);
wrapper.setProps({ sharedLink: { url: 'http://example.com/', isNewSharedLink: true } });
expect(wrapper.state().isAutoCreatingSharedLink).toBe(false);
});
test('should not call addSharedLink when modal is triggered to fetch existing URL', () => {
const sharedLink = { url: 'http://example.com/', isNewSharedLink: false };
const addSharedLink = jest.fn();
const wrapper = getWrapper({
addSharedLink,
submitting: true,
autoCreateSharedLink: true,
sharedLink,
});
expect(wrapper.state().isAutoCreatingSharedLink).toBe(false);
wrapper.setProps({ submitting: false });
expect(addSharedLink).toBeCalledTimes(0);
expect(wrapper.state().isAutoCreatingSharedLink).toBe(false);
});
test('should handle attempt to copy when the clipboard API is available and request is successful', async () => {
expect.assertions(6);
const sharedLink = { url: '', isNewSharedLink: false };
const addSharedLink = jest.fn();
const onCopyInitMock = jest.fn();
const onCopySuccessMock = jest.fn();
const onCopyErrorMock = jest.fn();
const writeTextSuccessMock = jest.fn(() => Promise.resolve());
navigator.clipboard = {
writeText: writeTextSuccessMock,
};
const wrapper = getWrapper({
addSharedLink,
autoCreateSharedLink: true,
onCopyError: onCopyErrorMock,
onCopyInit: onCopyInitMock,
onCopySuccess: onCopySuccessMock,
sharedLink,
submitting: true,
triggerCopyOnLoad: true,
});
wrapper.setProps({ submitting: false });
wrapper.setProps({ sharedLink: { url: 'http://example.com/', isNewSharedLink: true } });
await new Promise(r => setTimeout(r, 0));
expect(onCopyInitMock).toBeCalledTimes(1);
expect(writeTextSuccessMock).toBeCalledTimes(1);
expect(onCopySuccessMock).toBeCalledTimes(1);
expect(wrapper.find('TextInputWithCopyButton').prop('triggerCopyOnLoad')).toBe(true);
expect(wrapper.state('isCopySuccessful')).toEqual(true);
expect(onCopyErrorMock).toBeCalledTimes(0);
});
test('should call onSharedLinkCopy with current permission level when copy button is clicked', () => {
const onSharedLinkCopy = jest.fn();
const sharedLink = { url: 'http://example.com/', isNewSharedLink: false, permissionLevel: CAN_EDIT };
const wrapper = getWrapper({
sharedLink,
trackingProps: { onSharedLinkCopy },
});
wrapper.find('TextInputWithCopyButton').prop('onCopySuccess')();
expect(onSharedLinkCopy).toBeCalledWith(CAN_EDIT);
});
test('should only initiate copy when we specifically request a copy to be triggered', () => {
const sharedLink = { url: '', isNewSharedLink: false };
const addSharedLink = jest.fn();
const onCopyInitMock = jest.fn();
const onCopySuccessMock = jest.fn();
const onCopyErrorMock = jest.fn();
const writeTextSuccessMock = jest.fn(() => Promise.resolve());
navigator.clipboard = {
writeText: writeTextSuccessMock,
};
const wrapper = getWrapper({
addSharedLink,
autoCreateSharedLink: true,
autofocusSharedLink: true,
onCopyError: onCopyErrorMock,
onCopyInit: onCopyInitMock,
onCopySuccess: onCopySuccessMock,
sharedLink,
submitting: true,
triggerCopyOnLoad: false,
});
wrapper.setProps({ submitting: false });
wrapper.setProps({ sharedLink: { url: 'http://example.com/', isNewSharedLink: true } });
expect(onCopyInitMock).toBeCalledTimes(0);
expect(writeTextSuccessMock).toBeCalledTimes(0);
expect(onCopySuccessMock).toBeCalledTimes(0);
expect(onCopyErrorMock).toBeCalledTimes(0);
});
test('should handle attempt to copy when the clipboard request fails', async () => {
expect.assertions(6);
const sharedLink = { url: '', isNewSharedLink: false };
const addSharedLink = jest.fn();
const onCopyInitMock = jest.fn();
const onCopySuccessMock = jest.fn();
const onCopyErrorMock = jest.fn();
const writeTextRejectMock = jest.fn(() => Promise.reject());
navigator.clipboard = {
writeText: writeTextRejectMock,
};
const wrapper = getWrapper({
addSharedLink,
autoCreateSharedLink: true,
onCopyError: onCopyErrorMock,
onCopyInit: onCopyInitMock,
onCopySuccess: onCopySuccessMock,
sharedLink,
submitting: true,
triggerCopyOnLoad: true,
});
wrapper.setProps({ submitting: false });
wrapper.setProps({ sharedLink: { url: 'http://example.com/', isNewSharedLink: true } });
await new Promise(r => setTimeout(r, 0));
expect(onCopyInitMock).toBeCalledTimes(1);
expect(writeTextRejectMock).toBeCalledTimes(1);
expect(onCopySuccessMock).toBeCalledTimes(0);
expect(onCopyErrorMock).toBeCalledTimes(1);
expect(wrapper.find('TextInputWithCopyButton').prop('triggerCopyOnLoad')).toBe(false);
expect(wrapper.state('isCopySuccessful')).toEqual(false);
});
test.each`
isEditSettingAvailable | isAllowEditSharedLinkForFileEnabled | canShow | expected | should
${false} | ${false} | ${false} | ${0} | ${'should not call onShow if user cannot edit and ESL FF is off and canShow is false'}
${true} | ${false} | ${false} | ${0} | ${'should not call onShow if user can edit but ESL FF is off and canShow is false'}
${true} | ${true} | ${false} | ${0} | ${'should not call onShow if user can edit and ESL FF is on but canShow is false'}
${true} | ${true} | ${true} | ${1} | ${'should call onShow if user can edit and ESL FF is on and canShow is true'}
`('$should', ({ canShow, isAllowEditSharedLinkForFileEnabled, isEditSettingAvailable, expected }) => {
const onShow = jest.fn();
const onComplete = jest.fn();
const wrapper = getWrapper({
isAllowEditSharedLinkForFileEnabled,
sharedLink: {
accessLevel: ANYONE_WITH_LINK,
canChangeAccessLevel: false,
enterpriseName: 'Box',
expirationTimestamp: 0,
isEditSettingAvailable,
permissionLevel: CAN_EDIT,
url: 'https://example.com/shared-link',
},
sharedLinkEditTooltipTargetingApi: {
canShow: false,
onComplete,
onShow,
},
});
wrapper.setProps({
sharedLinkEditTooltipTargetingApi: {
canShow,
onComplete,
onShow,
},
});
expect(onShow).toHaveBeenCalledTimes(expected);
});
});
});