@openmrs/esm-stock-management-app 1.0.1-pre.666 → 1.0.1-pre.678

Sign up to get free protection for your applications and to get access to all the features.
package/dist/routes.json CHANGED
@@ -1 +1 @@
1
- {"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"fhir2":">=1.2","webservices.rest":"^2.24.0"},"extensions":[{"name":"stock-nav-menu","slot":"stock-sidebar-slot","component":"stockNavMenu","online":true,"offline":true},{"name":"overview-db-link","slot":"stock-page-dashboard-slot","component":"stockOverviewLink","meta":{"name":"overview","slot":"overview-dashboard-slot","title":"overview"},"order":0,"online":true,"offline":true},{"name":"stock-overview-db","slot":"overview-dashboard-slot","component":"stockOverview"},{"name":"operations-db-link","slot":"stock-page-dashboard-slot","component":"stockOperationsLink","meta":{"name":"operations","slot":"operations-dashboard-slot","title":"operations"},"order":2,"online":true,"offline":true},{"name":"stock-operations-db","slot":"operations-dashboard-slot","component":"stockOperations"},{"name":"items-db-link","slot":"stock-page-dashboard-slot","component":"stockItemsLink","meta":{"name":"items","slot":"items-dashboard-slot","title":"items"},"order":1,"online":true,"offline":true},{"name":"stock-items-db","slot":"items-dashboard-slot","component":"stockItems"},{"name":"user-scopes-db-link","slot":"stock-page-dashboard-slot","component":"stockUserScopesLink","meta":{"name":"user-scopes","slot":"user-scopes-dashboard-slot","title":"user-scopes"},"order":3,"online":true,"offline":true},{"name":"stock-user-scopes-db","slot":"user-scopes-dashboard-slot","component":"stockUserScopes"},{"name":"sources-db-link","slot":"stock-page-dashboard-slot","component":"stockSourcesLink","meta":{"name":"sources","slot":"sources-dashboard-slot","title":"Sources"},"order":2,"online":true,"offline":true},{"name":"stock-sources-db","slot":"sources-dashboard-slot","component":"stockSources"},{"name":"locations-db-link","slot":"stock-page-dashboard-slot","component":"stockLocationsLink","meta":{"name":"locations","slot":"locations-dashboard-slot","title":"Locations"},"order":4,"online":true,"offline":true},{"name":"stock-locations-db","slot":"locations-dashboard-slot","component":"stockLocations"},{"name":"reports-db-link","slot":"stock-page-dashboard-slot","component":"stockReportsLink","meta":{"name":"reports","slot":"reports-dashboard-slot","title":"Reports"},"order":5,"online":true,"offline":true},{"name":"stock-reports-db","slot":"reports-dashboard-slot","component":"stockReports"},{"name":"settings-db-link","slot":"stock-page-dashboard-slot","component":"stockSettingsLink","meta":{"name":"settings","slot":"settings-dashboard-slot","title":"Settings"},"order":6,"online":true,"offline":true},{"name":"stock-settings-db","slot":"settings-dashboard-slot","component":"stockSettings"},{"name":"stock-management-admin-card-link","slot":"system-admin-page-card-link-slot","component":"stockManagementAdminCardLink"},{"name":"stock-management-app-menu-item","component":"stockManagementAppMenuItem","slot":"app-menu-item-slot","meta":{"name":" Stock Management"}},{"name":"delete-packaging-unit-button","component":"deletePackagingUnitButton"}],"modals":[{"name":"delete-stock-modal","component":"deleteStockModal"},{"name":"delete-stock-user-scope-modal","component":"deleteUserScopeModal"},{"name":"delete-stock-rule-modal","component":"deleteStockRuleModal"},{"name":"delete-packaging-unit-modal","component":"deletePackagingUnitModal"},{"name":"import-bulk-stock-items","component":"importBulkStockItemsModal"},{"name":"stock-operation-dialog","component":"stockOperationModal"}],"pages":[{"component":"root","route":"stock-management"}],"version":"1.0.1-pre.666"}
1
+ {"$schema":"https://json.openmrs.org/routes.schema.json","backendDependencies":{"fhir2":">=1.2","webservices.rest":"^2.24.0"},"extensions":[{"name":"stock-nav-menu","slot":"stock-sidebar-slot","component":"stockNavMenu","online":true,"offline":true},{"name":"overview-db-link","slot":"stock-page-dashboard-slot","component":"stockOverviewLink","meta":{"name":"overview","slot":"overview-dashboard-slot","title":"overview"},"order":0,"online":true,"offline":true},{"name":"stock-overview-db","slot":"overview-dashboard-slot","component":"stockOverview"},{"name":"operations-db-link","slot":"stock-page-dashboard-slot","component":"stockOperationsLink","meta":{"name":"operations","slot":"operations-dashboard-slot","title":"operations"},"order":2,"online":true,"offline":true},{"name":"stock-operations-db","slot":"operations-dashboard-slot","component":"stockOperations"},{"name":"items-db-link","slot":"stock-page-dashboard-slot","component":"stockItemsLink","meta":{"name":"items","slot":"items-dashboard-slot","title":"items"},"order":1,"online":true,"offline":true},{"name":"stock-items-db","slot":"items-dashboard-slot","component":"stockItems"},{"name":"user-scopes-db-link","slot":"stock-page-dashboard-slot","component":"stockUserScopesLink","meta":{"name":"user-scopes","slot":"user-scopes-dashboard-slot","title":"user-scopes"},"order":3,"online":true,"offline":true},{"name":"stock-user-scopes-db","slot":"user-scopes-dashboard-slot","component":"stockUserScopes"},{"name":"sources-db-link","slot":"stock-page-dashboard-slot","component":"stockSourcesLink","meta":{"name":"sources","slot":"sources-dashboard-slot","title":"Sources"},"order":2,"online":true,"offline":true},{"name":"stock-sources-db","slot":"sources-dashboard-slot","component":"stockSources"},{"name":"locations-db-link","slot":"stock-page-dashboard-slot","component":"stockLocationsLink","meta":{"name":"locations","slot":"locations-dashboard-slot","title":"Locations"},"order":4,"online":true,"offline":true},{"name":"stock-locations-db","slot":"locations-dashboard-slot","component":"stockLocations"},{"name":"reports-db-link","slot":"stock-page-dashboard-slot","component":"stockReportsLink","meta":{"name":"reports","slot":"reports-dashboard-slot","title":"Reports"},"order":5,"online":true,"offline":true},{"name":"stock-reports-db","slot":"reports-dashboard-slot","component":"stockReports"},{"name":"settings-db-link","slot":"stock-page-dashboard-slot","component":"stockSettingsLink","meta":{"name":"settings","slot":"settings-dashboard-slot","title":"Settings"},"order":6,"online":true,"offline":true},{"name":"stock-settings-db","slot":"settings-dashboard-slot","component":"stockSettings"},{"name":"stock-management-admin-card-link","slot":"system-admin-page-card-link-slot","component":"stockManagementAdminCardLink"},{"name":"stock-management-app-menu-item","component":"stockManagementAppMenuItem","slot":"app-menu-item-slot","meta":{"name":" Stock Management"}},{"name":"delete-packaging-unit-button","component":"deletePackagingUnitButton"}],"modals":[{"name":"delete-stock-modal","component":"deleteStockModal"},{"name":"delete-stock-user-scope-modal","component":"deleteUserScopeModal"},{"name":"delete-stock-rule-modal","component":"deleteStockRuleModal"},{"name":"delete-packaging-unit-modal","component":"deletePackagingUnitModal"},{"name":"import-bulk-stock-items","component":"importBulkStockItemsModal"},{"name":"stock-operation-dialog","component":"stockOperationModal"}],"pages":[{"component":"root","route":"stock-management"}],"version":"1.0.1-pre.678"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openmrs/esm-stock-management-app",
3
- "version": "1.0.1-pre.666",
3
+ "version": "1.0.1-pre.678",
4
4
  "license": "MPL-2.0",
5
5
  "description": "Stock management microfrontend for OpenMRS 3.x",
6
6
  "browser": "dist/openmrs-esm-stock-management-app.js",
@@ -0,0 +1,248 @@
1
+ import React from 'react';
2
+ import { renderHook, act, render, screen, waitFor } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+ import '@testing-library/jest-dom/extend-expect';
5
+ import StockSourcesItems from './stock-sources-items-table.component';
6
+ import useStockSourcesPage from './stock-sources-items-table.resource';
7
+ import { useTranslation } from 'react-i18next';
8
+
9
+ jest.mock('react-i18next', () => ({
10
+ useTranslation: jest.fn(),
11
+ }));
12
+
13
+ const mockTranslation = {
14
+ t: (key) => key,
15
+ };
16
+
17
+ jest.mock('./stock-sources-items-table.resource', () => ({
18
+ __esModule: true,
19
+ default: jest.fn(),
20
+ useStockSourcesPage: jest.fn(),
21
+ }));
22
+
23
+ describe('StockSourcesItems', () => {
24
+ const mockFilter = {};
25
+ const mockItems = {
26
+ results: [{ name: 'Community', acronym: 'Community', sourceType: { display: 'Donation' } }],
27
+ totalCount: 1,
28
+ };
29
+
30
+ beforeEach(() => {
31
+ (useTranslation as jest.Mock).mockReturnValue(mockTranslation);
32
+ (useStockSourcesPage as jest.Mock).mockClear();
33
+ });
34
+
35
+ it('should return initial values', () => {
36
+ const mockFilter = {};
37
+ const mockItems = {
38
+ results: [{ name: 'Community', acronym: 'Community', sourceType: { display: 'Donation' } }],
39
+ totalCount: 1,
40
+ };
41
+
42
+ (useStockSourcesPage as jest.Mock).mockReturnValue({
43
+ items: mockItems.results,
44
+ isLoading: false,
45
+ totalItems: mockItems.totalCount,
46
+ currentPage: 1,
47
+ pageSizes: [10, 20, 50],
48
+ goTo: jest.fn(),
49
+ currentPageSize: 10,
50
+ setPageSize: jest.fn(),
51
+ error: null,
52
+ });
53
+
54
+ const { result } = renderHook(() => useStockSourcesPage(mockFilter));
55
+
56
+ expect(result.current.items).toEqual(mockItems.results);
57
+ expect(result.current.totalItems).toBe(mockItems.totalCount);
58
+ expect(result.current.currentPageSize).toBe(10);
59
+ expect(result.current.isLoading).toBe(false);
60
+ expect(result.current.error).toBe(null);
61
+ });
62
+
63
+ it('should update current page size', () => {
64
+ let currentPageSize = 10; // Track page size with a local variable
65
+
66
+ (useStockSourcesPage as jest.Mock).mockReturnValue({
67
+ items: mockItems.results,
68
+ isLoading: false,
69
+ totalItems: mockItems.totalCount,
70
+ currentPage: 1,
71
+ pageSizes: [10, 20, 50],
72
+ goTo: jest.fn(),
73
+ currentPageSize,
74
+ setPageSize: jest.fn((size) => {
75
+ currentPageSize = size; // Update local variable
76
+ }),
77
+ error: null,
78
+ });
79
+
80
+ const { result } = renderHook(() => useStockSourcesPage(mockFilter));
81
+
82
+ act(() => {
83
+ result.current.setPageSize(20);
84
+ });
85
+
86
+ expect(currentPageSize).toBe(20); // Check the local variable instead
87
+ });
88
+
89
+ it('should handle loading and error states', () => {
90
+ (useStockSourcesPage as jest.Mock).mockReturnValue({
91
+ items: { results: [], totalCount: 0 },
92
+ isLoading: true,
93
+ error: null,
94
+ totalItems: 0,
95
+ currentPage: 1,
96
+ currentPageSize: 10,
97
+ pageSizes: [10, 20, 50],
98
+ goTo: jest.fn(),
99
+ setPageSize: jest.fn(),
100
+ });
101
+
102
+ const { result } = renderHook(() => useStockSourcesPage(mockFilter));
103
+
104
+ expect(result.current.isLoading).toBe(true);
105
+ expect(result.current.error).toBe(null);
106
+ expect(result.current.totalItems).toBe(0);
107
+ });
108
+
109
+ test('renders loading state when data is being fetched', () => {
110
+ (useStockSourcesPage as jest.Mock).mockReturnValue({
111
+ items: [],
112
+ isLoading: true,
113
+ totalItems: 0,
114
+ tableHeaders: [],
115
+ currentPage: 1,
116
+ pageSizes: [10, 20, 50],
117
+ goTo: jest.fn(),
118
+ currentPageSize: 10,
119
+ setPageSize: jest.fn(),
120
+ });
121
+
122
+ render(<StockSourcesItems />);
123
+ expect(screen.getByRole('progressbar')).toBeInTheDocument();
124
+ });
125
+
126
+ test('renders data table when data is loaded', () => {
127
+ const mockItems = [
128
+ {
129
+ uuid: '1234',
130
+ name: 'Source A',
131
+ acronym: 'SA',
132
+ sourceType: { display: 'Internal' },
133
+ },
134
+ ];
135
+
136
+ (useStockSourcesPage as jest.Mock).mockReturnValue({
137
+ items: mockItems,
138
+ isLoading: false,
139
+ totalItems: 1,
140
+ tableHeaders: [
141
+ { key: 'name', header: 'Name' },
142
+ { key: 'sourceType', header: 'Source Type' },
143
+ ],
144
+ currentPage: 1,
145
+ pageSizes: [10, 20, 50],
146
+ goTo: jest.fn(),
147
+ currentPageSize: 10,
148
+ setPageSize: jest.fn(),
149
+ });
150
+
151
+ render(<StockSourcesItems />);
152
+
153
+ expect(screen.getByText('Source A')).toBeInTheDocument();
154
+ expect(screen.getByText('Internal')).toBeInTheDocument();
155
+ });
156
+
157
+ test('filters data based on source type', async () => {
158
+ const user = userEvent.setup();
159
+
160
+ const mockItems = [
161
+ {
162
+ uuid: '1234',
163
+ name: 'Source A',
164
+ acronym: 'SA',
165
+ sourceType: { display: 'Internal' },
166
+ },
167
+ {
168
+ uuid: '5678',
169
+ name: 'Source B',
170
+ acronym: 'SB',
171
+ sourceType: { display: 'External' },
172
+ },
173
+ ];
174
+
175
+ (useStockSourcesPage as jest.Mock).mockReturnValue({
176
+ items: mockItems,
177
+ isLoading: false,
178
+ totalItems: 2,
179
+ tableHeaders: [{ key: 'name', header: 'Name' }],
180
+ currentPage: 1,
181
+ pageSizes: [10, 20, 50],
182
+ goTo: jest.fn(),
183
+ currentPageSize: 10,
184
+ setPageSize: jest.fn(),
185
+ });
186
+
187
+ render(<StockSourcesItems />);
188
+
189
+ expect(screen.getByText('Source A')).toBeInTheDocument();
190
+ expect(screen.getByText('Source B')).toBeInTheDocument();
191
+
192
+ const filterInput = screen.getByLabelText('');
193
+ await user.type(filterInput, 'Internal');
194
+
195
+ await waitFor(() => {
196
+ expect(screen.getByText('Source A')).toBeInTheDocument();
197
+ });
198
+
199
+ await waitFor(() => {
200
+ expect(screen.getByText('Source B')).toBeInTheDocument();
201
+ });
202
+ });
203
+
204
+ test('renders a message when no stock sources are available', () => {
205
+ (useStockSourcesPage as jest.Mock).mockReturnValue({
206
+ items: [],
207
+ isLoading: false,
208
+ totalItems: 0,
209
+ tableHeaders: [],
210
+ currentPage: 1,
211
+ pageSizes: [10, 20, 50],
212
+ goTo: jest.fn(),
213
+ currentPageSize: 10,
214
+ setPageSize: jest.fn(),
215
+ });
216
+
217
+ render(<StockSourcesItems />);
218
+
219
+ expect(screen.getByText('noSourcesToDisplay')).toBeInTheDocument();
220
+ expect(screen.getByText('checkFilters')).toBeInTheDocument();
221
+ });
222
+
223
+ test('pagination works as expected', async () => {
224
+ const user = userEvent.setup();
225
+
226
+ const mockGoTo = jest.fn();
227
+ const mockSetPageSize = jest.fn();
228
+
229
+ (useStockSourcesPage as jest.Mock).mockReturnValue({
230
+ items: [],
231
+ isLoading: false,
232
+ totalItems: 20,
233
+ tableHeaders: [],
234
+ currentPage: 1,
235
+ pageSizes: [10, 20, 50],
236
+ goTo: mockGoTo,
237
+ currentPageSize: 10,
238
+ setPageSize: mockSetPageSize,
239
+ });
240
+
241
+ render(<StockSourcesItems />);
242
+
243
+ const nextPageButton = screen.getByLabelText('Next page');
244
+ await user.click(nextPageButton);
245
+
246
+ expect(mockGoTo).toHaveBeenCalledWith(2);
247
+ });
248
+ });