@openmrs/esm-stock-management-app 1.0.1-pre.785 → 1.0.1-pre.790

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/493.js +1 -1
  2. package/dist/493.js.map +1 -1
  3. package/dist/880.js +1 -0
  4. package/dist/880.js.map +1 -0
  5. package/dist/942.js +1 -0
  6. package/dist/942.js.map +1 -0
  7. package/dist/main.js +1 -1
  8. package/dist/main.js.map +1 -1
  9. package/dist/openmrs-esm-stock-management-app.js +1 -1
  10. package/dist/openmrs-esm-stock-management-app.js.buildmanifest.json +41 -41
  11. package/dist/routes.json +1 -1
  12. package/package.json +1 -1
  13. package/src/config-schema.ts +6 -0
  14. package/src/index.ts +15 -21
  15. package/src/routes.json +5 -4
  16. package/src/stock-operations/add-stock-operation/stock-operations-expanded-row/stock-items-table.scss +34 -0
  17. package/src/stock-operations/add-stock-operation/stock-operations-expanded-row/stock-items-table.tsx +111 -0
  18. package/src/stock-operations/add-stock-operation/stock-operations-expanded-row/stock-operation-expanded-row.component.tsx +116 -0
  19. package/src/stock-operations/add-stock-operation/stock-operations-expanded-row/stock-operation-expanded-row.scss +31 -0
  20. package/src/stock-operations/add-stock-operation/stock-operations-expanded-row/stock-operations-status.tsx +45 -0
  21. package/src/stock-operations/edit-stock-operation/edit-stock-operation-action-menu.component.tsx +2 -2
  22. package/src/stock-operations/stock-operation-actions.component.tsx +81 -0
  23. package/src/stock-operations/stock-operation-links.component.tsx +82 -0
  24. package/src/stock-operations/stock-operation-reference.component.tsx +2 -2
  25. package/src/stock-operations/stock-operation-types-selector/stock-operation-types-selector.component.tsx +2 -2
  26. package/src/stock-operations/stock-operation.utils.tsx +8 -13
  27. package/src/stock-operations/stock-operations-dialog/stock-operations-issue-stock-button.component.tsx +2 -2
  28. package/src/stock-operations/stock-operations-forms/input-components/stock-item-search.component.tsx +30 -7
  29. package/src/stock-operations/stock-operations-forms/step1.test.tsx +158 -17
  30. package/src/stock-operations/stock-operations-forms/step2.test.tsx +59 -10
  31. package/src/stock-operations/stock-operations-forms/step3.test.tsx +63 -10
  32. package/src/stock-operations/stock-operations-forms/steps/base-operation-details-form-step.tsx +11 -9
  33. package/src/stock-operations/stock-operations-forms/steps/received-items.component.tsx +111 -0
  34. package/src/stock-operations/stock-operations-forms/steps/stock-operation-item-cell.component.tsx +20 -9
  35. package/src/stock-operations/stock-operations-forms/steps/stock-operation-items-form-step.component.tsx +21 -46
  36. package/src/stock-operations/stock-operations-forms/steps/stock-operation-items-form-step.scc.scss +4 -18
  37. package/src/stock-operations/stock-operations-forms/steps/stock-operation-submission-form-step.component.tsx +22 -10
  38. package/src/stock-operations/stock-operations-forms/stock-issue-form-initializer-with-related-requisition-operation.component.tsx +20 -3
  39. package/src/stock-operations/stock-operations-forms/stock-item-form/stock-item-form.workspace.tsx +19 -7
  40. package/src/stock-operations/stock-operations-forms/stock-operation-form.component.tsx +114 -67
  41. package/src/stock-operations/stock-operations-forms/stock-operation-form.scss +5 -24
  42. package/src/stock-operations/stock-operations-forms/stock-operation-related-link.component.tsx +2 -2
  43. package/src/stock-operations/stock-operations-forms/stock-operation-stepper/stepper.scss +14 -11
  44. package/src/stock-operations/stock-operations-forms/stock-operation-stepper/stock-operation-stepper.component.tsx +2 -6
  45. package/src/stock-operations/stock-operations-table.component.tsx +39 -38
  46. package/src/stock-operations/stock-operations-table.scss +20 -0
  47. package/dist/155.js +0 -1
  48. package/dist/155.js.map +0 -1
  49. package/dist/914.js +0 -1
  50. package/dist/914.js.map +0 -1
  51. package/src/stock-operations/received-items.component.tsx +0 -93
  52. package/src/stock-operations/stock-operations-forms/stock-operation-form-header.component.tsx +0 -166
@@ -60,6 +60,11 @@ jest.mock('../stock-operations.resource', () => ({
60
60
  isLoading: false,
61
61
  error: null,
62
62
  }),
63
+ useStockOperationAndItems: jest.fn().mockReturnValue({
64
+ items: undefined,
65
+ isLoading: false,
66
+ error: null,
67
+ }),
63
68
  }));
64
69
 
65
70
  jest.mock('./hooks/useParties', () => jest.fn());
@@ -81,7 +86,15 @@ describe('Stock Operation step 1 (baseoperation details)', () => {
81
86
  sourceTags: [],
82
87
  destinationTags: [],
83
88
  });
84
- render(<StockOperationForm stockOperationType={receiptOperationTypeMock as any} />);
89
+ render(
90
+ <StockOperationForm
91
+ stockOperationType={receiptOperationTypeMock as any}
92
+ closeWorkspace={jest.fn()}
93
+ setTitle={jest.fn()}
94
+ closeWorkspaceWithSavedChanges={jest.fn()}
95
+ promptBeforeClosing={jest.fn()}
96
+ />,
97
+ );
85
98
  expect(screen.getByRole('progressbar')).toBeInTheDocument();
86
99
  });
87
100
 
@@ -94,7 +107,15 @@ describe('Stock Operation step 1 (baseoperation details)', () => {
94
107
  sourceTags: [],
95
108
  destinationTags: [],
96
109
  });
97
- render(<StockOperationForm stockOperationType={receiptOperationTypeMock as any} />);
110
+ render(
111
+ <StockOperationForm
112
+ stockOperationType={receiptOperationTypeMock as any}
113
+ closeWorkspace={jest.fn()}
114
+ setTitle={jest.fn()}
115
+ closeWorkspaceWithSavedChanges={jest.fn()}
116
+ promptBeforeClosing={jest.fn()}
117
+ />,
118
+ );
98
119
  expect(screen.getByText('error')).toBeInTheDocument();
99
120
  });
100
121
 
@@ -107,7 +128,15 @@ describe('Stock Operation step 1 (baseoperation details)', () => {
107
128
  sourceTags: [],
108
129
  destinationTags: [],
109
130
  });
110
- render(<StockOperationForm stockOperationType={receiptOperationTypeMock as any} />);
131
+ render(
132
+ <StockOperationForm
133
+ stockOperationType={receiptOperationTypeMock as any}
134
+ closeWorkspace={jest.fn()}
135
+ setTitle={jest.fn()}
136
+ closeWorkspaceWithSavedChanges={jest.fn()}
137
+ promptBeforeClosing={jest.fn()}
138
+ />,
139
+ );
111
140
  expect(screen.getByRole('button', { name: /next/i })).toBeInTheDocument();
112
141
  expect(screen.queryByRole('button', { name: /previous/i })).not.toBeInTheDocument();
113
142
  });
@@ -120,7 +149,15 @@ describe('Stock Operation step 1 (baseoperation details)', () => {
120
149
  sourceTags: [],
121
150
  destinationTags: [],
122
151
  });
123
- render(<StockOperationForm stockOperationType={receiptOperationTypeMock as any} />);
152
+ render(
153
+ <StockOperationForm
154
+ stockOperationType={receiptOperationTypeMock as any}
155
+ closeWorkspace={jest.fn()}
156
+ setTitle={jest.fn()}
157
+ closeWorkspaceWithSavedChanges={jest.fn()}
158
+ promptBeforeClosing={jest.fn()}
159
+ />,
160
+ );
124
161
  expect(screen.getByText(`${receiptOperationTypeMock.name} details`)).toBeInTheDocument();
125
162
  });
126
163
 
@@ -133,7 +170,15 @@ describe('Stock Operation step 1 (baseoperation details)', () => {
133
170
  sourceTags: [],
134
171
  destinationTags: [],
135
172
  });
136
- render(<StockOperationForm stockOperationType={receiptOperationTypeMock as any} />);
173
+ render(
174
+ <StockOperationForm
175
+ stockOperationType={receiptOperationTypeMock as any}
176
+ closeWorkspace={jest.fn()}
177
+ setTitle={jest.fn()}
178
+ closeWorkspaceWithSavedChanges={jest.fn()}
179
+ promptBeforeClosing={jest.fn()}
180
+ />,
181
+ );
137
182
  const sourceInput = screen.getByRole('combobox', {
138
183
  name: (_, element) =>
139
184
  element.getAttribute('placeholder') === 'chooseASource' && element.getAttribute('name') === 'sourceUuid',
@@ -150,7 +195,15 @@ describe('Stock Operation step 1 (baseoperation details)', () => {
150
195
  sourceTags: [],
151
196
  destinationTags: [],
152
197
  });
153
- render(<StockOperationForm stockOperationType={receiptOperationTypeMock as any} />);
198
+ render(
199
+ <StockOperationForm
200
+ stockOperationType={receiptOperationTypeMock as any}
201
+ closeWorkspace={jest.fn()}
202
+ setTitle={jest.fn()}
203
+ closeWorkspaceWithSavedChanges={jest.fn()}
204
+ promptBeforeClosing={jest.fn()}
205
+ />,
206
+ );
154
207
  expect(screen.getByLabelText('to')).toBeInTheDocument();
155
208
  });
156
209
 
@@ -163,7 +216,15 @@ describe('Stock Operation step 1 (baseoperation details)', () => {
163
216
  sourceTags: [],
164
217
  destinationTags: [],
165
218
  });
166
- render(<StockOperationForm stockOperationType={receiptOperationTypeMock as any} />);
219
+ render(
220
+ <StockOperationForm
221
+ stockOperationType={receiptOperationTypeMock as any}
222
+ closeWorkspace={jest.fn()}
223
+ setTitle={jest.fn()}
224
+ closeWorkspaceWithSavedChanges={jest.fn()}
225
+ promptBeforeClosing={jest.fn()}
226
+ />,
227
+ );
167
228
  expect(
168
229
  screen.getByRole('combobox', {
169
230
  name: (_, element) =>
@@ -182,7 +243,15 @@ describe('Stock Operation step 1 (baseoperation details)', () => {
182
243
  sourceTags: [],
183
244
  destinationTags: [],
184
245
  });
185
- render(<StockOperationForm stockOperationType={disposalOperationTypeMock as any} />);
246
+ render(
247
+ <StockOperationForm
248
+ stockOperationType={disposalOperationTypeMock as any}
249
+ closeWorkspace={jest.fn()}
250
+ setTitle={jest.fn()}
251
+ closeWorkspaceWithSavedChanges={jest.fn()}
252
+ promptBeforeClosing={jest.fn()}
253
+ />,
254
+ );
186
255
  expect(
187
256
  screen.getByRole('combobox', {
188
257
  name: (_, element) =>
@@ -201,7 +270,15 @@ describe('Stock Operation step 1 (baseoperation details)', () => {
201
270
  sourceTags: [],
202
271
  destinationTags: [],
203
272
  });
204
- render(<StockOperationForm stockOperationType={receiptOperationTypeMock as any} />);
273
+ render(
274
+ <StockOperationForm
275
+ stockOperationType={receiptOperationTypeMock as any}
276
+ closeWorkspace={jest.fn()}
277
+ setTitle={jest.fn()}
278
+ closeWorkspaceWithSavedChanges={jest.fn()}
279
+ promptBeforeClosing={jest.fn()}
280
+ />,
281
+ );
205
282
  expect(screen.queryByLabelText(/.*reason.*/i)).not.toBeInTheDocument();
206
283
  });
207
284
  it('should render reason input field for adjustment operation', async () => {
@@ -213,7 +290,15 @@ describe('Stock Operation step 1 (baseoperation details)', () => {
213
290
  sourceTags: [],
214
291
  destinationTags: [],
215
292
  });
216
- render(<StockOperationForm stockOperationType={adjustmentOpeationTypeMock as any} />);
293
+ render(
294
+ <StockOperationForm
295
+ stockOperationType={adjustmentOpeationTypeMock as any}
296
+ closeWorkspace={jest.fn()}
297
+ setTitle={jest.fn()}
298
+ closeWorkspaceWithSavedChanges={jest.fn()}
299
+ promptBeforeClosing={jest.fn()}
300
+ />,
301
+ );
217
302
  expect(screen.getByLabelText(/.*reason.*/i)).toBeInTheDocument();
218
303
  });
219
304
  it('should not render reason input field for opening stock operation', async () => {
@@ -225,7 +310,15 @@ describe('Stock Operation step 1 (baseoperation details)', () => {
225
310
  sourceTags: [],
226
311
  destinationTags: [],
227
312
  });
228
- render(<StockOperationForm stockOperationType={openingStockOperationTypeMock as any} />);
313
+ render(
314
+ <StockOperationForm
315
+ stockOperationType={openingStockOperationTypeMock as any}
316
+ closeWorkspace={jest.fn()}
317
+ setTitle={jest.fn()}
318
+ closeWorkspaceWithSavedChanges={jest.fn()}
319
+ promptBeforeClosing={jest.fn()}
320
+ />,
321
+ );
229
322
  expect(screen.queryByLabelText(/.*reason.*/i)).not.toBeInTheDocument();
230
323
  });
231
324
  it('should not render reason input field for requisition operation', async () => {
@@ -237,7 +330,15 @@ describe('Stock Operation step 1 (baseoperation details)', () => {
237
330
  sourceTags: [],
238
331
  destinationTags: [],
239
332
  });
240
- render(<StockOperationForm stockOperationType={requisitionOperationTypeMock as any} />);
333
+ render(
334
+ <StockOperationForm
335
+ stockOperationType={requisitionOperationTypeMock as any}
336
+ closeWorkspace={jest.fn()}
337
+ setTitle={jest.fn()}
338
+ closeWorkspaceWithSavedChanges={jest.fn()}
339
+ promptBeforeClosing={jest.fn()}
340
+ />,
341
+ );
241
342
  expect(screen.queryByLabelText(/.*reason.*/i)).not.toBeInTheDocument();
242
343
  });
243
344
  it('should not render reason input field for return operation', async () => {
@@ -249,7 +350,15 @@ describe('Stock Operation step 1 (baseoperation details)', () => {
249
350
  sourceTags: [],
250
351
  destinationTags: [],
251
352
  });
252
- render(<StockOperationForm stockOperationType={returnOperationTypeMock as any} />);
353
+ render(
354
+ <StockOperationForm
355
+ stockOperationType={returnOperationTypeMock as any}
356
+ closeWorkspace={jest.fn()}
357
+ setTitle={jest.fn()}
358
+ closeWorkspaceWithSavedChanges={jest.fn()}
359
+ promptBeforeClosing={jest.fn()}
360
+ />,
361
+ );
253
362
  expect(screen.queryByLabelText(/.*reason.*/i)).not.toBeInTheDocument();
254
363
  });
255
364
  it('should not render reason input field for issue operation', async () => {
@@ -261,7 +370,15 @@ describe('Stock Operation step 1 (baseoperation details)', () => {
261
370
  sourceTags: [],
262
371
  destinationTags: [],
263
372
  });
264
- render(<StockOperationForm stockOperationType={stockIssueOperationtypeMock as any} />);
373
+ render(
374
+ <StockOperationForm
375
+ stockOperationType={stockIssueOperationtypeMock as any}
376
+ closeWorkspace={jest.fn()}
377
+ setTitle={jest.fn()}
378
+ closeWorkspaceWithSavedChanges={jest.fn()}
379
+ promptBeforeClosing={jest.fn()}
380
+ />,
381
+ );
265
382
  expect(screen.queryByLabelText(/.*reason.*/i)).not.toBeInTheDocument();
266
383
  });
267
384
  it('should not render reason input field for tranfer out operation', async () => {
@@ -273,7 +390,15 @@ describe('Stock Operation step 1 (baseoperation details)', () => {
273
390
  sourceTags: [],
274
391
  destinationTags: [],
275
392
  });
276
- render(<StockOperationForm stockOperationType={tranferOutOperationTypeMock as any} />);
393
+ render(
394
+ <StockOperationForm
395
+ stockOperationType={tranferOutOperationTypeMock as any}
396
+ closeWorkspace={jest.fn()}
397
+ setTitle={jest.fn()}
398
+ closeWorkspaceWithSavedChanges={jest.fn()}
399
+ promptBeforeClosing={jest.fn()}
400
+ />,
401
+ );
277
402
  expect(screen.queryByLabelText(/.*reason.*/i)).not.toBeInTheDocument();
278
403
  });
279
404
  it('should render reason input field for disposal operation', async () => {
@@ -285,7 +410,15 @@ describe('Stock Operation step 1 (baseoperation details)', () => {
285
410
  sourceTags: [],
286
411
  destinationTags: [],
287
412
  });
288
- render(<StockOperationForm stockOperationType={disposalOperationTypeMock as any} />);
413
+ render(
414
+ <StockOperationForm
415
+ stockOperationType={disposalOperationTypeMock as any}
416
+ closeWorkspace={jest.fn()}
417
+ setTitle={jest.fn()}
418
+ closeWorkspaceWithSavedChanges={jest.fn()}
419
+ promptBeforeClosing={jest.fn()}
420
+ />,
421
+ );
289
422
  expect(screen.getByLabelText(/.*reason.*/i)).toBeInTheDocument();
290
423
  });
291
424
  it('should render reason input field for stock take operation', async () => {
@@ -297,7 +430,15 @@ describe('Stock Operation step 1 (baseoperation details)', () => {
297
430
  sourceTags: [],
298
431
  destinationTags: [],
299
432
  });
300
- render(<StockOperationForm stockOperationType={stockTakeOperationTypeMock as any} />);
433
+ render(
434
+ <StockOperationForm
435
+ stockOperationType={stockTakeOperationTypeMock as any}
436
+ closeWorkspace={jest.fn()}
437
+ setTitle={jest.fn()}
438
+ closeWorkspaceWithSavedChanges={jest.fn()}
439
+ promptBeforeClosing={jest.fn()}
440
+ />,
441
+ );
301
442
  expect(screen.getByLabelText(/.*reason.*/i)).toBeInTheDocument();
302
443
  });
303
444
  });
@@ -62,7 +62,11 @@ jest.mock('../../core/components/overlay/hook', () => ({
62
62
  }));
63
63
 
64
64
  jest.mock('../../stock-items/stock-items.resource', () => ({
65
- useStockItem: jest.fn(),
65
+ useStockItem: jest.fn().mockReturnValue({
66
+ isLoading: false,
67
+ item: {},
68
+ error: null,
69
+ }),
66
70
  useStockItems: jest.fn().mockReturnValue({
67
71
  isLoading: false,
68
72
  error: null,
@@ -146,16 +150,32 @@ describe('Stock Operation step 2 (stock operation items details)', () => {
146
150
  });
147
151
 
148
152
  it('should have both previous and next btns', async () => {
149
- render(<StockOperationForm stockOperationType={receiptOperationTypeMock as any} />);
153
+ render(
154
+ <StockOperationForm
155
+ stockOperationType={receiptOperationTypeMock as any}
156
+ closeWorkspace={jest.fn()}
157
+ setTitle={jest.fn()}
158
+ closeWorkspaceWithSavedChanges={jest.fn()}
159
+ promptBeforeClosing={jest.fn()}
160
+ />,
161
+ );
150
162
  // MOVE TO STEP 2
151
163
  await userEvent.click(screen.getByRole('button', { name: /Next/i }));
152
164
 
153
165
  expect(screen.getByRole('button', { name: /Next/i })).toBeInTheDocument();
154
- expect(screen.getByRole('button', { name: /previous/i })).toBeInTheDocument();
166
+ expect(screen.getByTestId('previous-btn')).toBeInTheDocument();
155
167
  });
156
168
 
157
169
  it('should render stock operation items table with item search component', async () => {
158
- render(<StockOperationForm stockOperationType={receiptOperationTypeMock as any} />);
170
+ render(
171
+ <StockOperationForm
172
+ stockOperationType={receiptOperationTypeMock as any}
173
+ closeWorkspace={jest.fn()}
174
+ setTitle={jest.fn()}
175
+ closeWorkspaceWithSavedChanges={jest.fn()}
176
+ promptBeforeClosing={jest.fn()}
177
+ />,
178
+ );
159
179
  const nextButton = screen.getByRole('button', { name: /Next/i });
160
180
  expect(nextButton).toBeInTheDocument();
161
181
  await userEvent.click(nextButton);
@@ -176,13 +196,23 @@ describe('Stock Operation step 2 (stock operation items details)', () => {
176
196
  it('should search stock operation item and render results', async () => {
177
197
  const mocksetSearchString = jest.fn();
178
198
  (useFilterableStockItems as jest.Mock).mockReturnValue({
179
- stockItemsList: [{ uuid: 'mock-uuid', commonName: 'mock-common-name' }] as Array<StockItemDTO>,
199
+ stockItemsList: [
200
+ { uuid: 'mock-uuid', commonName: 'mock-common-name', drugName: 'mock-common-name' },
201
+ ] as Array<StockItemDTO>,
180
202
  setLimit: jest.fn(),
181
203
  setRepresentation: jest.fn(),
182
204
  isLoading: false,
183
205
  setSearchString: mocksetSearchString,
184
206
  });
185
- render(<StockOperationForm stockOperationType={receiptOperationTypeMock as any} />);
207
+ render(
208
+ <StockOperationForm
209
+ stockOperationType={receiptOperationTypeMock as any}
210
+ closeWorkspace={jest.fn()}
211
+ setTitle={jest.fn()}
212
+ closeWorkspaceWithSavedChanges={jest.fn()}
213
+ promptBeforeClosing={jest.fn()}
214
+ />,
215
+ );
186
216
  // ----- CLICK NEXT TO MOVE TO STEP 2 ---------
187
217
  await userEvent.click(screen.getByRole('button', { name: /Next/i }));
188
218
  // -------------------------------
@@ -198,13 +228,23 @@ describe('Stock Operation step 2 (stock operation items details)', () => {
198
228
 
199
229
  it('should properly handle stock operation item selection', async () => {
200
230
  (useFilterableStockItems as jest.Mock).mockReturnValue({
201
- stockItemsList: [{ uuid: 'mock-uuid', commonName: 'mock-common-name' }] as Array<StockItemDTO>,
231
+ stockItemsList: [
232
+ { uuid: 'mock-uuid', commonName: 'mock-common-name', drugName: 'mock-common-name' },
233
+ ] as Array<StockItemDTO>,
202
234
  setLimit: jest.fn(),
203
235
  setRepresentation: jest.fn(),
204
236
  isLoading: false,
205
237
  setSearchString: jest.fn(),
206
238
  });
207
- render(<StockOperationForm stockOperationType={receiptOperationTypeMock as any} />);
239
+ render(
240
+ <StockOperationForm
241
+ stockOperationType={receiptOperationTypeMock as any}
242
+ closeWorkspace={jest.fn()}
243
+ setTitle={jest.fn()}
244
+ closeWorkspaceWithSavedChanges={jest.fn()}
245
+ promptBeforeClosing={jest.fn()}
246
+ />,
247
+ );
208
248
  // ----- CLICK NEXT TO MOVE TO STEP 2 ---------
209
249
  await userEvent.click(screen.getByRole('button', { name: /Next/i }));
210
250
  // -------------------------------
@@ -214,7 +254,8 @@ describe('Stock Operation step 2 (stock operation items details)', () => {
214
254
  await userEvent.click(searchInput);
215
255
  await userEvent.type(searchInput, 'stock');
216
256
  await userEvent.click(screen.getByText('mock-common-name'));
217
- expect(launchWorkspace).toHaveBeenCalled();
257
+ // Look for common name at the top of workspace
258
+ expect(screen.getByText(/noDrugNameAvailable|noCommonNameAvailable|mock-common-name/i)).toBeInTheDocument();
218
259
  });
219
260
 
220
261
  it('should render stock operation items in data table', async () => {
@@ -240,7 +281,15 @@ describe('Stock Operation step 2 (stock operation items details)', () => {
240
281
  setValue: jest.fn(),
241
282
  handleSubmit: jest.fn(),
242
283
  });
243
- render(<StockOperationForm stockOperationType={receiptOperationTypeMock as any} />);
284
+ render(
285
+ <StockOperationForm
286
+ stockOperationType={receiptOperationTypeMock as any}
287
+ closeWorkspace={jest.fn()}
288
+ setTitle={jest.fn()}
289
+ closeWorkspaceWithSavedChanges={jest.fn()}
290
+ promptBeforeClosing={jest.fn()}
291
+ />,
292
+ );
244
293
  // ----- CLICK NEXT TO MOVE TO STEP 2 ---------
245
294
  await userEvent.click(screen.getByRole('button', { name: /Next/i }));
246
295
  // -------------------------------
@@ -60,6 +60,11 @@ jest.mock('../stock-operations.resource', () => ({
60
60
  isLoading: false,
61
61
  error: null,
62
62
  }),
63
+ useStockOperationAndItems: jest.fn().mockReturnValue({
64
+ items: undefined,
65
+ isLoading: false,
66
+ error: null,
67
+ }),
63
68
  }));
64
69
 
65
70
  jest.mock('../../core/components/overlay/hook', () => ({
@@ -145,18 +150,34 @@ describe('Stock Operation form step 3 (stock submision)', () => {
145
150
  });
146
151
 
147
152
  it('should have previous btn and not next btn', async () => {
148
- render(<StockOperationForm stockOperationType={receiptOperationTypeMock as any} />);
153
+ render(
154
+ <StockOperationForm
155
+ stockOperationType={receiptOperationTypeMock as any}
156
+ closeWorkspace={jest.fn()}
157
+ setTitle={jest.fn()}
158
+ closeWorkspaceWithSavedChanges={jest.fn()}
159
+ promptBeforeClosing={jest.fn()}
160
+ />,
161
+ );
149
162
  // MOVE TO STEP 2
150
163
  await userEvent.click(screen.getByRole('button', { name: /Next/i }));
151
164
  // MOVE TO STEP3
152
165
  await userEvent.click(screen.getByRole('button', { name: /Next/i }));
153
166
 
154
167
  expect(screen.queryByRole('button', { name: /Next/i })).not.toBeInTheDocument();
155
- expect(screen.getByRole('button', { name: /previous/i })).toBeInTheDocument();
168
+ expect(screen.getByTestId('previous-btn')).toBeInTheDocument();
156
169
  });
157
170
 
158
171
  it('should render require approval radio button and save button', async () => {
159
- render(<StockOperationForm stockOperationType={receiptOperationTypeMock as any} />);
172
+ render(
173
+ <StockOperationForm
174
+ stockOperationType={receiptOperationTypeMock as any}
175
+ closeWorkspace={jest.fn()}
176
+ setTitle={jest.fn()}
177
+ closeWorkspaceWithSavedChanges={jest.fn()}
178
+ promptBeforeClosing={jest.fn()}
179
+ />,
180
+ );
160
181
  // MOVE TO STEP 2
161
182
  await userEvent.click(screen.getByRole('button', { name: /Next/i }));
162
183
  // MOVE TO STEP3
@@ -167,7 +188,15 @@ describe('Stock Operation form step 3 (stock submision)', () => {
167
188
  expect(screen.getAllByRole('radio', { name: /yes|no/i })).toHaveLength(2);
168
189
  });
169
190
  it('should render submitForReview button when require aprroval radion button is checked yes', async () => {
170
- render(<StockOperationForm stockOperationType={receiptOperationTypeMock as any} />);
191
+ render(
192
+ <StockOperationForm
193
+ stockOperationType={receiptOperationTypeMock as any}
194
+ closeWorkspace={jest.fn()}
195
+ setTitle={jest.fn()}
196
+ closeWorkspaceWithSavedChanges={jest.fn()}
197
+ promptBeforeClosing={jest.fn()}
198
+ />,
199
+ );
171
200
  // MOVE TO STEP 2
172
201
  await userEvent.click(screen.getByRole('button', { name: /Next/i }));
173
202
  // MOVE TO STEP3
@@ -182,7 +211,15 @@ describe('Stock Operation form step 3 (stock submision)', () => {
182
211
  expect(screen.getByRole('button', { name: /submitForReview/i })).toBeInTheDocument();
183
212
  });
184
213
  it('should render complete button when require aprroval radion button is checked no', async () => {
185
- render(<StockOperationForm stockOperationType={receiptOperationTypeMock as any} />);
214
+ render(
215
+ <StockOperationForm
216
+ stockOperationType={receiptOperationTypeMock as any}
217
+ closeWorkspace={jest.fn()}
218
+ setTitle={jest.fn()}
219
+ closeWorkspaceWithSavedChanges={jest.fn()}
220
+ promptBeforeClosing={jest.fn()}
221
+ />,
222
+ );
186
223
  // MOVE TO STEP 2
187
224
  await userEvent.click(screen.getByRole('button', { name: /Next/i }));
188
225
  // MOVE TO STEP3
@@ -192,10 +229,18 @@ describe('Stock Operation form step 3 (stock submision)', () => {
192
229
  expect(noRadioButton).toBeInTheDocument();
193
230
  await userEvent.click(noRadioButton);
194
231
  // On require aprooval should now show complete btn
195
- expect(screen.getByRole('button', { name: /complete/i })).toBeInTheDocument();
232
+ expect(screen.getByTestId('complete-button')).toBeInTheDocument();
196
233
  });
197
234
  it('should render dispatch btn for stock return operation and dont require aproval', async () => {
198
- render(<StockOperationForm stockOperationType={returnOperationTypeMock as any} />);
235
+ render(
236
+ <StockOperationForm
237
+ stockOperationType={returnOperationTypeMock as any}
238
+ closeWorkspace={jest.fn()}
239
+ setTitle={jest.fn()}
240
+ closeWorkspaceWithSavedChanges={jest.fn()}
241
+ promptBeforeClosing={jest.fn()}
242
+ />,
243
+ );
199
244
  // MOVE TO STEP 2
200
245
  await userEvent.click(screen.getByRole('button', { name: /Next/i }));
201
246
  // MOVE TO STEP3
@@ -205,10 +250,18 @@ describe('Stock Operation form step 3 (stock submision)', () => {
205
250
  expect(noRadioButton).toBeInTheDocument();
206
251
  await userEvent.click(noRadioButton);
207
252
  // On require aprooval should now show complete btn
208
- expect(screen.getByRole('button', { name: /dispatch/i })).toBeInTheDocument();
253
+ expect(screen.getByTestId('dipatch-button')).toBeInTheDocument();
209
254
  });
210
255
  it('should render dispatch btn for stock issue operation and dont require aproval', async () => {
211
- render(<StockOperationForm stockOperationType={stockIssueOperationtypeMock as any} />);
256
+ render(
257
+ <StockOperationForm
258
+ stockOperationType={stockIssueOperationtypeMock as any}
259
+ closeWorkspace={jest.fn()}
260
+ setTitle={jest.fn()}
261
+ closeWorkspaceWithSavedChanges={jest.fn()}
262
+ promptBeforeClosing={jest.fn()}
263
+ />,
264
+ );
212
265
  // MOVE TO STEP 2
213
266
  await userEvent.click(screen.getByRole('button', { name: /Next/i }));
214
267
  // MOVE TO STEP3
@@ -218,6 +271,6 @@ describe('Stock Operation form step 3 (stock submision)', () => {
218
271
  expect(noRadioButton).toBeInTheDocument();
219
272
  await userEvent.click(noRadioButton);
220
273
  // On require aprooval should now show complete btn
221
- expect(screen.getByRole('button', { name: /dispatch/i })).toBeInTheDocument();
274
+ expect(screen.getByTestId('dipatch-button')).toBeInTheDocument();
222
275
  });
223
276
  });
@@ -1,7 +1,7 @@
1
1
  import { Button, Column, ComboBox, DatePicker, DatePickerInput, InlineLoading, Stack, TextArea } from '@carbon/react';
2
2
  import { ErrorState } from '@openmrs/esm-framework';
3
3
  import React, { ChangeEvent, FC, useEffect, useMemo } from 'react';
4
- import { Controller, useFormContext } from 'react-hook-form';
4
+ import { Controller, useFormContext, useFormState } from 'react-hook-form';
5
5
  import { useTranslation } from 'react-i18next';
6
6
  import { DATE_PICKER_CONTROL_FORMAT, DATE_PICKER_FORMAT, MAIN_STORE_LOCATION_TAG } from '../../../constants';
7
7
  import { Party } from '../../../core/api/types/Party';
@@ -14,6 +14,7 @@ import StockOperationReasonSelector from '../input-components/stock-operation-re
14
14
  import UsersSelector from '../input-components/users-selector.component';
15
15
  import styles from '../stock-operation-form.scss';
16
16
  import { TextInput } from '@carbon/react';
17
+ import { ArrowRight } from '@carbon/react/icons';
17
18
 
18
19
  type BaseOperationDetailsFormStepProps = {
19
20
  stockOperation?: StockOperationDTO;
@@ -41,10 +42,11 @@ const BaseOperationDetailsFormStep: FC<BaseOperationDetailsFormStepProps> = ({
41
42
  () => OperationType.STOCK_ISSUE_OPERATION_TYPE === stockOperationType.operationType,
42
43
  [stockOperationType],
43
44
  );
45
+
44
46
  // initialize location fields
45
47
  useEffect(() => {
46
48
  // Prefill default locaton with current location if is a new operation
47
- if (!stockOperation) {
49
+ if (!stockOperation && stockOperationType.operationType !== OperationType.STOCK_ISSUE_OPERATION_TYPE) {
48
50
  if (stockOperationType?.hasSource) {
49
51
  const shouldLockSource = sourceTags.length === 1 && sourceTags[0] === MAIN_STORE_LOCATION_TAG;
50
52
  if (shouldLockSource && sourceParties?.length) {
@@ -82,13 +84,6 @@ const BaseOperationDetailsFormStep: FC<BaseOperationDetailsFormStepProps> = ({
82
84
  <Stack gap={4} className={styles.grid}>
83
85
  <div className={styles.heading}>
84
86
  <h4>{`${stockOperationType.name} ${t('details', 'Details')}`}</h4>
85
- <div className={styles.btnSet}>
86
- {typeof onNext === 'function' && (
87
- <Button kind="primary" onClick={onNext} role="button">
88
- {t('next', 'Next')}
89
- </Button>
90
- )}
91
- </div>
92
87
  </div>
93
88
  <Column>
94
89
  <Controller
@@ -234,6 +229,13 @@ const BaseOperationDetailsFormStep: FC<BaseOperationDetailsFormStepProps> = ({
234
229
  )}
235
230
  />
236
231
  </Column>
232
+ <div className={styles.btnSet}>
233
+ {typeof onNext === 'function' && (
234
+ <Button kind="primary" onClick={onNext} role="button" renderIcon={ArrowRight}>
235
+ {t('next', 'Next')}
236
+ </Button>
237
+ )}
238
+ </div>
237
239
  </Stack>
238
240
  );
239
241
  };