From 9eb56665afc581be79ef1c472e60da3cda243170 Mon Sep 17 00:00:00 2001 From: Dmytro-Melnyshyn <77053927+Dmytro-Melnyshyn@users.noreply.github.com> Date: Tue, 26 Nov 2024 11:51:31 +0200 Subject: [PATCH] UIQM-735: Return also sub permissions in `useUserTenantPermissions` hook. (#761) --- .github/workflows/build-npm-release.yml | 4 +- .github/workflows/build-npm.yml | 4 +- CHANGELOG.md | 4 ++ src/MarcRoute/MarcRoute.js | 2 +- src/MarcRoute/MarcRoute.test.js | 6 +-- src/QuickMarcEditor/QuickMarcEditor.test.js | 4 ++ .../QuickMarcEditorContainer.test.js | 48 +++++++++---------- .../useUserTenantPermissions.js | 19 +++++++- .../useUserTenantPermissions.test.js | 29 ++++++++++- 9 files changed, 85 insertions(+), 35 deletions(-) diff --git a/.github/workflows/build-npm-release.yml b/.github/workflows/build-npm-release.yml index c2694cf4..cb3d099e 100644 --- a/.github/workflows/build-npm-release.yml +++ b/.github/workflows/build-npm-release.yml @@ -149,7 +149,7 @@ jobs: comment_title: Jest Unit Test Statistics - name: Publish Jest coverage report - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 if: always() with: name: jest-coverage-report @@ -157,7 +157,7 @@ jobs: retention-days: 30 - name: Publish yarn.lock - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 if: failure() with: name: yarn.lock diff --git a/.github/workflows/build-npm.yml b/.github/workflows/build-npm.yml index b874e9a4..8cf5e1c2 100644 --- a/.github/workflows/build-npm.yml +++ b/.github/workflows/build-npm.yml @@ -92,7 +92,7 @@ jobs: comment_title: Jest Unit Test Statistics - name: Publish Jest coverage report - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 if: always() with: name: jest-coverage-report @@ -100,7 +100,7 @@ jobs: retention-days: 30 - name: Publish yarn.lock - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 if: failure() with: name: yarn.lock diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cd977bc..40eed1cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Change history for ui-quick-marc +## [8.0.2] (IN PROGRESS) + +* [UIQM-735](https://issues.folio.org/browse/UIQM-735) Return also sub permissions in `useUserTenantPermissions` hook. + ## [8.0.1] (https://github.com/folio-org/ui-quick-marc/tree/v8.0.1) (2024-04-18) * [UIQM-641](https://issues.folio.org/browse/UIQM-641) Call `cleanBytesFields` function with correct arguments to fix 008 field. diff --git a/src/MarcRoute/MarcRoute.js b/src/MarcRoute/MarcRoute.js index d6a17316..94c74c3a 100644 --- a/src/MarcRoute/MarcRoute.js +++ b/src/MarcRoute/MarcRoute.js @@ -44,7 +44,7 @@ const MarcRoute = ({ }); const checkCentralTenantPerm = useCallback((perm) => { - return centralTenantPermissions.some(({ permissionName }) => permissionName === perm); + return centralTenantPermissions.has(perm); }, [centralTenantPermissions]); if (isCentralTenantPermissionsLoading) { diff --git a/src/MarcRoute/MarcRoute.test.js b/src/MarcRoute/MarcRoute.test.js index 4e34a644..1e8754d3 100644 --- a/src/MarcRoute/MarcRoute.test.js +++ b/src/MarcRoute/MarcRoute.test.js @@ -40,7 +40,7 @@ const renderMarcRoute = ({ history, ...props } = {}) => (render( describe('Given Quick Marc', () => { beforeEach(() => { useUserTenantPermissions.mockReturnValue({ - userPermissions: [], + userPermissions: new Set(), isFetching: false, }); @@ -49,9 +49,7 @@ describe('Given Quick Marc', () => { describe('when a member tenant edits shared record', () => { it('should fetch the central tenant permissions', () => { - const userPermissions = [{ - permissionName: 'ui-quick-marc.quick-marc-editor.all', - }]; + const userPermissions = new Set(['ui-quick-marc.quick-marc-editor.all']); useUserTenantPermissions.mockReturnValue({ userPermissions, diff --git a/src/QuickMarcEditor/QuickMarcEditor.test.js b/src/QuickMarcEditor/QuickMarcEditor.test.js index 214a7d81..1a9dcd1d 100644 --- a/src/QuickMarcEditor/QuickMarcEditor.test.js +++ b/src/QuickMarcEditor/QuickMarcEditor.test.js @@ -2,6 +2,7 @@ import React from 'react'; import faker from 'faker'; import { useLocation } from 'react-router'; +import { createMemoryHistory } from 'history'; import { render, @@ -25,9 +26,12 @@ import Harness from '../../test/jest/helpers/harness'; import buildStripes from '../../test/jest/__mock__/stripesCore.mock'; import { bibLeader } from '../../test/jest/fixtures/leaders'; +const mockHistory = createMemoryHistory(); + jest.mock('react-router', () => ({ ...jest.requireActual('react-router'), useLocation: jest.fn(), + withRouter: Component => props => , })); jest.mock('../queries', () => ({ diff --git a/src/QuickMarcEditor/QuickMarcEditorContainer.test.js b/src/QuickMarcEditor/QuickMarcEditorContainer.test.js index bf42fbc7..ebc6f46c 100644 --- a/src/QuickMarcEditor/QuickMarcEditorContainer.test.js +++ b/src/QuickMarcEditor/QuickMarcEditorContainer.test.js @@ -282,16 +282,16 @@ describe('Given Quick Marc Editor Container', () => { }); }); - recordLengthField = screen.getByRole('textbox', { name: 'ui-quick-marc.record.fixedField.Record length' }); - statusField = screen.getByRole('combobox', { name: 'ui-quick-marc.record.fixedField.tip.Status' }); - typeField = screen.getByRole('combobox', { name: 'ui-quick-marc.record.fixedField.tip.Type' }); - blvlField = screen.getByRole('combobox', { name: 'ui-quick-marc.record.fixedField.tip.BLvl' }); - ctrlField = screen.getByRole('combobox', { name: 'ui-quick-marc.record.fixedField.tip.Ctrl' }); - positions9to16Field = screen.getByRole('textbox', { name: 'ui-quick-marc.record.fixedField.9-16 positions' }); - elvlField = screen.getByRole('textbox', { name: 'ui-quick-marc.record.fixedField.tip.ELvl' }); - descField = screen.getByRole('combobox', { name: 'ui-quick-marc.record.fixedField.tip.Desc' }); - multiLvlField = screen.getByRole('combobox', { name: 'ui-quick-marc.record.fixedField.tip.MultiLvl' }); - positions20to23Field = screen.getByRole('textbox', { name: 'ui-quick-marc.record.fixedField.20-23 positions' }); + recordLengthField = screen.getByRole('textbox', { name: /ui-quick-marc.record.fixedField.Record length/ }); + statusField = screen.getByRole('combobox', { name: /ui-quick-marc.record.fixedField.tip.Status/ }); + typeField = screen.getByRole('combobox', { name: /ui-quick-marc.record.fixedField.tip.Type/ }); + blvlField = screen.getByRole('combobox', { name: /ui-quick-marc.record.fixedField.tip.BLvl/ }); + ctrlField = screen.getByRole('combobox', { name: /ui-quick-marc.record.fixedField.tip.Ctrl/ }); + positions9to16Field = screen.getByRole('textbox', { name: /ui-quick-marc.record.fixedField.9-16 positions/ }); + elvlField = screen.getByRole('textbox', { name: /ui-quick-marc.record.fixedField.tip.ELvl/ }); + descField = screen.getByRole('combobox', { name: /ui-quick-marc.record.fixedField.tip.Desc/ }); + multiLvlField = screen.getByRole('combobox', { name: /ui-quick-marc.record.fixedField.tip.MultiLvl/ }); + positions20to23Field = screen.getByRole('textbox', { name: /ui-quick-marc.record.fixedField.20-23 positions/ }); }); it('should display correct default values', () => { @@ -408,13 +408,13 @@ describe('Given Quick Marc Editor Container', () => { }); }); - recordLengthField = screen.getByRole('textbox', { name: 'ui-quick-marc.record.fixedField.Record length' }); - statusField = screen.getByRole('combobox', { name: 'ui-quick-marc.record.fixedField.tip.Status' }); - typeField = screen.getByRole('combobox', { name: 'ui-quick-marc.record.fixedField.tip.Type' }); - positions7to16Field = screen.getByRole('textbox', { name: 'ui-quick-marc.record.fixedField.7-16 positions' }); - elvlField = screen.getByRole('combobox', { name: 'ui-quick-marc.record.fixedField.tip.ELvl' }); - punctField = screen.getByRole('combobox', { name: 'ui-quick-marc.record.fixedField.tip.Punct' }); - positions19to23Field = screen.getByRole('textbox', { name: 'ui-quick-marc.record.fixedField.19-23 positions' }); + recordLengthField = screen.getByRole('textbox', { name: /ui-quick-marc.record.fixedField.Record length/ }); + statusField = screen.getByRole('combobox', { name: /ui-quick-marc.record.fixedField.tip.Status/ }); + typeField = screen.getByRole('combobox', { name: /ui-quick-marc.record.fixedField.tip.Type/ }); + positions7to16Field = screen.getByRole('textbox', { name: /ui-quick-marc.record.fixedField.7-16 positions/ }); + elvlField = screen.getByRole('combobox', { name: /ui-quick-marc.record.fixedField.tip.ELvl/ }); + punctField = screen.getByRole('combobox', { name: /ui-quick-marc.record.fixedField.tip.Punct/ }); + positions19to23Field = screen.getByRole('textbox', { name: /ui-quick-marc.record.fixedField.19-23 positions/ }); }); it('should display correct default values', () => { @@ -492,13 +492,13 @@ describe('Given Quick Marc Editor Container', () => { }); }); - recordLengthField = screen.getByRole('textbox', { name: 'ui-quick-marc.record.fixedField.Record length' }); - statusField = screen.getByRole('combobox', { name: 'ui-quick-marc.record.fixedField.tip.Status' }); - typeField = screen.getByRole('combobox', { name: 'ui-quick-marc.record.fixedField.tip.Type' }); - positions7to16Field = screen.getByRole('textbox', { name: 'ui-quick-marc.record.fixedField.7-16 positions' }); - elvlField = screen.getByRole('combobox', { name: 'ui-quick-marc.record.fixedField.tip.ELvl' }); - itemField = screen.getByRole('combobox', { name: 'ui-quick-marc.record.fixedField.tip.Item' }); - positions19to23Field = screen.getByRole('textbox', { name: 'ui-quick-marc.record.fixedField.19-23 positions' }); + recordLengthField = screen.getByRole('textbox', { name: /ui-quick-marc.record.fixedField.Record length/ }); + statusField = screen.getByRole('combobox', { name: /ui-quick-marc.record.fixedField.tip.Status/ }); + typeField = screen.getByRole('combobox', { name: /ui-quick-marc.record.fixedField.tip.Type/ }); + positions7to16Field = screen.getByRole('textbox', { name: /ui-quick-marc.record.fixedField.7-16 positions/ }); + elvlField = screen.getByRole('combobox', { name: /ui-quick-marc.record.fixedField.tip.ELvl/ }); + itemField = screen.getByRole('combobox', { name: /ui-quick-marc.record.fixedField.tip.Item/ }); + positions19to23Field = screen.getByRole('textbox', { name: /ui-quick-marc.record.fixedField.19-23 positions/ }); }); it('should display correct default values', async () => { diff --git a/src/queries/useUserTenantPermissions/useUserTenantPermissions.js b/src/queries/useUserTenantPermissions/useUserTenantPermissions.js index 8bdbf31c..389351ed 100644 --- a/src/queries/useUserTenantPermissions/useUserTenantPermissions.js +++ b/src/queries/useUserTenantPermissions/useUserTenantPermissions.js @@ -1,3 +1,4 @@ +import { useMemo } from 'react'; import { useQuery } from 'react-query'; import { @@ -48,10 +49,26 @@ const useUserTenantPermissions = ( }, ); + const tenantPermissions = data.permissionNames || INITIAL_DATA; + + const flattenTenantPermissions = useMemo(() => { + const permSet = new Set(); + + tenantPermissions.forEach(perm => { + permSet.add(perm.permissionName); + + perm.subPermissions?.forEach(subPermission => { + permSet.add(subPermission); + }); + }); + + return permSet; + }, [tenantPermissions]); + return ({ isFetching, isLoading, - userPermissions: data.permissionNames || INITIAL_DATA, + userPermissions: flattenTenantPermissions, totalRecords: data.totalRecords, }); }; diff --git a/src/queries/useUserTenantPermissions/useUserTenantPermissions.test.js b/src/queries/useUserTenantPermissions/useUserTenantPermissions.test.js index 53004a4f..a0427720 100644 --- a/src/queries/useUserTenantPermissions/useUserTenantPermissions.test.js +++ b/src/queries/useUserTenantPermissions/useUserTenantPermissions.test.js @@ -18,7 +18,16 @@ const wrapper = ({ children }) => ( ); const response = { - permissionNames: [], + permissionNames: [ + { + permissionName: 'permissionName1', + subPermissions: ['subPermissions1', 'subPermissions2'], + }, + { + permissionName: 'permissionName2', + subPermissions: ['subPermissions1', 'subPermissions3'], + }, + ], totalRecords: 0, }; @@ -54,4 +63,22 @@ describe('useUserTenantPermissions', () => { expect(setHeaderMock).toHaveBeenCalledWith('X-Okapi-Tenant', options.tenantId); expect(getMock).toHaveBeenCalledWith(`perms/users/${options.userId}/permissions`, expect.objectContaining({})); }); + + it('should consider sub permissions without duplicates', async () => { + const options = { + userId: 'userId', + tenantId: 'tenantId', + }; + const { result } = renderHook(() => useUserTenantPermissions(options), { wrapper }); + + await act(async () => !result.current.isLoading); + + expect([...result.current.userPermissions]).toEqual([ + 'permissionName1', + 'subPermissions1', + 'subPermissions2', + 'permissionName2', + 'subPermissions3', + ]); + }); });