@openmrs/esm-stock-management-app 1.0.1-pre.543 → 1.0.1-pre.554

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. package/dist/271.js +1 -1
  2. package/dist/{157.js → 281.js} +1 -1
  3. package/dist/281.js.map +1 -0
  4. package/dist/319.js +1 -1
  5. package/dist/460.js +1 -1
  6. package/dist/574.js +1 -1
  7. package/dist/757.js +1 -1
  8. package/dist/788.js +1 -1
  9. package/dist/807.js +1 -1
  10. package/dist/833.js +1 -1
  11. package/dist/main.js +1 -1
  12. package/dist/main.js.map +1 -1
  13. package/dist/openmrs-esm-stock-management-app.js +1 -1
  14. package/dist/openmrs-esm-stock-management-app.js.buildmanifest.json +52 -52
  15. package/dist/routes.json +1 -1
  16. package/package.json +5 -5
  17. package/src/stock-home/stock-home-detail-cards.component.tsx +3 -3
  18. package/src/stock-home/stock-home-metrics.tsx +6 -1
  19. package/src/stock-items/add-stock-item/packaging-units/packaging-units-delete-modal.component.tsx +4 -1
  20. package/src/stock-items/add-stock-item/stock-item-details/stock-item-details.component.tsx +1 -1
  21. package/src/stock-items/add-stock-item/stock-item-units-edit/stock-item-units-edit.component.tsx +20 -15
  22. package/src/stock-operations/add-stock-operation/base-operation-details.component.tsx +4 -4
  23. package/src/stock-operations/add-stock-operation/received-items.component.tsx +6 -3
  24. package/src/stock-operations/add-stock-operation/stock-items-addition.component.tsx +3 -3
  25. package/src/stock-operations/stock-operation-types-selector/stock-operation-types-selector.component.tsx +2 -2
  26. package/src/stock-operations/stock-operations-dialog/stock-operations-dialog.component.tsx +16 -6
  27. package/src/stock-operations/stock-operations-filters.component.tsx +1 -1
  28. package/src/stock-operations/stock-operations-table.component.tsx +82 -122
  29. package/src/stock-operations/stock-operations-table.scss +61 -0
  30. package/src/stock-operations/stock-operations.resource.ts +0 -1
  31. package/src/stock-sources/stock-sources-delete/stock-sources-delete.component.tsx +4 -3
  32. package/src/stock-sources/stock-sources-delete/stock-sources-delete.test.tsx +190 -0
  33. package/translations/am.json +20 -11
  34. package/translations/ar.json +24 -15
  35. package/translations/en.json +20 -11
  36. package/translations/es.json +25 -16
  37. package/translations/fr.json +32 -23
  38. package/translations/he.json +21 -12
  39. package/translations/km.json +22 -13
  40. package/translations/zh.json +20 -11
  41. package/dist/157.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import React, { useCallback, useEffect, useMemo, useState } from "react";
1
+ import React, { useCallback, useMemo, useState } from "react";
2
2
  import { useStockOperationPages } from "./stock-operations-table.resource";
3
3
  import { ResourceRepresentation } from "../core/api/api";
4
4
  import {
@@ -30,10 +30,10 @@ import {
30
30
  DatePicker,
31
31
  TableToolbarMenu,
32
32
  TableToolbarAction,
33
+ InlineLoading,
33
34
  } from "@carbon/react";
34
35
  import { ArrowRight } from "@carbon/react/icons";
35
36
  import { formatDisplayDate } from "../core/utils/datetimeUtils";
36
- import styles from "../stock-items/stock-items-table.scss";
37
37
  import {
38
38
  StockOperationStatusCancelled,
39
39
  StockOperationStatusNew,
@@ -43,8 +43,8 @@ import {
43
43
  import {
44
44
  isDesktop,
45
45
  restBaseUrl,
46
- showModal,
47
46
  useConfig,
47
+ showModal,
48
48
  } from "@openmrs/esm-framework";
49
49
  import StockOperationTypesSelector from "./stock-operation-types-selector/stock-operation-types-selector.component";
50
50
  import { launchAddOrEditDialog } from "./stock-operation.utils";
@@ -59,6 +59,9 @@ import {
59
59
  StockFilters,
60
60
  } from "../constants";
61
61
  import { handleMutate } from "../utils";
62
+
63
+ import styles from "./stock-operations-table.scss";
64
+
62
65
  interface StockOperationsTableProps {
63
66
  status?: string;
64
67
  }
@@ -95,6 +98,12 @@ const StockOperations: React.FC<StockOperationsTableProps> = () => {
95
98
  []
96
99
  );
97
100
 
101
+ const [selectedFromDate, setSelectedFromDate] = useState(null);
102
+ const [selectedToDate, setSelectedToDate] = useState(null);
103
+ const [selectedSources, setSelectedSources] = useState<string[]>([]);
104
+ const [selectedStatus, setSelectedStatus] = useState<string[]>([]);
105
+ const [selectedOperations, setSelectedOperations] = useState<string[]>([]);
106
+
98
107
  const {
99
108
  items,
100
109
  tableHeaders,
@@ -108,17 +117,24 @@ const StockOperations: React.FC<StockOperationsTableProps> = () => {
108
117
  } = useStockOperationPages({
109
118
  v: ResourceRepresentation.Full,
110
119
  totalCount: true,
120
+ operationDateMin: selectedFromDate?.toISOString(),
121
+ operationDateMax: selectedToDate?.toISOString(),
122
+ status: selectedStatus.join(","),
123
+ sourceTypeUuid: selectedSources.join(","),
124
+ operationTypeUuid: selectedOperations.join(","),
111
125
  });
112
126
 
113
- const [filteredItems, setFilteredItems] = useState(items);
114
- const [selectedFromDate, setSelectedFromDate] = useState(null);
115
- const [selectedToDate, setSelectedToDate] = useState(null);
116
- const [selectedSources, setSelectedSources] = useState<string[]>([]);
117
- const [selectedStatus, setSelectedStatus] = useState<string[]>([]);
118
- const [selectedOperations, setSelectedOperations] = useState<string[]>([]);
127
+ const filterApplied =
128
+ selectedFromDate ||
129
+ selectedToDate ||
130
+ selectedSources.length ||
131
+ selectedStatus.length ||
132
+ selectedOperations.length;
133
+
119
134
  const config = useConfig();
120
135
 
121
136
  let operations: StockOperationType[] | null | undefined;
137
+
122
138
  const handleOnComplete = () => {
123
139
  const dispose = showModal("stock-operation-dialog", {
124
140
  title: "complete",
@@ -127,19 +143,6 @@ const StockOperations: React.FC<StockOperationsTableProps> = () => {
127
143
  handleMutate(`${restBaseUrl}/stockmanagement/stockoperation`);
128
144
  };
129
145
 
130
- useEffect(() => {
131
- filterItems();
132
- }, [
133
- selectedFromDate,
134
- selectedToDate,
135
- selectedSources,
136
- selectedStatus,
137
- selectedOperations,
138
- currentPage,
139
- currentPageSize,
140
- items,
141
- ]);
142
-
143
146
  const handleOnFilterChange = useCallback((selectedItems, filterType) => {
144
147
  if (filterType === StockFilters.SOURCES) {
145
148
  setSelectedSources(selectedItems);
@@ -165,51 +168,15 @@ const StockOperations: React.FC<StockOperationsTableProps> = () => {
165
168
  }
166
169
  };
167
170
 
168
- const filterItems = () => {
169
- let filtered = items;
170
-
171
- if (selectedSources.length > 0) {
172
- filtered = filtered.filter((row) =>
173
- selectedSources.includes(row.sourceName)
174
- );
175
- }
176
- if (selectedOperations.length > 0) {
177
- filtered = filtered.filter((row) =>
178
- selectedOperations.includes(row.operationTypeName)
179
- );
180
- }
181
- if (selectedStatus.length > 0) {
182
- filtered = filtered.filter((row) => selectedStatus.includes(row.status));
183
- }
184
- if (selectedFromDate && selectedToDate) {
185
- filtered = filtered.filter((row) => {
186
- const itemDate = new Date(row.operationDate);
187
- return itemDate >= selectedFromDate && itemDate <= selectedToDate;
188
- });
189
- } else if (selectedFromDate) {
190
- filtered = filtered.filter((row) => {
191
- const itemDate = new Date(row.operationDate);
192
- return itemDate >= selectedFromDate;
193
- });
194
- } else if (selectedToDate) {
195
- filtered = filtered.filter((row) => {
196
- const itemDate = new Date(row.operationDate);
197
- return itemDate <= selectedToDate;
198
- });
199
- }
200
-
201
- setFilteredItems(filtered);
202
- };
203
-
204
171
  const tableRows = useMemo(() => {
205
- return filteredItems?.map((stockOperation, index) => ({
172
+ return items?.map((stockOperation, index) => ({
206
173
  ...stockOperation,
207
174
  id: stockOperation?.uuid,
208
175
  key: `key-${stockOperation?.uuid}`,
209
176
  operationTypeName: `${stockOperation?.operationTypeName}`,
210
177
  operationNumber: (
211
178
  <EditStockOperationActionMenu
212
- model={filteredItems[index]}
179
+ model={items[index]}
213
180
  operations={operations}
214
181
  />
215
182
  ),
@@ -348,7 +315,7 @@ const StockOperations: React.FC<StockOperationsTableProps> = () => {
348
315
  onClick={() => {
349
316
  launchAddOrEditDialog(
350
317
  t,
351
- filteredItems[index],
318
+ items[index],
352
319
  true,
353
320
  operation,
354
321
  operations,
@@ -359,9 +326,9 @@ const StockOperations: React.FC<StockOperationsTableProps> = () => {
359
326
  </OverflowMenu>
360
327
  ),
361
328
  }));
362
- }, [handleOnComplete, filteredItems, operation, operations, t]);
329
+ }, [items, operation, operations, t]);
363
330
 
364
- if (isLoading) {
331
+ if (isLoading && !filterApplied) {
365
332
  return (
366
333
  <DataTableSkeleton
367
334
  className={styles.dataTableSkeleton}
@@ -531,47 +498,39 @@ const StockOperations: React.FC<StockOperationsTableProps> = () => {
531
498
  <StructuredListBody>
532
499
  <StructuredListRow>
533
500
  <StructuredListCell noWrap>
534
- {filteredItems[index]?.dateCreated
535
- ? formatDisplayDate(
536
- filteredItems[index]?.dateCreated
537
- )
501
+ {items[index]?.dateCreated
502
+ ? formatDisplayDate(items[index]?.dateCreated)
538
503
  : ""}
539
504
  &nbsp;
540
- {filteredItems[index]?.dateCreated ? "By" : ""}
505
+ {items[index]?.dateCreated ? "By" : ""}
541
506
  &nbsp;
542
- {filteredItems[index]?.dateCreated
543
- ? filteredItems[index]?.creatorFamilyName
507
+ {items[index]?.dateCreated
508
+ ? items[index]?.creatorFamilyName
544
509
  : ""}
545
510
  </StructuredListCell>
546
511
  <StructuredListCell>
547
- {filteredItems[index]?.completedDate
512
+ {items[index]?.completedDate
548
513
  ? formatDisplayDate(
549
- filteredItems[index]?.completedDate
514
+ items[index]?.completedDate
550
515
  )
551
516
  : ""}
552
517
  &nbsp;
553
- {filteredItems[index]?.completedDate
554
- ? "By"
555
- : ""}
518
+ {items[index]?.completedDate ? "By" : ""}
556
519
  &nbsp;
557
- {filteredItems[index]?.completedDate
558
- ? filteredItems[index]?.creatorFamilyName
520
+ {items[index]?.completedDate
521
+ ? items[index]?.creatorFamilyName
559
522
  : ""}
560
523
  </StructuredListCell>
561
524
  <StructuredListCell>
562
- {filteredItems[index]?.stockOperationItems
563
- ? filteredItems[
564
- index
565
- ].stockOperationItems?.map(
525
+ {items[index]?.stockOperationItems
526
+ ? items[index].stockOperationItems?.map(
566
527
  (item) => item.batchNo
567
528
  )[0]
568
529
  : ""}
569
530
  </StructuredListCell>
570
531
  <StructuredListCell>
571
- {filteredItems[index]?.stockOperationItems
572
- ? filteredItems[
573
- index
574
- ].stockOperationItems?.map(
532
+ {items[index]?.stockOperationItems
533
+ ? items[index].stockOperationItems?.map(
575
534
  (item) => item.quantity
576
535
  )[0]
577
536
  : ""}
@@ -579,61 +538,55 @@ const StockOperations: React.FC<StockOperationsTableProps> = () => {
579
538
  </StructuredListRow>
580
539
  <StructuredListRow>
581
540
  <StructuredListCell noWrap>
582
- {filteredItems[index]?.stockOperationItems.map(
541
+ {items[index]?.stockOperationItems.map(
583
542
  (item) => item.quantity
584
543
  )[1]
585
- ? formatDisplayDate(
586
- filteredItems[index]?.dateCreated
587
- )
544
+ ? formatDisplayDate(items[index]?.dateCreated)
588
545
  : ""}
589
546
  &nbsp;
590
- {filteredItems[index]?.stockOperationItems.map(
547
+ {items[index]?.stockOperationItems.map(
591
548
  (item) => item.quantity
592
549
  )[1]
593
550
  ? "By"
594
551
  : ""}
595
552
  &nbsp;
596
- {filteredItems[index]?.stockOperationItems.map(
553
+ {items[index]?.stockOperationItems.map(
597
554
  (item) => item.quantity
598
555
  )[1]
599
- ? filteredItems[index]?.creatorFamilyName
556
+ ? items[index]?.creatorFamilyName
600
557
  : ""}
601
558
  </StructuredListCell>
602
559
  <StructuredListCell>
603
- {filteredItems[index]?.stockOperationItems.map(
560
+ {items[index]?.stockOperationItems.map(
604
561
  (item) => item.quantity
605
562
  )[1]
606
563
  ? formatDisplayDate(
607
- filteredItems[index]?.completedDate
564
+ items[index]?.completedDate
608
565
  )
609
566
  : ""}
610
567
  &nbsp;
611
- {filteredItems[index]?.stockOperationItems.map(
568
+ {items[index]?.stockOperationItems.map(
612
569
  (item) => item.quantity
613
- )[1] && filteredItems[index]?.completedDate
570
+ )[1] && items[index]?.completedDate
614
571
  ? "By"
615
572
  : ""}
616
573
  &nbsp;
617
- {filteredItems[index]?.stockOperationItems.map(
574
+ {items[index]?.stockOperationItems.map(
618
575
  (item) => item.quantity
619
- )[1] && filteredItems[index]?.completedDate
576
+ )[1] && items[index]?.completedDate
620
577
  ? items[index]?.creatorFamilyName
621
578
  : ""}
622
579
  </StructuredListCell>
623
580
  <StructuredListCell>
624
- {filteredItems[index]?.stockOperationItems
625
- ? filteredItems[
626
- index
627
- ].stockOperationItems?.map(
581
+ {items[index]?.stockOperationItems
582
+ ? items[index].stockOperationItems?.map(
628
583
  (item) => item.batchNo
629
584
  )[1]
630
585
  : ""}
631
586
  </StructuredListCell>
632
587
  <StructuredListCell>
633
- {filteredItems[index]?.stockOperationItems
634
- ? filteredItems[
635
- index
636
- ].stockOperationItems?.map(
588
+ {items[index]?.stockOperationItems
589
+ ? items[index].stockOperationItems?.map(
637
590
  (item) => item.quantity
638
591
  )[1]
639
592
  : ""}
@@ -647,7 +600,7 @@ const StockOperations: React.FC<StockOperationsTableProps> = () => {
647
600
  })}
648
601
  </TableBody>
649
602
  </Table>
650
- {rows.length === 0 ? (
603
+ {rows.length === 0 && !isLoading ? (
651
604
  <div className={styles.tileContainer}>
652
605
  <Tile className={styles.tile}>
653
606
  <div className={styles.tileContent}>
@@ -661,24 +614,31 @@ const StockOperations: React.FC<StockOperationsTableProps> = () => {
661
614
  </Tile>
662
615
  </div>
663
616
  ) : null}
617
+ {filterApplied && isLoading && (
618
+ <div className={styles.rowLoadingContainer}>
619
+ <InlineLoading description={t("loading", "Loading...")} />
620
+ </div>
621
+ )}
664
622
  </TableContainer>
665
623
  )}
666
624
  ></DataTable>
667
- <Pagination
668
- page={currentPage}
669
- pageSize={currentPageSize}
670
- pageSizes={pageSizes}
671
- totalItems={totalItems}
672
- onChange={({ pageSize, page }) => {
673
- if (pageSize !== currentPageSize) {
674
- setPageSize(pageSize);
675
- }
676
- if (page !== currentPage) {
677
- goTo(page);
678
- }
679
- }}
680
- className={styles.paginationOverride}
681
- />
625
+ {items.length > 0 && (
626
+ <Pagination
627
+ page={currentPage}
628
+ pageSize={currentPageSize}
629
+ pageSizes={pageSizes}
630
+ totalItems={totalItems}
631
+ onChange={({ pageSize, page }) => {
632
+ if (pageSize !== currentPageSize) {
633
+ setPageSize(pageSize);
634
+ }
635
+ if (page !== currentPage) {
636
+ goTo(page);
637
+ }
638
+ }}
639
+ className={styles.paginationOverride}
640
+ />
641
+ )}
682
642
  </div>
683
643
  );
684
644
  };
@@ -0,0 +1,61 @@
1
+ @use '@carbon/styles/scss/spacing';
2
+ @use '@carbon/styles/scss/type';
3
+ @import "~@openmrs/esm-styleguide/src/vars";
4
+ @import '../root.scss';
5
+
6
+ .tileContainer {
7
+ background-color: $ui-02;
8
+ border-top: 1px solid $ui-03;
9
+ padding: 5rem 0;
10
+ }
11
+
12
+ .tile {
13
+ margin: auto;
14
+ width: fit-content;
15
+ }
16
+
17
+ .tileContent {
18
+ display: flex;
19
+ flex-direction: column;
20
+ align-items: center;
21
+ }
22
+
23
+ .content {
24
+ @include type.type-style('heading-compact-02');
25
+ color: $text-02;
26
+ margin-bottom: 0.5rem;
27
+ }
28
+
29
+ .helper {
30
+ @include type.type-style('body-compact-01');
31
+ color: $text-02;
32
+ }
33
+
34
+ .toolbarContent {
35
+ display: flex;
36
+ align-items: center;
37
+ }
38
+
39
+ .filterContainer {
40
+ display: flex;
41
+ align-items: center;
42
+ }
43
+
44
+ .dateAlign {
45
+ padding-top: spacing.$spacing-03;
46
+ height: 100%;
47
+ }
48
+
49
+ .filterContainer {
50
+ display: flex;
51
+ align-items: center;
52
+ justify-content: space-between;
53
+ margin-bottom: spacing.$spacing-05;
54
+ }
55
+
56
+ .rowLoadingContainer {
57
+ text-align: center;
58
+ padding: 5rem 2rem;
59
+ margin: auto;
60
+ width: 20%;
61
+ }
@@ -7,7 +7,6 @@ import useSWR from "swr";
7
7
  import { ResourceFilterCriteria, toQueryParams } from "../core/api/api";
8
8
  import { PageableResult } from "../core/api/types/PageableResult";
9
9
  import { StockOperationDTO } from "../core/api/types/stockOperation/StockOperationDTO";
10
- import { StockOperationLinkDTO } from "../core/api/types/stockOperation/StockOperationLinkDTO";
11
10
  import { StopOperationAction } from "../core/api/types/stockOperation/StockOperationAction";
12
11
  import { InventoryGroupBy } from "../core/api/types/stockItem/StockItem";
13
12
 
@@ -61,9 +61,10 @@ const StockSourcesDeleteActionMenu: React.FC<
61
61
  kind="ghost"
62
62
  size="md"
63
63
  onClick={handleDeleteStockSource}
64
- iconDescription={t("deleteSource", "Delete Source")}
65
- renderIcon={(props) => <TrashCan size={16} {...props} />}
66
- />
64
+ aria-label={t("deleteSource", "Delete Source")}
65
+ >
66
+ <TrashCan size={16} />
67
+ </Button>
67
68
  );
68
69
 
69
70
  return deletingSource ? <InlineLoading /> : deleteButton;
@@ -0,0 +1,190 @@
1
+ import React from "react";
2
+ import { render, fireEvent, waitFor, screen } from "@testing-library/react";
3
+ import "@testing-library/jest-dom/extend-expect";
4
+ import { showModal, showSnackbar } from "@openmrs/esm-framework";
5
+ import { deleteStockSource } from "../stock-sources.resource";
6
+ import StockSourcesDeleteActionMenu from "./stock-sources-delete.component";
7
+ import DeleteConfirmation from "../../stock-user-role-scopes/delete-stock-user-scope-modal.component";
8
+ import { handleMutate } from "../../utils";
9
+
10
+ jest.mock("react-i18next", () => ({
11
+ useTranslation: () => ({
12
+ t: (key) => key,
13
+ }),
14
+ }));
15
+
16
+ jest.mock("@openmrs/esm-framework", () => ({
17
+ showModal: jest.fn(),
18
+ showSnackbar: jest.fn(),
19
+ restBaseUrl: "http://localhost:8080",
20
+ }));
21
+
22
+ jest.mock("../stock-sources.resource", () => ({
23
+ deleteStockSource: jest.fn(),
24
+ }));
25
+
26
+ jest.mock("../../utils", () => ({
27
+ handleMutate: jest.fn(),
28
+ }));
29
+
30
+ describe("StockSourcesDeleteActionMenu", () => {
31
+ const uuid = "1234-5678";
32
+ const uuids: string[] = ["1234-5678"];
33
+
34
+ beforeEach(() => {
35
+ jest.clearAllMocks();
36
+ });
37
+
38
+ it("renders the delete button correctly", () => {
39
+ const { getByRole } = render(<StockSourcesDeleteActionMenu uuid={uuid} />);
40
+ const button = getByRole("button", { name: "deleteSource" });
41
+ expect(button).toBeInTheDocument();
42
+ });
43
+
44
+ it("opens the delete modal when the delete button is clicked", () => {
45
+ const { getByRole } = render(<StockSourcesDeleteActionMenu uuid={uuid} />);
46
+ const button = getByRole("button", { name: "deleteSource" });
47
+ fireEvent.click(button);
48
+ expect(showModal).toHaveBeenCalledWith("delete-stock-modal", expect.objectContaining({
49
+ close: expect.any(Function),
50
+ uuid: uuid,
51
+ onConfirmation: expect.any(Function),
52
+ }));
53
+ });
54
+
55
+ it('calls onConfirmation when delete is clicked', () => {
56
+ const mockOnConfirmation = jest.fn();
57
+ const mockClose = jest.fn();
58
+
59
+ render(
60
+ <DeleteConfirmation
61
+ close={mockClose}
62
+ onConfirmation={mockOnConfirmation}
63
+ />
64
+ );
65
+
66
+ expect(screen.getByText(/deleteStockUserScope/i)).toBeInTheDocument();
67
+
68
+ const deleteButton = screen.getByRole('button', { name: /delete/i });
69
+ fireEvent.click(deleteButton);
70
+
71
+ expect(mockOnConfirmation).toHaveBeenCalledTimes(1);
72
+ expect(mockClose).not.toHaveBeenCalled();
73
+ });
74
+
75
+ it("calls deleteStockSource with the correct UUID on confirmation", async () => {
76
+ const mockOnConfirmation = jest.fn();
77
+ const mockClose = jest.fn();
78
+
79
+ render(
80
+ <DeleteConfirmation
81
+ close={mockClose}
82
+ onConfirmation={() => {
83
+ mockOnConfirmation();
84
+ deleteStockSource([uuid]);
85
+ }}
86
+ />
87
+ );
88
+
89
+ const deleteButton = screen.getByRole('button', { name: /delete/i });
90
+ fireEvent.click(deleteButton);
91
+
92
+ expect(mockOnConfirmation).toHaveBeenCalledTimes(1);
93
+ expect(deleteStockSource).toHaveBeenCalledWith([uuid]);
94
+ });
95
+
96
+ it("calls handleMutate with the correct URL on successful deletion", async () => {
97
+ (deleteStockSource as jest.Mock).mockResolvedValueOnce({});
98
+
99
+ const mockOnConfirmation = jest.fn();
100
+ const mockClose = jest.fn();
101
+
102
+ render(
103
+ <DeleteConfirmation
104
+ close={mockClose}
105
+ onConfirmation={async () => {
106
+ await deleteStockSource([uuid]);
107
+ handleMutate("/openmrs/ws/rest/v1/stocksource");
108
+ }}
109
+ />
110
+ );
111
+
112
+ const deleteButton = screen.getByRole('button', { name: /delete/i });
113
+ fireEvent.click(deleteButton);
114
+
115
+ await waitFor(() => {
116
+ expect(deleteStockSource).toHaveBeenCalledWith([uuid]);
117
+ expect(handleMutate).toHaveBeenCalledWith("/openmrs/ws/rest/v1/stocksource");
118
+ });
119
+ });
120
+
121
+ it("calls showSnackbar with the correct parameters on deletion error", async () => {
122
+ (deleteStockSource as jest.Mock).mockRejectedValueOnce(new Error("Deletion failed"));
123
+
124
+ const mockOnConfirmation = jest.fn();
125
+ const mockClose = jest.fn();
126
+
127
+ render(
128
+ <DeleteConfirmation
129
+ close={mockClose}
130
+ onConfirmation={async () => {
131
+ try {
132
+ await deleteStockSource([uuid]);
133
+ } catch (error) {
134
+ showSnackbar({
135
+ title: "stockSourceDeleteError",
136
+ kind: "error",
137
+ });
138
+ }
139
+ }}
140
+ />
141
+ );
142
+
143
+ const deleteButton = screen.getByRole('button', { name: /delete/i });
144
+ fireEvent.click(deleteButton);
145
+
146
+ await waitFor(() => {
147
+ expect(deleteStockSource).toHaveBeenCalledWith([uuid]);
148
+ expect(showSnackbar).toHaveBeenCalledWith({
149
+ title: "stockSourceDeleteError",
150
+ kind: "error",
151
+ });
152
+ });
153
+ });
154
+
155
+ it("handles the error state correctly when the delete action fails", async () => {
156
+ (deleteStockSource as jest.Mock).mockRejectedValueOnce(new Error("Deletion failed"));
157
+
158
+ const mockOnConfirmation = jest.fn();
159
+ const mockClose = jest.fn();
160
+
161
+ render(
162
+ <DeleteConfirmation
163
+ close={mockClose}
164
+ onConfirmation={async () => {
165
+ try {
166
+ await deleteStockSource([uuid]);
167
+ } catch (error) {
168
+ showSnackbar({
169
+ title: "stockSourceDeleteError",
170
+ kind: "error",
171
+ });
172
+ }
173
+ }}
174
+ />
175
+ );
176
+
177
+ const deleteButton = screen.getByRole("button", { name: /delete/i });
178
+ fireEvent.click(deleteButton);
179
+
180
+ await waitFor(() => {
181
+ expect(deleteStockSource).toHaveBeenCalledWith([uuid]);
182
+
183
+ expect(showSnackbar).toHaveBeenCalledWith({
184
+ title: "stockSourceDeleteError",
185
+ kind: "error",
186
+ });
187
+ expect(deleteButton).toBeInTheDocument();
188
+ });
189
+ });
190
+ });