Skip to content

Commit

Permalink
UIIN-2784: Set central tenant id in the request when Member tenant de…
Browse files Browse the repository at this point in the history
…letes a shared record (#2416)

* UIIN-2784: Set central tenant id in the request when Member tenant deletes a shared record

* UIIN-2784: Set central tenant id in the request when Member tenant deletes a shared record

* Update utils.test.js

* UIIN-2784: Throw error in catch block

* UIIN-2784: Remove try catch

* UIIN-2784: Throw exception if response is failed

* UIIN-2784: Fix tests

(cherry picked from commit 0ca01a0)
  • Loading branch information
OleksandrHladchenko1 authored and mariia-aloshyna committed Apr 11, 2024
1 parent 2a16568 commit a3ba268
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 17 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
## [10.0.1] (IN PROGRESS)

* Keep query and results list when switching Browse options. Refs UIIN-2802.
* Set central tenant id in the request when Member tenant deletes a shared record. Fixes UIIN-2784.

## [11.0.0](https://github.com/folio-org/ui-inventory/tree/v11.0.0) (2024-03-21)
[Full Changelog](https://github.com/folio-org/ui-inventory/compare/v10.0.11...v11.0.0)
Expand Down
20 changes: 7 additions & 13 deletions src/ViewInstance.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
isInstanceShadowCopy,
isMARCSource,
getLinkedAuthorityIds,
setRecordForDeletion,
} from './utils';
import {
CONSORTIUM_PREFIX,
Expand Down Expand Up @@ -169,14 +170,6 @@ class ViewInstance extends React.Component {
accumulate: true,
throwErrors: false,
},
setForDeletion: {
type: 'okapi',
throwErrors: false,
accumulate: true,
DELETE: {
path: 'inventory/instances/:{id}/mark-deleted',
},
},
authorities: {
type: 'okapi',
path: 'authority-storage/authorities',
Expand Down Expand Up @@ -587,15 +580,19 @@ class ViewInstance extends React.Component {

handleSetForDeletion = () => {
const {
mutator,
okapi,
isShared,
centralTenantId,
refetchInstance,
selectedInstance: {
title: instanceTitle,
id,
source,
},
} = this.props;
const tenantId = isShared && !isInstanceShadowCopy(source) ? centralTenantId : okapi.tenant;

mutator.setForDeletion.DELETE(id)
setRecordForDeletion(okapi, id, tenantId)
.then(async () => {
this.handleCloseSetForDeletionModal();

Expand Down Expand Up @@ -1207,9 +1204,6 @@ ViewInstance.propTypes = {
POST: PropTypes.func.isRequired,
GET: PropTypes.func.isRequired,
}).isRequired,
setForDeletion: PropTypes.shape({
DELETE: PropTypes.func.isRequired,
}).isRequired,
authorities: PropTypes.shape({
GET: PropTypes.func.isRequired,
}).isRequired,
Expand Down
15 changes: 12 additions & 3 deletions src/ViewInstance.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ const spyOncollapseAllSections = jest.spyOn(require('@folio/stripes/components')
const spyOnexpandAllSections = jest.spyOn(require('@folio/stripes/components'), 'expandAllSections');

const spyOnGetUserTenantsPermissions = jest.spyOn(utils, 'getUserTenantsPermissions');
const spyOnSetRecordForDeletion = jest.spyOn(utils, 'setRecordForDeletion');

const location = {
pathname: '/testPathName',
Expand Down Expand Up @@ -1117,20 +1118,28 @@ describe('ViewInstance', () => {
fireEvent.click(screen.getByText('Set record for deletion'));
fireEvent.click(screen.getByText('Confirm'));

expect(defaultProp.mutator.setForDeletion.DELETE).toHaveBeenCalledWith(defaultProp.selectedInstance.id);
expect(spyOnSetRecordForDeletion).toHaveBeenCalledWith(
{ tenant: defaultProp.okapi.tenant },
defaultProp.selectedInstance.id,
defaultProp.okapi.tenant,
);
expect(screen.queryByText(`${defaultProp.selectedInstance.title} has been set for deletion`)).toBeDefined();
});

describe('when there\'s an error', () => {
it('should throw an error with id of the instance and show error message', async () => {
defaultProp.mutator.setForDeletion.DELETE.mockRejectedValueOnce();
global.fetch.mockRejectedValueOnce({ ok: false });

renderViewInstance();

fireEvent.click(screen.getByText('Set record for deletion'));
fireEvent.click(screen.getByText('Confirm'));

expect(defaultProp.mutator.setForDeletion.DELETE).toHaveBeenCalledWith(defaultProp.selectedInstance.id);
expect(spyOnSetRecordForDeletion).toHaveBeenCalledWith(
{ tenant: defaultProp.okapi.tenant },
defaultProp.selectedInstance.id,
defaultProp.okapi.tenant,
);
expect(screen.queryByText(`${defaultProp.selectedInstance.title} was not set for deletion`)).toBeDefined();
});
});
Expand Down
24 changes: 24 additions & 0 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -886,3 +886,27 @@ export const clearStorage = () => {
removeItem(`${namespace}.${segment}.lastOpenRecord`);
});
};

export const setRecordForDeletion = async (okapi, id, tenantId) => {
const {
url,
token,
} = okapi;
const path = `${url}/inventory/instances/${id}/mark-deleted`;

const response = await fetch(path, {
method: 'DELETE',
headers: {
[OKAPI_TENANT_HEADER]: tenantId,
[CONTENT_TYPE_HEADER]: 'application/json',
...(token && { [OKAPI_TOKEN_HEADER]: token }),
},
credentials: 'include',
});

if (!response.ok) {
throw response;
}

return response;
};
74 changes: 73 additions & 1 deletion src/utils.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,14 @@ import {
validateAlphaNumericField,
getQueryTemplate,
switchAffiliation,
setRecordForDeletion,
} from './utils';
import { browseModeOptions } from './constants';
import {
CONTENT_TYPE_HEADER,
OKAPI_TENANT_HEADER,
OKAPI_TOKEN_HEADER,
browseModeOptions,
} from './constants';

describe('validateRequiredField', () => {
const expectedResult = <FormattedMessage id="ui-inventory.hridHandling.validation.enterValue" />;
Expand Down Expand Up @@ -179,3 +185,69 @@ describe('switchAffiliation', () => {
});
});
});

describe('setRecordForDeletion', () => {
afterEach(() => {
global.fetch.mockClear();
});

afterAll(() => {
delete global.fetch;
});

const instanceId = 'testInstanceId';
const tenantId = 'testTenantId';
const okapi = {
token: 'token',
url: 'url/test',
};

describe('when the request was fulfilled successfuly', () => {
it('should return the appropriate response', () => {
global.fetch = jest.fn().mockReturnValue({ ok: true });

setRecordForDeletion(okapi, instanceId, tenantId);

expect(global.fetch).toHaveBeenCalledWith(
`${okapi.url}/inventory/instances/${instanceId}/mark-deleted`,
{
credentials: 'include',
headers: expect.objectContaining({
[OKAPI_TENANT_HEADER]: tenantId,
[OKAPI_TOKEN_HEADER]: okapi.token,
[CONTENT_TYPE_HEADER]: 'application/json',
}),
method: 'DELETE',
},
);

expect(global.fetch.mock.results[0].value.ok).toBe(true);
});
});

describe('when the request was fulfilled with an error', () => {
it('should return the appropriate response', async () => {
global.fetch = jest.fn().mockReturnValue({ ok: false });

try {
await setRecordForDeletion(okapi, instanceId, tenantId);
} catch (error) {
expect(error).toBeDefined();
expect(error.ok).toBe(false);

expect(global.fetch).toHaveBeenCalledWith(
`${okapi.url}/inventory/instances/${instanceId}/mark-deleted`,
{
credentials: 'include',
headers: expect.objectContaining({
[OKAPI_TENANT_HEADER]: tenantId,
[OKAPI_TOKEN_HEADER]: okapi.token,
[CONTENT_TYPE_HEADER]: 'application/json',
}),
method: 'DELETE',
},
);
}
});
});
});

0 comments on commit a3ba268

Please sign in to comment.