import ActionsDropdown, {
ActionsDropdownItem
} from 'sonar-ui-common/components/controls/ActionsDropdown';
+import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner';
import RestoreAccessModal from './RestoreAccessModal';
import ApplyTemplate from '../permissions/project/components/ApplyTemplate';
-import { getComponentShow, Project } from '../../api/components';
+import { Project } from '../../api/components';
import { getComponentNavigation } from '../../api/nav';
import { getComponentPermissionsUrl } from '../../helpers/urls';
}
fetchPermissions = () => {
- this.setState({ loading: false });
- // call `getComponentNavigation` to check if user has the "Administer" permission
- // call `getComponentShow` to check if user has the "Browse" permission
- Promise.all([
- getComponentNavigation({ component: this.props.project.key }),
- getComponentShow({ component: this.props.project.key })
- ]).then(
- ([navResponse]) => {
+ this.setState({ loading: true });
+ getComponentNavigation({ component: this.props.project.key }).then(
+ ({ configuration }) => {
if (this.mounted) {
- const hasAccess = Boolean(
- navResponse.configuration && navResponse.configuration.showPermissions
- );
+ const hasAccess = Boolean(configuration && configuration.showPermissions);
this.setState({ hasAccess, loading: false });
}
},
() => {
if (this.mounted) {
- this.setState({ hasAccess: false, loading: false });
+ this.setState({ loading: false });
}
}
);
};
render() {
- const { hasAccess } = this.state;
+ const { hasAccess, loading } = this.state;
return (
<>
<ActionsDropdown onOpen={this.handleDropdownOpen}>
- {hasAccess === true && (
- <ActionsDropdownItem to={getComponentPermissionsUrl(this.props.project.key)}>
- {translate('edit_permissions')}
- </ActionsDropdownItem>
- )}
-
- {hasAccess === false && (
- <ActionsDropdownItem
- className="js-restore-access"
- onClick={this.handleRestoreAccessClick}>
- {translate('global_permissions.restore_access')}
+ {loading ? (
+ <ActionsDropdownItem>
+ <DeferredSpinner />
</ActionsDropdownItem>
+ ) : (
+ <>
+ {hasAccess === true && (
+ <ActionsDropdownItem
+ className="js-edit-permissions"
+ to={getComponentPermissionsUrl(this.props.project.key)}>
+ {translate('edit_permissions')}
+ </ActionsDropdownItem>
+ )}
+
+ {hasAccess === false && (
+ <ActionsDropdownItem
+ className="js-restore-access"
+ onClick={this.handleRestoreAccessClick}>
+ {translate('global_permissions.restore_access')}
+ </ActionsDropdownItem>
+ )}
+ </>
)}
<ActionsDropdownItem
import { shallow } from 'enzyme';
import { click, waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
import ProjectRowActions, { Props } from '../ProjectRowActions';
-import { Project } from '../../../api/components';
-
-jest.mock('../../../api/components', () => ({
- getComponentShow: jest.fn(() => Promise.reject(undefined))
-}));
+import { mockLoggedInUser } from '../../../helpers/testMocks';
+import { getComponentNavigation } from '../../../api/nav';
jest.mock('../../../api/nav', () => ({
- getComponentNavigation: jest.fn(() => Promise.resolve())
+ getComponentNavigation: jest.fn().mockResolvedValue({})
}));
-const project: Project = {
- id: '',
- key: 'project',
- name: 'Project',
- organization: 'org',
- qualifier: 'TRK',
- visibility: 'private'
-};
-
-it('restores access', async () => {
+it('renders correctly', () => {
const wrapper = shallowRender();
expect(wrapper).toMatchSnapshot();
+});
- wrapper.find('ActionsDropdown').prop<Function>('onOpen')();
- await waitAndUpdate(wrapper);
- expect(wrapper).toMatchSnapshot();
+describe('restore access', () => {
+ beforeAll(() => {
+ jest.resetAllMocks();
+ (getComponentNavigation as jest.Mock).mockResolvedValue({
+ configuration: {
+ showPermissions: false
+ }
+ });
+ });
- click(wrapper.find('.js-restore-access'));
- wrapper.update();
- expect(wrapper).toMatchSnapshot();
+ it('shows the restore access action', async () => {
+ const wrapper = shallowRender();
+ wrapper.instance().handleDropdownOpen();
+ await waitAndUpdate(wrapper);
+
+ expect(getComponentNavigation).toBeCalledWith({ component: 'foo' });
+ expect(wrapper.find('.js-restore-access').exists()).toBe(true);
+ });
+
+ it('shows the restore access modal', async () => {
+ const wrapper = shallowRender();
+ wrapper.instance().handleDropdownOpen();
+ await waitAndUpdate(wrapper);
+
+ click(wrapper.find('.js-restore-access'));
+ expect(wrapper.find('RestoreAccessModal')).toMatchSnapshot();
+
+ wrapper.instance().handleRestoreAccessDone();
+ await waitAndUpdate(wrapper);
+ expect(wrapper.find('.js-restore-access').exists()).toBe(false);
+ expect(wrapper.find('RestoreAccessModal').exists()).toBe(false);
+ });
});
-it('applies permission template', () => {
- const wrapper = shallowRender();
- click(wrapper.find('.js-apply-template'));
- expect(wrapper.find('ApplyTemplate')).toMatchSnapshot();
+describe('permissions', () => {
+ beforeAll(() => {
+ jest.resetAllMocks();
+ (getComponentNavigation as jest.Mock).mockResolvedValue({
+ configuration: {
+ showPermissions: true
+ }
+ });
+ });
+
+ it('shows the update permissions action', async () => {
+ const wrapper = shallowRender();
+ wrapper.instance().handleDropdownOpen();
+ await waitAndUpdate(wrapper);
+ expect(wrapper.find('.js-edit-permissions').exists()).toBe(true);
+ });
+
+ it('shows the apply permission template modal', async () => {
+ const wrapper = shallowRender();
+ wrapper.instance().handleDropdownOpen();
+ await waitAndUpdate(wrapper);
+
+ click(wrapper.find('.js-apply-template'));
+ expect(wrapper.find('ApplyTemplate')).toMatchSnapshot();
+
+ wrapper.instance().handleApplyTemplateClose();
+ await waitAndUpdate(wrapper);
+ expect(wrapper.find('ApplyTemplate').exists()).toBe(false);
+ });
});
function shallowRender(props: Partial<Props> = {}) {
- const wrapper = shallow(
+ return shallow<ProjectRowActions>(
<ProjectRowActions
- currentUser={{ login: 'admin' }}
+ currentUser={mockLoggedInUser()}
organization="org"
- project={project}
+ project={{
+ id: 'foo',
+ key: 'foo',
+ name: 'Foo',
+ organization: 'bar',
+ qualifier: 'TRK',
+ visibility: 'private'
+ }}
{...props}
/>
);
- (wrapper.instance() as ProjectRowActions).mounted = true;
- return wrapper;
}
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`applies permission template 1`] = `
+exports[`permissions shows the apply permission template modal 1`] = `
<ApplyTemplate
onClose={[Function]}
organization="org"
project={
Object {
- "id": "",
- "key": "project",
- "name": "Project",
- "organization": "org",
+ "id": "foo",
+ "key": "foo",
+ "name": "Foo",
+ "organization": "bar",
"qualifier": "TRK",
"visibility": "private",
}
/>
`;
-exports[`restores access 1`] = `
+exports[`renders correctly 1`] = `
<Fragment>
<ActionsDropdown
onOpen={[Function]}
</Fragment>
`;
-exports[`restores access 2`] = `
-<Fragment>
- <ActionsDropdown
- onOpen={[Function]}
- >
- <ActionsDropdownItem
- className="js-restore-access"
- onClick={[Function]}
- >
- global_permissions.restore_access
- </ActionsDropdownItem>
- <ActionsDropdownItem
- className="js-apply-template"
- onClick={[Function]}
- >
- projects_role.apply_template
- </ActionsDropdownItem>
- </ActionsDropdown>
-</Fragment>
-`;
-
-exports[`restores access 3`] = `
-<Fragment>
- <ActionsDropdown
- onOpen={[Function]}
- >
- <ActionsDropdownItem
- className="js-restore-access"
- onClick={[Function]}
- >
- global_permissions.restore_access
- </ActionsDropdownItem>
- <ActionsDropdownItem
- className="js-apply-template"
- onClick={[Function]}
- >
- projects_role.apply_template
- </ActionsDropdownItem>
- </ActionsDropdown>
- <RestoreAccessModal
- currentUser={
- Object {
- "login": "admin",
- }
+exports[`restore access shows the restore access modal 1`] = `
+<RestoreAccessModal
+ currentUser={
+ Object {
+ "groups": Array [],
+ "isLoggedIn": true,
+ "login": "luke",
+ "name": "Skywalker",
+ "scmAccounts": Array [],
}
- onClose={[Function]}
- onRestoreAccess={[Function]}
- project={
- Object {
- "id": "",
- "key": "project",
- "name": "Project",
- "organization": "org",
- "qualifier": "TRK",
- "visibility": "private",
- }
+ }
+ onClose={[Function]}
+ onRestoreAccess={[Function]}
+ project={
+ Object {
+ "id": "foo",
+ "key": "foo",
+ "name": "Foo",
+ "organization": "bar",
+ "qualifier": "TRK",
+ "visibility": "private",
}
- />
-</Fragment>
+ }
+/>
`;