Skip to content

Commit

Permalink
Merge branch 'master' into UIIN-2831
Browse files Browse the repository at this point in the history
  • Loading branch information
artem-blazhko committed May 12, 2024
2 parents df01db5 + e4fcd61 commit 47a0fe3
Show file tree
Hide file tree
Showing 62 changed files with 2,025 additions and 509 deletions.
31 changes: 28 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,41 @@
## [11.1.0] (IN PROGRESS)

* Remove unused code related to auto-open record detail view. Refs UIIN-2819.
* Replace `all` with the `=` operator to get correct results when using the `All` search option. Refs UIIN-2816.
* Keyboard shortcuts modal: Add quickMARC shortcuts to modal. Refs UIIN-2795.
* Create new settings for classification type sorting. Refs UIIN-2775.
* Add "Display to public" column to receiving history on Holdings. Refs UIIN-2826.
* Add new browse options for Instance classification numbers. Refs UIIN-2624.
* Add new Instance search option `Classification, normalized` for the `Instance` toggle and advanced search modal. Refs UIIN-2801.
* Import `useUserTenantPermissions`, `getUserTenantsPermissions` from `@folio/stripes/core`. Refs UIIN-2837.
* ECS Member tenant - add `Shared` and `Held by` facets for the `Classification` browse. Refs UIIN-2813.
* Jest/RTL: Cover CalloutRenderer component with unit tests. Refs UIIN-2665.
* Jest/RTL: Cover ConnectedTitle component with unit tests. Refs UIIN-2666.
* Jest/RTL: Cover InstancePlugin component with unit tests. Refs UIIN-2668.
* Jest/RTL: Cover ImportRecord component with unit test. Refs UIIN-2667.
* Jest/RTL: Cover MoveHoldingContext component with unit tests. Refs UIIN-2664.
* Use consolidated locations endpoint to fetch all locations when in central tenant context. Refs UIIN-2811.
* Change label of eye-readable call number search option in holdings/items. Refs UIIN-2797.
* Add callout noting user's active affiliation when it changes after selecting holding or item. Refs UIIN-2831, UIIN-2872.

## [11.0.2] (IN PROGRESS)
## [11.0.4](https://github.com/folio-org/ui-inventory/tree/v11.0.4) (2024-04-30)
[Full Changelog](https://github.com/folio-org/ui-inventory/compare/v11.0.3...v11.0.4)

* Replace `all` with the `=` operator to get correct results when using the `All` search option. Refs UIIN-2816.

## [11.0.3](https://github.com/folio-org/ui-inventory/tree/v11.0.3) (2024-04-26)
[Full Changelog](https://github.com/folio-org/ui-inventory/compare/v11.0.2...v11.0.3)

* Fetch facets with the same query as `Contributor` records when the search is done by selecting browse result. Refs UIIN-2859.
* Change the `Effective location` call numbers facet query to not see locations assigned to items with an empty `Effective call number` field. Refs UIIN-2871.
* Do not remove field from the form when its value is an empty string. Fixes UIIN-2787.
* Update Permission name for Inventory: Set records for deletion and staff suppress. Refs UIIN-2855.

## [11.0.2](https://github.com/folio-org/ui-inventory/tree/v11.0.2) (2024-04-19)
[Full Changelog](https://github.com/folio-org/ui-inventory/compare/v11.0.1...v11.0.2)

* ECS: Shared instance cannot be edited from member tenant, even with permissions in both Central and member tenants. Fixes UIIN-2845.
* Restricted status displays as Order Closed. Fixes UIIN-2821.
* Update Permission name for Inventory: Set records for deletion and staff suppress. Refs UIIN-2855.
* Add a new "Inventory: Create and download In transit items report" permission. Fixes UIIN-2776.
* Include mod-search permissions to "Inventory: Module is enabled" UI permission. Refs UIIN-2860.

## [11.0.1](https://github.com/folio-org/ui-inventory/tree/v11.0.1) (2024-04-11)
Expand Down Expand Up @@ -67,6 +87,11 @@
* Increase holdings limit to 5000. Fixes UIIN-2785.
* User with "Inventory: All permissions" permission only should not be seeing the "Staff suppress" facet. Fixes UIIN-2807.

## [10.0.14](https://github.com/folio-org/ui-inventory/tree/v10.0.14) (2024-04-25)
[Full Changelog](https://github.com/folio-org/ui-inventory/compare/v10.0.13...v10.0.14)

* Include mod-search permissions to "Inventory: Module is enabled" UI permission. Refs UIIN-2860.

## [10.0.13](https://github.com/folio-org/ui-inventory/tree/v10.0.13) (2024-04-18)
[Full Changelog](https://github.com/folio-org/ui-inventory/compare/v10.0.12...v10.0.13)

Expand Down
25 changes: 13 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@folio/inventory",
"version": "11.0.1",
"version": "11.0.4",
"description": "Inventory manager",
"repository": "folio-org/ui-inventory",
"publishConfig": {
Expand Down Expand Up @@ -83,7 +83,7 @@
"material-types": "2.0",
"modes-of-issuance": "1.0",
"nature-of-content-terms": "1.0",
"search": "0.7 1.0",
"search": "0.7 1.0 1.3",
"source-storage-records": "3.0",
"statistical-code-types": "1.0",
"statistical-codes": "1.0",
Expand Down Expand Up @@ -569,7 +569,8 @@
"browse.subjects.instances.collection.get",
"browse.classification-numbers.instances.collection.get",
"perms.users.get",
"inventory-storage.bound-with-parts.collection.get"
"inventory-storage.bound-with-parts.collection.get",
"consortium-search.locations.collection.get"
],
"visible": true
},
Expand Down Expand Up @@ -889,13 +890,13 @@
"@babel/preset-react": "^7.9.0",
"@folio/eslint-config-stripes": "^7.0.0",
"@folio/jest-config-stripes": "^2.0.0",
"@folio/stripes": "^9.0.0",
"@folio/stripes-cli": "^3.0.0",
"@folio/stripes-components": "^12.0.0",
"@folio/stripes-connect": "^9.0.0",
"@folio/stripes-core": "^10.0.0",
"@folio/stripes-marc-components": "^1.0.0",
"@folio/stripes-smart-components": "^9.0.0",
"@folio/stripes": "^9.1.2",
"@folio/stripes-cli": "^3.1.0",
"@folio/stripes-components": "^12.1.2",
"@folio/stripes-connect": "^9.1.0",
"@folio/stripes-core": "^10.1.1",
"@folio/stripes-marc-components": "^1.0.1",
"@folio/stripes-smart-components": "^9.1.1",
"@folio/stripes-testing": "^4.6.0",
"@folio/stripes-util": "^6.0.0",
"@formatjs/cli": "^6.1.3",
Expand Down Expand Up @@ -936,8 +937,8 @@
"use-session-storage-state": "^18.2.0"
},
"peerDependencies": {
"@folio/stripes": "^9.0.0",
"@folio/stripes-marc-components": "^1.0.0",
"@folio/stripes": "^9.1.2",
"@folio/stripes-marc-components": "^1.0.1",
"react": "^18.2.0",
"react-intl": "^6.4.4",
"react-query": "^3.6.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ describe('render SubInstanceList', () => {
it('NoValue should display when no title is present', () => {
useLoadSubInstances.mockReturnValue([{}]);
const { getAllByText } = renderSubInstanceList(defaultProps);
expect(getAllByText(/No value set/i).length).toBe(4);
expect(getAllByText(/No value set/i).length).toBe(6);
});
it('No link to be present when tittleKey is empty', () => {
useLoadSubInstances.mockReturnValue(mockuseLoadSubInstancesVaues);
Expand All @@ -87,6 +87,6 @@ describe('render SubInstanceList', () => {
useLoadSubInstances.mockReturnValue(mockuseLoadSubInstancesVaues);
const { container, getByRole } = renderSubInstanceList(defaultProps);
userEvent.click(getByRole('button', { name: 'Next' }));
expect(container.getElementsByClassName('sr-only').length).toBe(1);
expect(container.getElementsByClassName('sr-only').length).toBe(3);
});
});
225 changes: 225 additions & 0 deletions src/Instance/MoveHoldingContext/MoveHoldingContext.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import { keyBy } from 'lodash';

import { screen, waitFor, configure, fireEvent } from '@folio/jest-config-stripes/testing-library/react';
import { within } from '@folio/jest-config-stripes/testing-library/dom';

import { DataContext } from '../../contexts';
import { useHoldings, useInstanceHoldingsQuery } from '../../providers';
import { useLocationsQuery } from '../../hooks';
import { holdingsById, identifierTypes, instanceRelationshipTypes } from '../../../test/fixtures';
import renderWithIntl from '../../../test/jest/helpers/renderWithIntl';
import translationsProperties from '../../../test/jest/helpers/translationsProperties';
import MoveHoldingContext from './MoveHoldingContext';
import { leftInstance, rightInstance } from '../../../test/fixtures/movingInstances';
import { locationsById } from '../../../test/fixtures/locationsById';
import { InstanceMovementDetailsContainer } from '../InstanceMovement';

configure({ testIdAttribute: 'id' });

jest.mock('../../providers', () => ({
...jest.requireActual('../../providers'),
useHoldings: jest.fn(),
useInstanceHoldingsQuery: jest.fn(),
}));

jest.mock('../../hooks', () => ({
...jest.requireActual('../../hooks'),
useHoldingItemsQuery: jest.fn().mockImplementation(() => ({
totalRecords: 1,
isLoading: false,
isFetching: false,
})),
useLocationsQuery: jest.fn()
}));

useHoldings.mockImplementation(() => ({
holdingsById,
}));

useInstanceHoldingsQuery.mockImplementation((id) => ({
holdingsRecords: Object.values(holdingsById).filter(holding => holding.instanceId === id),
isLoading: false,
}));

useLocationsQuery.mockImplementation(() => ({
data: Object.values(locationsById)
}));

const onClose = jest.fn();
const moveHoldings = jest.fn().mockImplementation(() => Promise.resolve());

const renderMoveHoldingContext = () => renderWithIntl(
<Router>
<DataContext.Provider value={{
contributorTypes: [],
identifierTypes,
identifierTypesById: keyBy(identifierTypes, 'id'),
identifierTypesByName: keyBy(identifierTypes, 'name'),
instanceRelationshipTypes,
instanceRelationshipTypesById: keyBy(identifierTypes, 'id'),
instanceFormats: [],
modesOfIssuance: [],
natureOfContentTerms: [],
tagsRecords: [],
locationsById,
}}
>
<MoveHoldingContext
leftInstance={leftInstance}
rightInstance={rightInstance}
moveHoldings={moveHoldings}
>
<InstanceMovementDetailsContainer
instance={leftInstance}
onClose={onClose}
data-test-movement-from-instance-details
id="movement-from-instance-details"
/>

<InstanceMovementDetailsContainer
instance={rightInstance}
onClose={onClose}
data-test-movement-to-instance-details
id="movement-to-instance-details"
/>
</MoveHoldingContext>
</DataContext.Provider>
</Router>,
translationsProperties
);


describe('MoveHoldingContext', () => {
it('should render correct holdings accordion for left pane', () => {
const { getByTestId } = renderMoveHoldingContext();

const leftPane = getByTestId('movement-from-instance-details');
expect(within(leftPane).getByText(/Holdings: Main Library/)).toBeInTheDocument();
expect(within(leftPane).getByText(/Holdings: Annex/)).toBeInTheDocument();
});

it('should render "Drop holding" area in right pane', () => {
const { getByTestId } = renderMoveHoldingContext();

const leftPane = getByTestId('movement-to-instance-details');
expect(within(leftPane).getByText(/Drop holding/)).toBeInTheDocument();
});

it('"Select holdings" checkbox functionality works as expected', () => {
const { getByTestId } = renderMoveHoldingContext();

const selectHoldingCheckbox = getByTestId('select-holding-c4a15834-0184-4a6f-9c0c-0ca5bad8286d');

fireEvent.click(selectHoldingCheckbox);
expect(selectHoldingCheckbox).toBeChecked();

fireEvent.click(selectHoldingCheckbox);
expect(selectHoldingCheckbox).not.toBeChecked();
});

it('should render confirmation modal with initial state in background', () => {
const { getByText } = renderMoveHoldingContext();

expect(getByText(/ConfirmationModal/)).toBeInTheDocument();
expect(getByText(/0 items will be moved to/)).toBeInTheDocument();
});

it('should render correct list of holdings for Annex with checkbox', async () => {
const { getByTestId } = renderMoveHoldingContext();

const annexSection = getByTestId('c4a15834-0184-4a6f-9c0c-0ca5bad8286d');
const annexHoldingsAccordionBtn = getByTestId('accordion-toggle-button-c4a15834-0184-4a6f-9c0c-0ca5bad8286d');

fireEvent.click(annexHoldingsAccordionBtn);

let grid;
let rows;

await waitFor(() => {
grid = within(annexSection).getByRole('grid');
rows = within(grid).getAllByRole('row');

expect(grid).toBeVisible();
expect(rows).toHaveLength(3);

// render correct table headers
const titles = [
'Item: barcode',
'Status',
'Copy number',
'Loan type',
'Effective location',
'Enumeration',
'Chronology',
'Volume',
'Year, caption',
'Material type'
];

titles.forEach(title => {
expect(within(rows[0]).getByText(title)).toBeInTheDocument();
});

// second row should have 'Inactive' cell
expect(within(rows[1]).getByText('Inactive')).toBeInTheDocument();

// should render 'End of list' indicator
expect(within(grid).getByText('End of list')).toBeInTheDocument();
});

fireEvent.click(within(rows[1]).getByRole('checkbox'));

rows.forEach(row => {
expect(within(row).getByRole('checkbox')).toBeChecked();
});

fireEvent.click(within(rows[1]).getByRole('checkbox'));

rows.forEach(row => {
expect(within(row).getByRole('checkbox')).not.toBeChecked();
});
});

describe('when "Move" button is clicked', () => {
const clickMoveFlow = ({ getByTestId, getByText }) => {
const holdingsAnnex = getByTestId('item-row-c4a15834-0184-4a6f-9c0c-0ca5bad8286d');

const moveToBtn = within(holdingsAnnex).getByText('Move to');

fireEvent.click(moveToBtn);

const dropdownMoveBtn = within(holdingsAnnex).getByText('A journey through Europe Bildtontraeger high-speed lines European Commission, Directorate-General for Mobility and Transport');
expect(dropdownMoveBtn).toBeInTheDocument();

fireEvent.click(dropdownMoveBtn);

expect(getByText('1 holding will be moved to')).toBeInTheDocument();
};

it('should move selected holdings if "Confirm button" is clicked', () => {
const { getByText, getByTestId } = renderMoveHoldingContext();

clickMoveFlow({ getByText, getByTestId });

const confirmBtn = screen.getByRole('button', { name: /confirm/ });

fireEvent.click(confirmBtn);

expect(screen.queryByText('Loading')).toBeInTheDocument();
});

it('should close modal and stop moving when "Cancel" is clicked', () => {
const { getByText, getByTestId } = renderMoveHoldingContext();

clickMoveFlow({ getByText, getByTestId });

const cancelBtn = screen.getByRole('button', { name: /cancel/ });

fireEvent.click(cancelBtn);

expect(screen.queryByText('Loading')).not.toBeInTheDocument();
});
});
});
10 changes: 9 additions & 1 deletion src/common/hooks/useFacets.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ import { useFacetSettings } from '../../stores/facetsStore';
// - when the user places the cursor in a facet's input field, all options for it must be fetched;
// - when multiple facets are open and the user enters a value in the search box, options must be fetched for all open facets.
// - when multiple facets are open and the user selects an option of any facet, options must be fetched for all open facets.
// - when a facet option is selected, and then another is selected from another facet, the first selected facet option may
// become with count 0, and it should still be visible and moved to the bottom of the provided options. This is done in `getFacetOptions`.
// - the "Contributor" search utilizes distinct queries for the "Search" lookup and the "Browse" search. When a user
// selects a contributor record from the "Browse" search, they are redirected to the "Search" lookup. This redirection
// request uses one specific query. If the user then clicks the search button again, without making any changes,
// a different query is generated because the `selectedBrowseResult` parameter is removed. Therefore, even if the only
// change made is to the `selectedBrowseResult`, all open facets need to be fetched.

const useFacets = (
segmentAccordions,
Expand All @@ -24,6 +31,7 @@ const useFacets = (
query,
qindex,
filters = '',
selectedBrowseResult,
},
onFetchFacets,
parentResources: { facets },
Expand Down Expand Up @@ -242,7 +250,7 @@ const useFacets = (
handleFetchFacets();
prevUrl.current.all = location.search;
}
}, [query]);
}, [query, selectedBrowseResult]);

return [
accordions,
Expand Down

0 comments on commit 47a0fe3

Please sign in to comment.