@openmrs/esm-stock-management-app 1.0.1-pre.652 → 1.0.1-pre.653

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-operation-dialog","component":"stockOperationDialog"},{"name":"import-bulk-stock-items","component":"importBulkStockItemsDialog"},{"name":"delete-stock-modal","component":"deleteStockModal"},{"name":"delete-stock-user-scope-modal","component":"deleteUserScopeModal"},{"name":"stock-management-app-menu-item","component":"stockManagementAppMenuItem","slot":"app-menu-item-slot","meta":{"name":" Stock Management"}},{"name":"delete-stock-rule-modal","component":"deleteStockRuleModal"},{"name":"delete-packaging-unit-modal","component":"deletePackagingUnitModal"},{"name":"delete-packaging-unit-button","component":"deletePackagingUnitButton"}],"pages":[{"component":"root","route":"stock-management"}],"version":"1.0.1-pre.652"}
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-operation-dialog","component":"stockOperationDialog"},{"name":"import-bulk-stock-items","component":"importBulkStockItemsDialog"},{"name":"delete-stock-modal","component":"deleteStockModal"},{"name":"delete-stock-user-scope-modal","component":"deleteUserScopeModal"},{"name":"stock-management-app-menu-item","component":"stockManagementAppMenuItem","slot":"app-menu-item-slot","meta":{"name":" Stock Management"}},{"name":"delete-stock-rule-modal","component":"deleteStockRuleModal"},{"name":"delete-packaging-unit-modal","component":"deletePackagingUnitModal"},{"name":"delete-packaging-unit-button","component":"deletePackagingUnitButton"}],"pages":[{"component":"root","route":"stock-management"}],"version":"1.0.1-pre.653"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openmrs/esm-stock-management-app",
3
- "version": "1.0.1-pre.652",
3
+ "version": "1.0.1-pre.653",
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,216 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+ import AddEditStockItem from './add-stock-item.component';
5
+ import { StockItemDTO } from '../../core/api/types/stockItem/StockItem';
6
+
7
+ // Mock components
8
+ jest.mock('react-i18next', () => ({
9
+ useTranslation: () => ({
10
+ t: (key) => key,
11
+ }),
12
+ }));
13
+ jest.mock('@carbon/react', () => {
14
+ const originalModule = jest.requireActual('@carbon/react');
15
+ return {
16
+ ...originalModule,
17
+ useMatchMedia: jest.fn().mockReturnValue(false),
18
+ };
19
+ });
20
+
21
+ jest.mock('@carbon/react/icons', () => ({
22
+ Save: () => <div>Save Icon</div>,
23
+ }));
24
+
25
+ jest.mock('./stock-item-details/stock-item-details.component', () => ({ model }) => (
26
+ <div data-testid="stock-item-details">Stock Item Details: {model.uuid}</div>
27
+ ));
28
+
29
+ jest.mock('./packaging-units/packaging-units.component', () => ({ stockItemUuid }) => (
30
+ <div data-testid="packaging-units">Packaging Units: {stockItemUuid || 'N/A'}</div>
31
+ ));
32
+
33
+ jest.mock('./transactions/transactions.component', () => ({ stockItemUuid }) => (
34
+ <div data-testid="transactions">Transactions: {stockItemUuid || 'N/A'}</div>
35
+ ));
36
+
37
+ jest.mock('./batch-information/batch-information.component', () => ({ stockItemUuid }) => (
38
+ <div data-testid="batch-information">Batch Information: {stockItemUuid || 'N/A'}</div>
39
+ ));
40
+
41
+ jest.mock('./quantities/quantities.component', () => ({ stockItemUuid }) => (
42
+ <div data-testid="quantities">Quantities: {stockItemUuid || 'N/A'}</div>
43
+ ));
44
+
45
+ jest.mock('./stock-item-rules/stock-item-rules.component', () => ({ stockItemUuid }) => (
46
+ <div data-testid="stock-rules">Rules: {stockItemUuid || 'N/A'}</div>
47
+ ));
48
+
49
+ jest.mock('./stock-item-references/stock-item-references.component', () => ({ stockItemUuid }) => (
50
+ <div data-testid="stock-references">References: {stockItemUuid || 'N/A'}</div>
51
+ ));
52
+
53
+ // Mock window.matchMedia
54
+ Object.defineProperty(window, 'matchMedia', {
55
+ writable: true,
56
+ value: jest.fn().mockImplementation((query) => ({
57
+ matches: false,
58
+ media: query,
59
+ onchange: null,
60
+ addListener: jest.fn(),
61
+ removeListener: jest.fn(),
62
+ addEventListener: jest.fn(),
63
+ removeEventListener: jest.fn(),
64
+ dispatchEvent: jest.fn(),
65
+ })),
66
+ });
67
+
68
+ describe('AddEditStockItem', () => {
69
+ const mockModel: StockItemDTO = {
70
+ uuid: 'test-uuid-123',
71
+ isDrug: true,
72
+ drugUuid: 'drug-uuid-456',
73
+ drugName: 'Test Drug',
74
+ conceptUuid: 'concept-uuid-789',
75
+ commonName: 'Test Common Name',
76
+ acronym: 'TCN',
77
+ conceptName: 'Test Concept Name',
78
+ hasExpiration: true,
79
+ packagingUnits: [
80
+ {
81
+ uuid: 'packaging-uuid-001',
82
+ stockItemUuid: 'test-uuid-123',
83
+ packagingUomName: 'Box',
84
+ packagingUomUuid: 'uom-uuid-001',
85
+ factor: 100,
86
+ isDefaultStockOperationsUoM: true,
87
+ isDispensingUnit: false,
88
+ },
89
+ ],
90
+ permission: {
91
+ canView: true,
92
+ canEdit: true,
93
+ canApprove: false,
94
+ canReceiveItems: true,
95
+ canDisplayReceivedItems: true,
96
+ isRequisitionAndCanIssueStock: false,
97
+ canUpdateBatchInformation: true,
98
+ },
99
+ categoryUuid: 'category-uuid-001',
100
+ categoryName: 'Test Category',
101
+ preferredVendorUuid: 'vendor-uuid-001',
102
+ preferredVendorName: 'Test Vendor',
103
+ purchasePrice: 10.99,
104
+ purchasePriceUoMUuid: 'uom-uuid-002',
105
+ purchasePriceUoMName: 'Each',
106
+ dispensingUnitName: 'Tablet',
107
+ dispensingUnitUuid: 'uom-uuid-003',
108
+ dispensingUnitPackagingUoMUuid: 'uom-uuid-003',
109
+ dispensingUnitPackagingUoMName: 'Tablet',
110
+ defaultStockOperationsUoMUuid: 'uom-uuid-001',
111
+ defaultStockOperationsUoMName: 'Box',
112
+ reorderLevel: 100,
113
+ reorderLevelUoMUuid: 'uom-uuid-001',
114
+ reorderLevelUoMName: 'Box',
115
+ dateCreated: new Date('2023-05-01T10:00:00Z'),
116
+ creatorGivenName: 'John',
117
+ creatorFamilyName: 'Doe',
118
+ voided: false,
119
+ expiryNotice: 30,
120
+ };
121
+
122
+ it('renders correctly with initial state and default selected tab', () => {
123
+ render(<AddEditStockItem model={mockModel} />);
124
+ expect(screen.getByTestId('stock-item-details')).toBeInTheDocument();
125
+ expect(screen.getByText('Stock Item Details: test-uuid-123')).toBeInTheDocument();
126
+ });
127
+
128
+ it('changes selected tab when clicking on different tabs', async () => {
129
+ const user = userEvent.setup();
130
+ render(<AddEditStockItem model={mockModel} isEditing={true} />);
131
+
132
+ await user.click(screen.getByText('packagingUnits'));
133
+ expect(screen.getByTestId('packaging-units')).toBeInTheDocument();
134
+ expect(screen.getByText('Packaging Units: test-uuid-123')).toBeInTheDocument();
135
+
136
+ await user.click(screen.getByText('transactions'));
137
+ expect(screen.getByTestId('transactions')).toBeInTheDocument();
138
+ expect(screen.getByText('Transactions: test-uuid-123')).toBeInTheDocument();
139
+ });
140
+
141
+ it('disables tabs when isEditing is false', () => {
142
+ render(<AddEditStockItem model={mockModel} isEditing={false} />);
143
+
144
+ const disabledTabs = [
145
+ 'packagingUnits',
146
+ 'transactions',
147
+ 'batchInformation',
148
+ 'quantities',
149
+ 'stockRules',
150
+ 'references',
151
+ ];
152
+ disabledTabs.forEach((tabName) => {
153
+ const tab = screen.getByRole('tab', { name: tabName });
154
+ expect(tab).toHaveAttribute('aria-disabled', 'true');
155
+ });
156
+ });
157
+
158
+ it('enables tabs when isEditing is true', () => {
159
+ render(<AddEditStockItem model={mockModel} isEditing={true} />);
160
+
161
+ const enabledTabs = [
162
+ 'packagingUnits',
163
+ 'transactions',
164
+ 'batchInformation',
165
+ 'quantities',
166
+ 'stockRules',
167
+ 'references',
168
+ ];
169
+ enabledTabs.forEach((tabName) => {
170
+ const tab = screen.getByRole('tab', { name: tabName });
171
+ expect(tab).not.toHaveAttribute('aria-disabled', 'true');
172
+ });
173
+ });
174
+
175
+ it('renders correct components based on model prop', async () => {
176
+ const user = userEvent.setup();
177
+ render(<AddEditStockItem model={mockModel} isEditing={true} />);
178
+
179
+ expect(screen.getByText('Stock Item Details: test-uuid-123')).toBeInTheDocument();
180
+
181
+ await user.click(screen.getByText('packagingUnits'));
182
+ expect(screen.getByText('Packaging Units: test-uuid-123')).toBeInTheDocument();
183
+
184
+ await user.click(screen.getByText('transactions'));
185
+ expect(screen.getByText('Transactions: test-uuid-123')).toBeInTheDocument();
186
+
187
+ await user.click(screen.getByText('batchInformation'));
188
+ expect(screen.getByText('Batch Information: test-uuid-123')).toBeInTheDocument();
189
+
190
+ await user.click(screen.getByText('quantities'));
191
+ expect(screen.getByText('Quantities: test-uuid-123')).toBeInTheDocument();
192
+
193
+ await user.click(screen.getByText('stockRules'));
194
+ expect(screen.getByText('Rules: test-uuid-123')).toBeInTheDocument();
195
+
196
+ await user.click(screen.getByText('references'));
197
+ expect(screen.getByText('References: test-uuid-123')).toBeInTheDocument();
198
+ });
199
+
200
+ it('translates tab names correctly', () => {
201
+ render(<AddEditStockItem model={mockModel} />);
202
+
203
+ const tabNames = [
204
+ 'stockItemDetails',
205
+ 'packagingUnits',
206
+ 'transactions',
207
+ 'batchInformation',
208
+ 'quantities',
209
+ 'stockRules',
210
+ 'references',
211
+ ];
212
+ tabNames.forEach((tabName) => {
213
+ expect(screen.getByText(tabName)).toBeInTheDocument();
214
+ });
215
+ });
216
+ });