Skip to content

Commit

Permalink
Merge branch 'UISACQCOMP-236' of https://github.com/folio-org/stripes…
Browse files Browse the repository at this point in the history
…-acq-components into UISACQCOMP-236
  • Loading branch information
usavkov-epam committed Dec 18, 2024
2 parents c280f5e + f2578fe commit ca5c5db
Show file tree
Hide file tree
Showing 12 changed files with 388 additions and 6 deletions.
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @folio-org/acquisitions-ui
13 changes: 13 additions & 0 deletions PULL_REQUEST_TEMPLATE.md → .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,19 @@
[ ] Use GitHub checklists. When solved, check the box and explain the answer.
-->

## Screenshots
<!-- OPTIONAL
One picture is literally worth a thousand words. When the feature is
an interaction, an animated GIF or video is best. Most of the time it helps to
include "before" and "after" screenshots to quickly demonstrate the
value of the feature.
Here are some great tools to help you record gifs:
Windows: https://getsharex.com/
Mac: https://gifox.io/
-->

<!-- OPTIONAL
## Learning
Help out not only your reviewer, but also your fellow developer!
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
/* Developed collaboratively using AI (GitHub Copilot) */

import {
render,
screen,
} from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';

import { render, screen } from '@testing-library/react';
import stripesFinalForm from '@folio/stripes/final-form';

import { FieldClaimingDate } from './FieldClaimingDate';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/* Developed collaboratively using AI (GitHub Copilot) */

import {
render,
screen,
} from '@testing-library/react';
import userEvent from '@testing-library/user-event';

import { DelayClaimActionMenuItem } from './DelayClaimActionMenuItem';

const defaultProps = {
onClick: jest.fn(),
};

const renderComponent = (props = {}) => render(
<DelayClaimActionMenuItem
{...defaultProps}
{...props}
/>,
);

describe('DelayClaimActionMenuItem', () => {
afterEach(() => {
jest.clearAllMocks();
});

it('should call onClick when button is clicked', async () => {
renderComponent();

await userEvent.click(screen.getByTestId('delay-claim-button'));

expect(defaultProps.onClick).toHaveBeenCalledTimes(1);
});

it('should be disabled when disabled prop is true', () => {
renderComponent({ disabled: true });

expect(screen.getByTestId('delay-claim-button')).toBeDisabled();
});

it('should not call onClick when button is disabled and clicked', async () => {
renderComponent({ disabled: true });

await userEvent.click(screen.getByTestId('delay-claim-button'));

expect(defaultProps.onClick).not.toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/* Developed collaboratively using AI (GitHub Copilot) */

import {
render,
screen,
} from '@testing-library/react';
import userEvent from '@testing-library/user-event';

import { MarkUnreceivableActionMenuItem } from './MarkUnreceivableActionMenuItem';

const defaultProps = {
onClick: jest.fn(),
disabled: false,
};

const renderComponent = (props = {}) => render(
<MarkUnreceivableActionMenuItem
{...defaultProps}
{...props}
/>,
);

describe('MarkUnreceivableActionMenuItem', () => {
afterEach(() => {
jest.clearAllMocks();
});

it('should render the button', () => {
renderComponent();

expect(screen.getByTestId('unreceivable-button')).toBeInTheDocument();
});

it('should call onClick when button is clicked', async () => {
renderComponent();

await userEvent.click(screen.getByTestId('unreceivable-button'));

expect(defaultProps.onClick).toHaveBeenCalledTimes(1);
});

it('should disable the button when disabled prop is true', () => {
renderComponent({ disabled: true });

expect(screen.getByTestId('unreceivable-button')).toBeDisabled();
});

it('should enable the button when disabled prop is false', () => {
renderComponent({ disabled: false });

expect(screen.getByTestId('unreceivable-button')).toBeEnabled();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/* Developed collaboratively using AI (GitHub Copilot) */

import {
render,
screen,
} from '@testing-library/react';
import userEvent from '@testing-library/user-event';

import { SendClaimActionMenuItem } from './SendClaimActionMenuItem';

const defaultProps = {
onClick: jest.fn(),
};

const renderComponent = (props = {}) => render(
<SendClaimActionMenuItem
{...defaultProps}
{...props}
/>,
);

describe('SendClaimActionMenuItem', () => {
it('should render the button', () => {
renderComponent();

expect(screen.getByTestId('send-claim-button')).toBeInTheDocument();
});

it('should call onClick when button is clicked', async () => {
renderComponent();

await userEvent.click(screen.getByTestId('send-claim-button'));

expect(defaultProps.onClick).toHaveBeenCalled();
});

it('should disable the button when disabled prop is true', () => {
renderComponent({ disabled: true });

expect(screen.getByTestId('send-claim-button')).toBeDisabled();
});

it('should enable the button when disabled prop is false', () => {
renderComponent({ disabled: false });

expect(screen.getByTestId('send-claim-button')).not.toBeDisabled();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/* Developed collaboratively using AI (GitHub Copilot) */

import {
render,
screen,
} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { MemoryRouter } from 'react-router-dom';

import { dayjs } from '@folio/stripes/components';

import DelayClaimsModal from './DelayClaimsModal';

const FORMAT = 'MM/DD/YYYY';
const today = dayjs();

const defaultProps = {
claimsCount: 1,
onSubmit: jest.fn(() => console.log('')),
message: 'Test message',
onCancel: jest.fn(),
open: true,
};

const renderComponent = (props = {}) => render(
<DelayClaimsModal
{...defaultProps}
{...props}
/>,
{ wrapper: MemoryRouter },
);

describe('DelayClaimsModal', () => {
it('should call onCancel when cancel button is clicked', async () => {
renderComponent();

await userEvent.click(screen.getByText('stripes-acq-components.FormFooter.cancel'));

expect(defaultProps.onCancel).toHaveBeenCalled();
});

it('should validate "Delay to" field and call onSubmit when save button is clicked', async () => {
renderComponent();

const saveBtn = screen.getByRole('button', { name: 'stripes-acq-components.FormFooter.save' });

/* Empty input */
await userEvent.click(saveBtn);

expect(screen.getByText('stripes-acq-components.validation.required')).toBeInTheDocument();

/* Invalid date input */
await userEvent.type(screen.getByPlaceholderText(FORMAT), today.format(FORMAT));
await userEvent.click(saveBtn);

expect(screen.getByText('stripes-acq-components.validation.dateAfter')).toBeInTheDocument();

/* Valid date */
await userEvent.clear(screen.getByPlaceholderText(FORMAT));
await userEvent.type(screen.getByPlaceholderText(FORMAT), dayjs().add(5, 'days').format(FORMAT));
await userEvent.click(saveBtn);

expect(defaultProps.onSubmit).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { render, screen } from '@testing-library/react';
import {
render,
screen,
} from '@testing-library/react';
import user from '@testing-library/user-event';
import { MemoryRouter } from 'react-router-dom';

Expand Down Expand Up @@ -32,7 +35,7 @@ describe('SendClaimsModal', () => {
it('should render send claim modal', () => {
renderSendClaimsModal();

expect(screen.getByText('ui-receiving.modal.sendClaim.heading')).toBeInTheDocument();
expect(screen.getByText('stripes-acq-components.claiming.modal.sendClaim.heading')).toBeInTheDocument();
});

it('should validate "Claim expiry date" field', async () => {
Expand All @@ -41,11 +44,13 @@ describe('SendClaimsModal', () => {
const saveBtn = screen.getByRole('button', { name: 'stripes-acq-components.FormFooter.save' });

await user.click(saveBtn);

expect(screen.getByText('stripes-acq-components.validation.required')).toBeInTheDocument();

await user.type(screen.getByPlaceholderText(FORMAT), today.format(FORMAT));
await user.click(saveBtn);
expect(screen.getByText('ui-receiving.validation.dateAfter')).toBeInTheDocument();

expect(screen.getByText('stripes-acq-components.validation.dateAfter')).toBeInTheDocument();
});

it('should submit valid form', async () => {
Expand All @@ -56,8 +61,8 @@ describe('SendClaimsModal', () => {
const externalNote = 'External';

await user.type(screen.getByPlaceholderText(FORMAT), date.format(FORMAT));
await user.type(screen.getByLabelText('ui-receiving.piece.internalNote'), internalNote);
await user.type(screen.getByLabelText('ui-receiving.piece.externalNote'), externalNote);
await user.type(screen.getByLabelText('stripes-acq-components.claiming.modal.sendClaim.field.internalNote'), internalNote);
await user.type(screen.getByLabelText('stripes-acq-components.claiming.modal.sendClaim.field.externalNote'), externalNote);
await user.click(screen.getByRole('button', { name: 'stripes-acq-components.FormFooter.save' }));

expect(defaultProps.onSubmit).toHaveBeenCalledWith(
Expand Down
40 changes: 40 additions & 0 deletions lib/claiming/hooks/useClaimsDelay/useClaimsDelay.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { renderHook } from '@testing-library/react-hooks';

import { PIECE_STATUS } from '../../../constants';
import { usePiecesStatusBatchUpdate } from '../../../hooks';
import { useClaimsDelay } from './useClaimsDelay';

jest.mock('../../../hooks', () => ({
usePiecesStatusBatchUpdate: jest.fn(),
}));

const mockUpdatePiecesStatus = jest.fn(() => Promise.resolve());

describe('useClaimsDelay', () => {
beforeEach(() => {
usePiecesStatusBatchUpdate.mockReturnValue({
isLoading: false,
updatePiecesStatus: mockUpdatePiecesStatus,
});
});

afterEach(() => {
jest.clearAllMocks();
});

it('should call updatePiecesStatus with correct parameters when delayClaims is called', async () => {
const { result } = renderHook(() => useClaimsDelay());
const claimingInterval = 30;
const pieceIds = ['piece1', 'piece2'];

await result.current.delayClaims({ claimingInterval, pieceIds });

expect(mockUpdatePiecesStatus).toHaveBeenCalledWith({
data: {
claimingInterval,
pieceIds,
receivingStatus: PIECE_STATUS.claimDelayed,
},
});
});
});
59 changes: 59 additions & 0 deletions lib/claiming/hooks/useClaimsSend/useClaimsSend.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/* Developed collaboratively using AI (GitHub Copilot) */

import { renderHook } from '@testing-library/react-hooks';
import {
QueryClient,
QueryClientProvider,
} from 'react-query';

import { useOkapiKy } from '@folio/stripes/core';

import { SEND_CLAIMS_API } from '../../../constants';
import { useClaimsSend } from './useClaimsSend';

const queryClient = new QueryClient();
const wrapper = ({ children }) => (
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
);

describe('useClaimsSend', () => {
const kyPostMock = jest.fn();

beforeEach(() => {
useOkapiKy.mockReturnValue({
post: kyPostMock,
});
});

afterEach(() => {
jest.clearAllMocks();
});

it('should call ky.post with correct arguments when sendClaims is called', async () => {
const { result } = renderHook(() => useClaimsSend(), { wrapper });
const data = { claim: 'test' };

kyPostMock.mockReturnValue({
json: jest.fn().mockResolvedValue({}),
});

await result.current.sendClaims({ data });

expect(kyPostMock).toHaveBeenCalledWith(SEND_CLAIMS_API, { json: data });
});

it('should handle errors when sendClaims is called', async () => {
const { result } = renderHook(() => useClaimsSend(), { wrapper });

const data = { claim: 'test' };
const error = new Error('Failed to send claims');

kyPostMock.mockReturnValue({
json: jest.fn().mockRejectedValue(error),
});

await expect(result.current.sendClaims({ data })).rejects.toThrow(error);
});
});
Loading

0 comments on commit ca5c5db

Please sign in to comment.