mirror of
				https://github.com/inventree/inventree-app.git
				synced 2025-10-31 05:15:42 +00:00 
			
		
		
		
	Stock location scan (#169)
* Add action for scanning a stock location into another location * Adds barcode scan handler for new functionality * Handle scanning of stock location * Cleanup * Refactor existing barcode scanning functions - Will require extensive testing and validation * Add entry to release notes * Delete dead code * Improved ordering based on stock quantity * Bug fix for 'adjustStock' function * Improve error responses for barcode scanning * Improve error responses for barcode scanning * Remove old debug statements * Add some extra explanatory texts * Icon change * Fixes for unit tests * Adds extra functionality for user profile manager * Refactor barcode code - do not rely on BuildContext * Adds initial unit testing for barcode scanning - Work on mocking barcode data - Add hooks for testing snackBar and audio files * Linting fixes * More barcode unit tests * Cleanup unit tests for barcode * Remove unused import * Handle HTTPException in API * Improvements for API unit testing * Unit testing for scanning item into location * Add unit test for scanning in items from a location context * Unit test for scanning location into parent location * Improve feedback for barcode scanning events
This commit is contained in:
		| @@ -5,6 +5,7 @@ | ||||
| import "package:test/test.dart"; | ||||
|  | ||||
| import "package:inventree/api.dart"; | ||||
| import "package:inventree/helpers.dart"; | ||||
| import "package:inventree/user_profile.dart"; | ||||
|  | ||||
|  | ||||
| @@ -94,6 +95,9 @@ void main() { | ||||
|  | ||||
|         assert(!api.checkConnection()); | ||||
|  | ||||
|         debugContains("Token request failed: STATUS 401"); | ||||
|         debugContains("showSnackIcon: 'Not Connected'"); | ||||
|  | ||||
|       } else { | ||||
|         assert(false); | ||||
|       } | ||||
| @@ -137,6 +141,9 @@ void main() { | ||||
|       assert(api.checkPermission("stocklocation", "delete")); | ||||
|       assert(!api.checkPermission("part", "weirdpermission")); | ||||
|       assert(api.checkPermission("blah", "bloo")); | ||||
|  | ||||
|       debugContains("Received token from server"); | ||||
|       debugContains("showSnackIcon: 'Connected to Server'"); | ||||
|     }); | ||||
|  | ||||
|   }); | ||||
|   | ||||
							
								
								
									
										160
									
								
								test/barcode_test.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										160
									
								
								test/barcode_test.dart
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,160 @@ | ||||
| /* | ||||
|  * Unit testing for barcode scanning functionality. | ||||
|  * | ||||
|  * As the unit testing framework cannot really "scan" barcode data, | ||||
|  * we will mock the scanned data by passing raw "barcode" data to the scanning framework. | ||||
|  */ | ||||
|  | ||||
| import "package:flutter_test/flutter_test.dart"; | ||||
|  | ||||
| import "package:inventree/api.dart"; | ||||
| import "package:inventree/barcode.dart"; | ||||
| import "package:inventree/helpers.dart"; | ||||
| import "package:inventree/user_profile.dart"; | ||||
|  | ||||
| import "package:inventree/inventree/stock.dart"; | ||||
|  | ||||
| void main() { | ||||
|  | ||||
|   // Connect to the server | ||||
|   setUpAll(() async { | ||||
|     final prf = await UserProfileDBManager().getProfileByName("Test Profile"); | ||||
|  | ||||
|     if (prf != null) { | ||||
|       UserProfileDBManager().deleteProfile(prf); | ||||
|     } | ||||
|  | ||||
|     bool result = await UserProfileDBManager().addProfile( | ||||
|       UserProfile( | ||||
|         name: "Test Profile", | ||||
|         server: "http://localhost:12345", | ||||
|         username: "testuser", | ||||
|         password: "testpassword", | ||||
|         selected: true, | ||||
|       ), | ||||
|     ); | ||||
|  | ||||
|     assert(result); | ||||
|  | ||||
|     assert(await UserProfileDBManager().selectProfileByName("Test Profile")); | ||||
|     assert(await InvenTreeAPI().connectToServer()); | ||||
|   }); | ||||
|  | ||||
|   setUp(() async { | ||||
|     // Clear the debug log | ||||
|     clearDebugMessage(); | ||||
|   }); | ||||
|  | ||||
|   group("Test BarcodeScanHandler:", () { | ||||
|     // Tests for scanning a "generic" barcode | ||||
|  | ||||
|     var handler = BarcodeScanHandler(); | ||||
|  | ||||
|     test("Empty Barcode", () async { | ||||
|       // Handle an 'empty' barcode | ||||
|       await handler.processBarcode(null, ""); | ||||
|  | ||||
|       debugContains("Scanned barcode data: ''"); | ||||
|       debugContains("showSnackIcon: 'Barcode scan error'"); | ||||
|  | ||||
|       assert(debugMessageCount() == 2); | ||||
|     }); | ||||
|  | ||||
|     test("Junk Data", () async { | ||||
|       // test scanning 'junk' data | ||||
|  | ||||
|       await handler.processBarcode(null, "abcdefg"); | ||||
|  | ||||
|       debugContains("Scanned barcode data: 'abcdefg'"); | ||||
|       debugContains("showSnackIcon: 'No match for barcode'"); | ||||
|     }); | ||||
|  | ||||
|     test("Invalid StockLocation", () async { | ||||
|       // Scan an invalid stock location | ||||
|       await handler.processBarcode(null, '{"stocklocation": 999999}'); | ||||
|  | ||||
|       debugContains("Scanned barcode data: '{\"stocklocation\": 999999}'"); | ||||
|       debugContains("showSnackIcon: 'No match for barcode'"); | ||||
|       assert(debugMessageCount() == 2); | ||||
|     }); | ||||
|  | ||||
|   }); | ||||
|  | ||||
|   group("Test StockItemScanIntoLocationHandler:", () { | ||||
|     // Tests for scanning a stock item into a location | ||||
|  | ||||
|     test("Scan Into Location", () async { | ||||
|  | ||||
|       final item = await InvenTreeStockItem().get(1) as InvenTreeStockItem?; | ||||
|  | ||||
|       assert(item != null); | ||||
|       assert(item!.pk == 1); | ||||
|  | ||||
|       var handler = StockItemScanIntoLocationHandler(item!); | ||||
|  | ||||
|       await handler.processBarcode(null, '{"stocklocation": 7}'); | ||||
|       // Check the location has been updated | ||||
|       await item.reload(); | ||||
|       assert(item.locationId == 7); | ||||
|  | ||||
|       debugContains("Scanned stock location 7"); | ||||
|  | ||||
|       // Scan into a new location | ||||
|       await handler.processBarcode(null, '{"stocklocation": 1}'); | ||||
|       await item.reload(); | ||||
|       assert(item.locationId == 1); | ||||
|  | ||||
|     }); | ||||
|   }); | ||||
|  | ||||
|   group("Test StockLocationScanInItemsHandler:", () { | ||||
|     // Tests for scanning items into a stock location | ||||
|  | ||||
|     test("Scan In Items", () async { | ||||
|       final location = await InvenTreeStockLocation().get(1) as InvenTreeStockLocation?; | ||||
|  | ||||
|       assert(location != null); | ||||
|       assert(location!.pk == 1); | ||||
|  | ||||
|       var handler = StockLocationScanInItemsHandler(location!); | ||||
|  | ||||
|       // Scan multiple items into this location | ||||
|       for (int id in [1, 2, 11]) { | ||||
|         await handler.processBarcode(null, '{"stockitem": ${id}}'); | ||||
|  | ||||
|         var item = await InvenTreeStockItem().get(id) as InvenTreeStockItem?; | ||||
|  | ||||
|         assert(item != null); | ||||
|         assert(item!.pk == id); | ||||
|         assert(item!.locationId == 1); | ||||
|       } | ||||
|  | ||||
|     }); | ||||
|   }); | ||||
|  | ||||
|   group("Test ScanParentLocationHandler:", () { | ||||
|     // Tests for scanning a location into a parent location | ||||
|  | ||||
|     test("Scan Parent", () async { | ||||
|       final location = await InvenTreeStockLocation().get(7) as InvenTreeStockLocation?; | ||||
|  | ||||
|       assert(location != null); | ||||
|       assert(location!.pk == 7); | ||||
|       assert(location!.parentId == 4); | ||||
|  | ||||
|       var handler = ScanParentLocationHandler(location!); | ||||
|  | ||||
|       // Scan into new parent location | ||||
|       await handler.processBarcode(null, '{"stocklocation": 1}'); | ||||
|       await location.reload(); | ||||
|       assert(location.parentId == 1); | ||||
|  | ||||
|       // Scan back into old parent location | ||||
|       await handler.processBarcode(null, '{"stocklocation": 4}'); | ||||
|       await location.reload(); | ||||
|       assert(location.parentId == 4); | ||||
|  | ||||
|       debugContains("showSnackIcon: 'Scanned into location'"); | ||||
|     }); | ||||
|   }); | ||||
| } | ||||
| @@ -2,11 +2,11 @@ | ||||
|  * Unit tests for accessing various model classes via the API | ||||
|  */ | ||||
|  | ||||
| import "package:inventree/inventree/model.dart"; | ||||
| import "package:test/test.dart"; | ||||
|  | ||||
| import "package:inventree/api.dart"; | ||||
| import "package:inventree/user_profile.dart"; | ||||
| import "package:inventree/inventree/model.dart"; | ||||
| import "package:inventree/inventree/part.dart"; | ||||
|  | ||||
|  | ||||
| @@ -112,32 +112,40 @@ void main() { | ||||
|       assert(result != null); | ||||
|       assert(result is InvenTreePart); | ||||
|  | ||||
|       APIResponse? response; | ||||
|  | ||||
|       if (result != null) { | ||||
|         InvenTreePart part = result as InvenTreePart; | ||||
|         assert(part.name == "M2x4 LPHS"); | ||||
|  | ||||
|         // Change the name to something else | ||||
|         assert(await part.update( | ||||
|  | ||||
|         response = await part.update( | ||||
|           values: { | ||||
|             "name": "Woogle", | ||||
|           } | ||||
|         )); | ||||
|         ); | ||||
|  | ||||
|         assert(response.isValid()); | ||||
|         assert(response.statusCode == 200); | ||||
|  | ||||
|         assert(await part.reload()); | ||||
|         assert(part.name == "Woogle"); | ||||
|  | ||||
|         // And change it back again | ||||
|         assert(await part.update( | ||||
|         response = await part.update( | ||||
|           values: { | ||||
|             "name": "M2x4 LPHS" | ||||
|           } | ||||
|         )); | ||||
|         ); | ||||
|  | ||||
|         assert(response.isValid()); | ||||
|         assert(response.statusCode == 200); | ||||
|  | ||||
|         assert(await part.reload()); | ||||
|         assert(part.name == "M2x4 LPHS"); | ||||
|       } | ||||
|     }); | ||||
|  | ||||
|   }); | ||||
|  | ||||
| } | ||||
		Reference in New Issue
	
	Block a user