Skip to content

Commit 55eddef

Browse files
chore(share-access-select): Migrate ShareAccessSelect (#4013)
* chore(share-access-select): Migrate ShareAccessSelect * chore(share-access-select): Migrate ShareAccessSelect
1 parent 7dd2934 commit 55eddef

File tree

3 files changed

+169
-2
lines changed

3 files changed

+169
-2
lines changed

src/elements/common/share-access-select/ShareAccessSelect.js renamed to src/elements/common/share-access-select/ShareAccessSelect.js.flow

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
/**
2-
* @flow
3-
* @file Content Explorer Delete Confirmation Dialog
2+
* @file Share Access Select component
43
* @author Box
54
*/
65

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* @file Share Access Select component
3+
* @author Box
4+
*/
5+
6+
import * as React from 'react';
7+
import { useIntl } from 'react-intl';
8+
import { ACCESS_NONE, ACCESS_OPEN, ACCESS_COLLAB, ACCESS_COMPANY } from '../../../constants';
9+
import type { BoxItem } from '../../../common/types/core';
10+
11+
import './ShareAccessSelect.scss';
12+
13+
import messages from '../messages';
14+
15+
export interface ShareAccessSelectProps {
16+
canSetShareAccess: boolean;
17+
className: string;
18+
item: BoxItem;
19+
onChange: (value: string, item: BoxItem) => void;
20+
}
21+
22+
const ShareAccessSelect = ({ className, canSetShareAccess, onChange, item }: ShareAccessSelectProps) => {
23+
const { formatMessage } = useIntl();
24+
const { allowed_shared_link_access_levels: allowedSharedAccessLevels, permissions, shared_link: sharedLink } = item;
25+
26+
if (!allowedSharedAccessLevels) {
27+
return <span />;
28+
}
29+
30+
const { access = ACCESS_NONE } = sharedLink || {};
31+
const { can_set_share_access: allowShareAccessChange } = permissions || {};
32+
33+
const changeHandler = ({ target }: React.ChangeEvent<HTMLSelectElement>) => onChange(target.value, item);
34+
const allowOpen = allowedSharedAccessLevels.indexOf(ACCESS_OPEN) > -1;
35+
const allowCollab = allowedSharedAccessLevels.indexOf(ACCESS_COLLAB) > -1;
36+
const allowCompany = allowedSharedAccessLevels.indexOf(ACCESS_COMPANY) > -1;
37+
const allowed = canSetShareAccess && allowShareAccessChange && (allowOpen || allowCompany || allowCollab);
38+
39+
if (!allowed) {
40+
return <span />;
41+
}
42+
43+
/* eslint-disable jsx-a11y/no-onchange */
44+
return (
45+
<select className={`be-share-access-select ${className}`} onChange={changeHandler} value={access}>
46+
{allowOpen ? <option value={ACCESS_OPEN}>{formatMessage(messages.shareAccessOpen)}</option> : null}
47+
{allowCollab ? <option value={ACCESS_COLLAB}>{formatMessage(messages.shareAccessCollab)}</option> : null}
48+
{allowCompany ? <option value={ACCESS_COMPANY}>{formatMessage(messages.shareAccessCompany)}</option> : null}
49+
<option value={ACCESS_NONE}>
50+
{access === ACCESS_NONE
51+
? formatMessage(messages.shareAccessNone)
52+
: formatMessage(messages.shareAccessRemove)}
53+
</option>
54+
</select>
55+
);
56+
};
57+
58+
export default ShareAccessSelect;
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import React from 'react';
2+
import { screen, render, fireEvent } from '../../../../test-utils/testing-library';
3+
import ShareAccessSelect from '../ShareAccessSelect';
4+
import { ACCESS_NONE, ACCESS_OPEN, ACCESS_COLLAB, ACCESS_COMPANY } from '../../../../constants';
5+
6+
describe('elements/common/share-access-select/ShareAccessSelect', () => {
7+
const getDefaultItem = (overrides = {}) => ({
8+
allowed_shared_link_access_levels: [ACCESS_OPEN, ACCESS_COLLAB, ACCESS_COMPANY],
9+
permissions: {
10+
can_set_share_access: true,
11+
},
12+
shared_link: {
13+
access: ACCESS_NONE,
14+
},
15+
...overrides,
16+
});
17+
18+
const defaultProps = {
19+
canSetShareAccess: true,
20+
className: 'test-share-access',
21+
item: getDefaultItem(),
22+
onChange: jest.fn(),
23+
};
24+
25+
const renderComponent = (props = {}) => {
26+
return render(<ShareAccessSelect {...defaultProps} {...props} />);
27+
};
28+
29+
test('should render select with all options when all access levels are allowed', () => {
30+
renderComponent();
31+
32+
const select = screen.getByRole('combobox');
33+
expect(select).toHaveClass('be-share-access-select test-share-access');
34+
35+
const options = screen.getAllByRole('option');
36+
expect(options).toHaveLength(4); // Open, Collab, Company, and None
37+
expect(options[0]).toHaveValue(ACCESS_OPEN);
38+
expect(screen.getByText('Access: People with the link')).toBeInTheDocument();
39+
expect(options[1]).toHaveValue(ACCESS_COLLAB);
40+
expect(screen.getByText('Access: People in this folder')).toBeInTheDocument();
41+
expect(options[2]).toHaveValue(ACCESS_COMPANY);
42+
expect(screen.getByText('People in this company')).toBeInTheDocument();
43+
expect(options[3]).toHaveValue(ACCESS_NONE);
44+
expect(screen.getByText('No shared link')).toBeInTheDocument();
45+
});
46+
47+
test('should render only allowed access level options', () => {
48+
const item = getDefaultItem({
49+
allowed_shared_link_access_levels: [ACCESS_OPEN, ACCESS_COMPANY],
50+
});
51+
renderComponent({ item });
52+
53+
const options = screen.getAllByRole('option');
54+
expect(options).toHaveLength(3); // Open, Company, and None
55+
expect(options[0]).toHaveValue(ACCESS_OPEN);
56+
expect(screen.getByText('Access: People with the link')).toBeInTheDocument();
57+
expect(options[1]).toHaveValue(ACCESS_COMPANY);
58+
expect(screen.getByText('People in this company')).toBeInTheDocument();
59+
expect(options[2]).toHaveValue(ACCESS_NONE);
60+
expect(screen.getByText('No shared link')).toBeInTheDocument();
61+
});
62+
63+
test('should not render select when canSetShareAccess is false', () => {
64+
renderComponent({ canSetShareAccess: false });
65+
expect(screen.queryByRole('combobox')).not.toBeInTheDocument();
66+
});
67+
68+
test('should not render select when can_set_share_access permission is false', () => {
69+
const item = getDefaultItem({
70+
permissions: { can_set_share_access: false },
71+
});
72+
renderComponent({ item });
73+
expect(screen.queryByRole('combobox')).not.toBeInTheDocument();
74+
});
75+
76+
test('should not render select when no allowed_shared_link_access_levels', () => {
77+
const item = getDefaultItem({
78+
allowed_shared_link_access_levels: null,
79+
});
80+
renderComponent({ item });
81+
expect(screen.queryByRole('combobox')).not.toBeInTheDocument();
82+
});
83+
84+
test('should call onChange with selected value and item when selection changes', () => {
85+
const onChange = jest.fn();
86+
renderComponent({ onChange });
87+
88+
const select = screen.getByRole('combobox');
89+
fireEvent.change(select, { target: { value: ACCESS_OPEN } });
90+
91+
expect(onChange).toHaveBeenCalledWith(ACCESS_OPEN, defaultProps.item);
92+
});
93+
94+
test('should show "Remove" text for ACCESS_NONE option when current access is not ACCESS_NONE', () => {
95+
const item = getDefaultItem({
96+
shared_link: { access: ACCESS_OPEN },
97+
});
98+
renderComponent({ item });
99+
100+
const noneOption = screen.getByRole('option', { name: 'Remove shared link' });
101+
expect(noneOption).toBeInTheDocument();
102+
});
103+
104+
test('should show "None" text for ACCESS_NONE option when current access is ACCESS_NONE', () => {
105+
renderComponent();
106+
107+
const noneOption = screen.getByRole('option', { name: 'No shared link' });
108+
expect(noneOption).toBeInTheDocument();
109+
});
110+
});

0 commit comments

Comments
 (0)