mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-31 13:15:43 +00:00 
			
		
		
		
	[Refactor] Serial generation (#8246)
* Refactor "update_serial_number" method * Refactor serial number validation - Query is much more efficient now - Does not have to check each serial number individually - Makes use of existing Part class method * Refactor creation of multiple stock items * Fix for singular item creation * Refactor serializeStock method: - Push "rebuild tree" to background worker - Use bulk_create actions * Refactor createion of serialized build outputs * Prevent 1+N DB hits * Cleanup * Cleanup * Reinstate serial number checks * Add limit for serial number extraction * Fix cache config * Revert cache settings * Fix for unit tests * Playwright tests * Bug fix * Force False cookie mode in testing * Revert aria-label for PanelGroup items - No longer works as expected with playwright locators * Fix playwright vtest * Further updates * Playwright test adjustments * Remove duplicate locator
This commit is contained in:
		| @@ -5,7 +5,7 @@ test('Modals as admin', async ({ page }) => { | ||||
|   await doQuickLogin(page, 'admin', 'inventree'); | ||||
|  | ||||
|   // use server info | ||||
|   await page.getByRole('button', { name: 'Open spotlight' }).click(); | ||||
|   await page.getByLabel('open-spotlight').click(); | ||||
|   await page | ||||
|     .getByRole('button', { | ||||
|       name: 'Server Information About this Inventree instance' | ||||
| @@ -17,7 +17,7 @@ test('Modals as admin', async ({ page }) => { | ||||
|   await page.waitForURL('**/platform/home'); | ||||
|  | ||||
|   // use license info | ||||
|   await page.getByRole('button', { name: 'Open spotlight' }).click(); | ||||
|   await page.getByLabel('open-spotlight').click(); | ||||
|   await page | ||||
|     .getByRole('button', { | ||||
|       name: 'License Information Licenses for dependencies of the service' | ||||
| @@ -44,7 +44,7 @@ test('Modals as admin', async ({ page }) => { | ||||
|     .click(); | ||||
|  | ||||
|   // use about | ||||
|   await page.getByRole('button', { name: 'Open spotlight' }).click(); | ||||
|   await page.getByLabel('open-spotlight').click(); | ||||
|   await page | ||||
|     .getByRole('button', { name: 'About InvenTree About the InvenTree org' }) | ||||
|     .click(); | ||||
|   | ||||
| @@ -178,3 +178,53 @@ test('Purchase Orders - Barcodes', async ({ page }) => { | ||||
|   await page.waitForTimeout(500); | ||||
|   await page.getByRole('button', { name: 'Issue Order' }).waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Purchase Orders - General', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|  | ||||
|   await page.getByRole('tab', { name: 'Purchasing' }).click(); | ||||
|   await page.getByRole('cell', { name: 'PO0012' }).click(); | ||||
|   await page.waitForTimeout(200); | ||||
|  | ||||
|   await page.getByRole('tab', { name: 'Line Items' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Received Stock' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Attachments' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Purchasing' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Suppliers' }).click(); | ||||
|   await page.getByText('Arrow', { exact: true }).click(); | ||||
|   await page.waitForTimeout(200); | ||||
|  | ||||
|   await page.getByRole('tab', { name: 'Supplied Parts' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Purchase Orders' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Stock Items' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Contacts' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Addresses' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Attachments' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Purchasing' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Manufacturers' }).click(); | ||||
|   await page.getByText('AVX Corporation').click(); | ||||
|   await page.waitForTimeout(200); | ||||
|  | ||||
|   await page.getByRole('tab', { name: 'Addresses' }).click(); | ||||
|   await page.getByRole('cell', { name: 'West Branch' }).click(); | ||||
|   await page.locator('.mantine-ScrollArea-root').click(); | ||||
|   await page | ||||
|     .getByRole('row', { name: 'West Branch Yes Surf Avenue 9' }) | ||||
|     .getByRole('button') | ||||
|     .click(); | ||||
|   await page.getByRole('menuitem', { name: 'Edit' }).click(); | ||||
|  | ||||
|   await page.getByLabel('text-field-title').waitFor(); | ||||
|   await page.getByLabel('text-field-line2').waitFor(); | ||||
|  | ||||
|   // Read the current value of the cell, to ensure we always *change* it! | ||||
|   const value = await page.getByLabel('text-field-line2').inputValue(); | ||||
|   await page | ||||
|     .getByLabel('text-field-line2') | ||||
|     .fill(value == 'old' ? 'new' : 'old'); | ||||
|  | ||||
|   await page.getByRole('button', { name: 'Submit' }).isEnabled(); | ||||
|  | ||||
|   await page.getByRole('button', { name: 'Submit' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Details' }).waitFor(); | ||||
| }); | ||||
|   | ||||
							
								
								
									
										104
									
								
								src/frontend/tests/pages/pui_stock.spec.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								src/frontend/tests/pages/pui_stock.spec.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,104 @@ | ||||
| import { test } from '../baseFixtures.js'; | ||||
| import { baseUrl } from '../defaults.js'; | ||||
| import { doQuickLogin } from '../login.js'; | ||||
|  | ||||
| test('Stock', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|  | ||||
|   await page.goto(`${baseUrl}/stock/location/index/`); | ||||
|   await page.waitForURL('**/platform/stock/location/**'); | ||||
|  | ||||
|   await page.getByRole('tab', { name: 'Location Details' }).click(); | ||||
|   await page.waitForURL('**/platform/stock/location/index/details'); | ||||
|  | ||||
|   await page.getByRole('tab', { name: 'Stock Items' }).click(); | ||||
|   await page.getByText('1551ABK').first().click(); | ||||
|  | ||||
|   await page.getByRole('tab', { name: 'Stock', exact: true }).click(); | ||||
|   await page.waitForURL('**/platform/stock/**'); | ||||
|   await page.getByRole('tab', { name: 'Stock Locations' }).click(); | ||||
|   await page.getByRole('cell', { name: 'Electronics Lab' }).first().click(); | ||||
|   await page.getByRole('tab', { name: 'Default Parts' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Stock Locations' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Stock Items' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Location Details' }).click(); | ||||
|  | ||||
|   await page.goto(`${baseUrl}/stock/item/1194/details`); | ||||
|   await page.getByText('D.123 | Doohickey').waitFor(); | ||||
|   await page.getByText('Batch Code: BX-123-2024-2-7').waitFor(); | ||||
|   await page.getByRole('tab', { name: 'Stock Tracking' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Test Data' }).click(); | ||||
|   await page.getByText('395c6d5586e5fb656901d047be27e1f7').waitFor(); | ||||
|   await page.getByRole('tab', { name: 'Installed Items' }).click(); | ||||
| }); | ||||
|  | ||||
| test('Stock - Location Tree', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|  | ||||
|   await page.goto(`${baseUrl}/stock/location/index/`); | ||||
|   await page.waitForURL('**/platform/stock/location/**'); | ||||
|   await page.getByRole('tab', { name: 'Location Details' }).click(); | ||||
|  | ||||
|   await page.getByLabel('nav-breadcrumb-action').click(); | ||||
|   await page.getByLabel('nav-tree-toggle-1}').click(); | ||||
|   await page.getByLabel('nav-tree-item-2').click(); | ||||
|  | ||||
|   await page.getByLabel('breadcrumb-2-storage-room-a').waitFor(); | ||||
|   await page.getByLabel('breadcrumb-1-factory').click(); | ||||
|  | ||||
|   await page.getByRole('cell', { name: 'Factory' }).first().waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Stock - Serial Numbers', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|  | ||||
|   // Use the "global search" functionality to find a part we are interested in | ||||
|   // This is to exercise the search functionality and ensure it is working as expected | ||||
|   await page.getByLabel('open-search').click(); | ||||
|  | ||||
|   await page.getByLabel('global-search-input').clear(); | ||||
|   await page.getByLabel('global-search-input').fill('widget green'); | ||||
|  | ||||
|   // Remove the "stock item" results group | ||||
|   await page.getByLabel('remove-search-group-stockitem').click(); | ||||
|  | ||||
|   await page | ||||
|     .getByText(/widget\.green/) | ||||
|     .first() | ||||
|     .click(); | ||||
|  | ||||
|   await page | ||||
|     .getByLabel('panel-tabs-part') | ||||
|     .getByRole('tab', { name: 'Stock', exact: true }) | ||||
|     .click(); | ||||
|   await page.getByLabel('action-button-add-stock-item').click(); | ||||
|  | ||||
|   // Initially fill with invalid serial/quantity combinations | ||||
|   await page.getByLabel('text-field-serial_numbers').fill('200-250'); | ||||
|   await page.getByLabel('number-field-quantity').fill('10'); | ||||
|  | ||||
|   await page.getByRole('button', { name: 'Submit' }).click(); | ||||
|  | ||||
|   // Expected error messages | ||||
|   await page.getByText('Errors exist for one or more form fields').waitFor(); | ||||
|   await page | ||||
|     .getByText(/exceeds allowed quantity/) | ||||
|     .first() | ||||
|     .waitFor(); | ||||
|  | ||||
|   // Now, with correct quantity | ||||
|   await page.getByLabel('number-field-quantity').fill('51'); | ||||
|   await page.getByRole('button', { name: 'Submit' }).click(); | ||||
|   await page | ||||
|     .getByText( | ||||
|       /The following serial numbers already exist or are invalid : 200,201,202,203,204/ | ||||
|     ) | ||||
|     .first() | ||||
|     .waitFor(); | ||||
|  | ||||
|   // Expected error messages | ||||
|   await page.getByText('Errors exist for one or more form fields').waitFor(); | ||||
|  | ||||
|   // Close the form | ||||
|   await page.getByRole('button', { name: 'Cancel' }).click(); | ||||
| }); | ||||
| @@ -15,7 +15,7 @@ test('Quick Command', async ({ page }) => { | ||||
|   await page.waitForURL('**/platform/dashboard'); | ||||
|  | ||||
|   // Open Spotlight with Button | ||||
|   await page.getByRole('button', { name: 'Open spotlight' }).click(); | ||||
|   await page.getByLabel('open-spotlight').click(); | ||||
|   await page.getByRole('button', { name: 'Home Go to the home page' }).click(); | ||||
|   await page | ||||
|     .getByRole('heading', { name: 'Welcome to your Dashboard,' }) | ||||
| @@ -35,7 +35,7 @@ test('Quick Command - No Keys', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|  | ||||
|   // Open Spotlight with Button | ||||
|   await page.getByRole('button', { name: 'Open spotlight' }).click(); | ||||
|   await page.getByLabel('open-spotlight').click(); | ||||
|   await page.getByRole('button', { name: 'Home Go to the home page' }).click(); | ||||
|   await page | ||||
|     .getByRole('heading', { name: 'Welcome to your Dashboard,' }) | ||||
| @@ -43,7 +43,7 @@ test('Quick Command - No Keys', async ({ page }) => { | ||||
|   await page.waitForURL('**/platform'); | ||||
|  | ||||
|   // Use navigation menu | ||||
|   await page.getByRole('button', { name: 'Open spotlight' }).click(); | ||||
|   await page.getByLabel('open-spotlight').click(); | ||||
|   await page | ||||
|     .getByRole('button', { name: 'Open Navigation Open the main' }) | ||||
|     .click(); | ||||
| @@ -56,7 +56,7 @@ test('Quick Command - No Keys', async ({ page }) => { | ||||
|   await page.keyboard.press('Escape'); | ||||
|  | ||||
|   // use server info | ||||
|   await page.getByRole('button', { name: 'Open spotlight' }).click(); | ||||
|   await page.getByLabel('open-spotlight').click(); | ||||
|   await page | ||||
|     .getByRole('button', { | ||||
|       name: 'Server Information About this Inventree instance' | ||||
| @@ -68,7 +68,7 @@ test('Quick Command - No Keys', async ({ page }) => { | ||||
|   await page.waitForURL('**/platform'); | ||||
|  | ||||
|   // use license info | ||||
|   await page.getByRole('button', { name: 'Open spotlight' }).click(); | ||||
|   await page.getByLabel('open-spotlight').click(); | ||||
|   await page | ||||
|     .getByRole('button', { | ||||
|       name: 'License Information Licenses for dependencies of the service' | ||||
| @@ -80,7 +80,7 @@ test('Quick Command - No Keys', async ({ page }) => { | ||||
|   await page.getByLabel('License Information').getByRole('button').click(); | ||||
|  | ||||
|   // use about | ||||
|   await page.getByRole('button', { name: 'Open spotlight' }).click(); | ||||
|   await page.getByLabel('open-spotlight').click(); | ||||
|   await page | ||||
|     .getByRole('button', { name: 'About InvenTree About the InvenTree org' }) | ||||
|     .click(); | ||||
| @@ -89,7 +89,7 @@ test('Quick Command - No Keys', async ({ page }) => { | ||||
|   await page.getByLabel('About InvenTree').getByRole('button').click(); | ||||
|  | ||||
|   // use documentation | ||||
|   await page.getByRole('button', { name: 'Open spotlight' }).click(); | ||||
|   await page.getByLabel('open-spotlight').click(); | ||||
|   await page | ||||
|     .getByRole('button', { | ||||
|       name: 'Documentation Visit the documentation to learn more about InvenTree' | ||||
| @@ -105,7 +105,7 @@ test('Quick Command - No Keys', async ({ page }) => { | ||||
|   /* | ||||
|   await page.getByPlaceholder('Search...').fill('secret'); | ||||
|   await page.getByRole('button', { name: 'Secret action It was' }).click(); | ||||
|   await page.getByRole('button', { name: 'Open spotlight' }).click(); | ||||
|   await page.getByLabel('open-spotlight').click(); | ||||
|   await page.getByPlaceholder('Search...').fill('Another secret action'); | ||||
|   await page | ||||
|     .getByRole('button', { | ||||
| @@ -113,7 +113,7 @@ test('Quick Command - No Keys', async ({ page }) => { | ||||
|     }) | ||||
|     .click(); | ||||
|   await page.getByRole('tab', { name: 'Home' }).click(); | ||||
|   await page.getByRole('button', { name: 'Open spotlight' }).click(); | ||||
|   await page.getByLabel('open-spotlight').click(); | ||||
|   */ | ||||
|   await page.getByPlaceholder('Search...').fill('secret'); | ||||
|   await page.getByText('Nothing found...').click(); | ||||
|   | ||||
| @@ -1,100 +0,0 @@ | ||||
| import { test } from './baseFixtures.js'; | ||||
| import { baseUrl } from './defaults.js'; | ||||
| import { doQuickLogin } from './login.js'; | ||||
|  | ||||
| test('Stock', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|  | ||||
|   await page.goto(`${baseUrl}/stock/location/index/`); | ||||
|   await page.waitForURL('**/platform/stock/location/**'); | ||||
|  | ||||
|   await page.getByRole('tab', { name: 'Location Details' }).click(); | ||||
|   await page.waitForURL('**/platform/stock/location/index/details'); | ||||
|  | ||||
|   await page.getByRole('tab', { name: 'Stock Items' }).click(); | ||||
|   await page.getByText('1551ABK').first().click(); | ||||
|  | ||||
|   await page.getByRole('tab', { name: 'Stock', exact: true }).click(); | ||||
|   await page.waitForURL('**/platform/stock/**'); | ||||
|   await page.getByRole('tab', { name: 'Stock Locations' }).click(); | ||||
|   await page.getByRole('cell', { name: 'Electronics Lab' }).first().click(); | ||||
|   await page.getByRole('tab', { name: 'Default Parts' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Stock Locations' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Stock Items' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Location Details' }).click(); | ||||
|  | ||||
|   await page.goto(`${baseUrl}/stock/item/1194/details`); | ||||
|   await page.getByText('D.123 | Doohickey').waitFor(); | ||||
|   await page.getByText('Batch Code: BX-123-2024-2-7').waitFor(); | ||||
|   await page.getByRole('tab', { name: 'Stock Tracking' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Test Data' }).click(); | ||||
|   await page.getByText('395c6d5586e5fb656901d047be27e1f7').waitFor(); | ||||
|   await page.getByRole('tab', { name: 'Installed Items' }).click(); | ||||
| }); | ||||
|  | ||||
| test('Purchasing', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|  | ||||
|   await page.getByRole('tab', { name: 'Purchasing' }).click(); | ||||
|   await page.getByRole('cell', { name: 'PO0012' }).click(); | ||||
|   await page.waitForTimeout(200); | ||||
|  | ||||
|   await page.getByRole('tab', { name: 'Line Items' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Received Stock' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Attachments' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Purchasing' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Suppliers' }).click(); | ||||
|   await page.getByText('Arrow', { exact: true }).click(); | ||||
|   await page.waitForTimeout(200); | ||||
|  | ||||
|   await page.getByRole('tab', { name: 'Supplied Parts' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Purchase Orders' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Stock Items' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Contacts' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Addresses' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Attachments' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Purchasing' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Manufacturers' }).click(); | ||||
|   await page.getByText('AVX Corporation').click(); | ||||
|   await page.waitForTimeout(200); | ||||
|  | ||||
|   await page.getByRole('tab', { name: 'Addresses' }).click(); | ||||
|   await page.getByRole('cell', { name: 'West Branch' }).click(); | ||||
|   await page.locator('.mantine-ScrollArea-root').click(); | ||||
|   await page | ||||
|     .getByRole('row', { name: 'West Branch Yes Surf Avenue 9' }) | ||||
|     .getByRole('button') | ||||
|     .click(); | ||||
|   await page.getByRole('menuitem', { name: 'Edit' }).click(); | ||||
|  | ||||
|   await page.getByLabel('text-field-title').waitFor(); | ||||
|   await page.getByLabel('text-field-line2').waitFor(); | ||||
|  | ||||
|   // Read the current value of the cell, to ensure we always *change* it! | ||||
|   const value = await page.getByLabel('text-field-line2').inputValue(); | ||||
|   await page | ||||
|     .getByLabel('text-field-line2') | ||||
|     .fill(value == 'old' ? 'new' : 'old'); | ||||
|  | ||||
|   await page.getByRole('button', { name: 'Submit' }).isEnabled(); | ||||
|  | ||||
|   await page.getByRole('button', { name: 'Submit' }).click(); | ||||
|   await page.getByRole('tab', { name: 'Details' }).waitFor(); | ||||
| }); | ||||
|  | ||||
| test('Stock Location Tree', async ({ page }) => { | ||||
|   await doQuickLogin(page); | ||||
|  | ||||
|   await page.goto(`${baseUrl}/stock/location/index/`); | ||||
|   await page.waitForURL('**/platform/stock/location/**'); | ||||
|   await page.getByRole('tab', { name: 'Location Details' }).click(); | ||||
|  | ||||
|   await page.getByLabel('nav-breadcrumb-action').click(); | ||||
|   await page.getByLabel('nav-tree-toggle-1}').click(); | ||||
|   await page.getByLabel('nav-tree-item-2').click(); | ||||
|  | ||||
|   await page.getByLabel('breadcrumb-2-storage-room-a').waitFor(); | ||||
|   await page.getByLabel('breadcrumb-1-factory').click(); | ||||
|  | ||||
|   await page.getByRole('cell', { name: 'Factory' }).first().waitFor(); | ||||
| }); | ||||
		Reference in New Issue
	
	Block a user