mirror of
https://github.com/inventree/InvenTree.git
synced 2025-12-17 09:48:30 +00:00
Generator updates (#10605)
* Form Field updates: - Allow spec of leftSection prop - Allow spec of rightSection prop * Add ability to auto-fill text input with placeholder value * Simplify stock form * Better serial number placeholders * Update other generator fields * Add default placeholder to DateInput * Enhance TextField * Remove serial_numbers field for non-creation forms * Update playwright tests * Adjust playwright tests * Further playwright adjustments * Fix project code field for build serializer
This commit is contained in:
@@ -34,7 +34,7 @@ test('Build Order - Basic Tests', async ({ browser }) => {
|
||||
|
||||
// Edit the build order (via keyboard shortcut)
|
||||
await page.keyboard.press('Control+E');
|
||||
await page.getByLabel('text-field-title').waitFor();
|
||||
await page.getByLabel('text-field-title', { exact: true }).waitFor();
|
||||
await page.getByLabel('related-field-project_code').waitFor();
|
||||
await page.getByRole('button', { name: 'Cancel' }).click();
|
||||
|
||||
@@ -85,7 +85,9 @@ test('Build Order - Basic Tests', async ({ browser }) => {
|
||||
.getByLabel('add-test-result');
|
||||
|
||||
await button.click();
|
||||
await page.getByRole('textbox', { name: 'text-field-value' }).waitFor();
|
||||
await page
|
||||
.getByRole('textbox', { name: 'text-field-value', exact: true })
|
||||
.waitFor();
|
||||
await page.getByRole('button', { name: 'Cancel' }).click();
|
||||
|
||||
// Click through to the "parent" build
|
||||
@@ -189,22 +191,27 @@ test('Build Order - Build Outputs', async ({ browser }) => {
|
||||
await page.getByLabel('action-button-add-build-output').click();
|
||||
await page.getByLabel('number-field-quantity').fill('5');
|
||||
|
||||
const placeholder = await page
|
||||
.getByLabel('text-field-serial_numbers')
|
||||
.getAttribute('placeholder');
|
||||
const placeholder: string =
|
||||
(await page
|
||||
.getByLabel('text-field-serial_numbers', { exact: true })
|
||||
.getAttribute('placeholder')) || '';
|
||||
|
||||
expect(placeholder).toContain('Next serial number');
|
||||
expect(placeholder).toContain('+');
|
||||
|
||||
let sn = 1;
|
||||
|
||||
if (!!placeholder && placeholder.includes('Next serial number')) {
|
||||
sn = Number.parseInt(placeholder.split(':')[1].trim());
|
||||
}
|
||||
sn = Number.parseInt(placeholder.split('+')[0].trim());
|
||||
|
||||
// Generate some new serial numbers
|
||||
await page.getByLabel('text-field-serial_numbers').fill(`${sn}, ${sn + 1}`);
|
||||
await page
|
||||
.getByLabel('text-field-serial_numbers', { exact: true })
|
||||
.fill(`${sn}, ${sn + 1}`);
|
||||
|
||||
// Accept the suggested batch code
|
||||
await page
|
||||
.getByRole('img', { name: 'text-field-batch_code-accept-placeholder' })
|
||||
.click();
|
||||
|
||||
await page.getByLabel('text-field-batch_code').fill('BATCH12345');
|
||||
await page.getByLabel('related-field-location').click();
|
||||
await page.getByLabel('related-field-location').fill('Reel');
|
||||
await page.getByText('- Electronics Lab/Reel Storage').click();
|
||||
@@ -397,7 +404,7 @@ test('Build Order - Consume Stock', async ({ browser }) => {
|
||||
await page.getByLabel('Consume Stock').getByText('5 / 35').waitFor();
|
||||
await page.getByLabel('Consume Stock').getByText('5 / 40').waitFor();
|
||||
await page
|
||||
.getByRole('textbox', { name: 'text-field-notes' })
|
||||
.getByRole('textbox', { name: 'text-field-notes', exact: true })
|
||||
.fill('some notes here...');
|
||||
await page.getByRole('button', { name: 'Cancel' }).click();
|
||||
|
||||
@@ -426,7 +433,7 @@ test('Build Order - Tracked Outputs', async ({ browser }) => {
|
||||
const cancelBuildOutput = async (cell) => {
|
||||
await clickOnRowMenu(cell);
|
||||
await page.getByRole('menuitem', { name: 'Cancel' }).click();
|
||||
await page.getByRole('button', { name: 'Submit' }).click();
|
||||
await page.getByRole('button', { name: 'Submit', exact: true }).click();
|
||||
await page.getByText('Build outputs have been cancelled').waitFor();
|
||||
};
|
||||
|
||||
@@ -444,7 +451,9 @@ test('Build Order - Tracked Outputs', async ({ browser }) => {
|
||||
.getByRole('button', { name: 'action-button-add-build-output' })
|
||||
.click();
|
||||
await page.getByLabel('number-field-quantity').fill('1');
|
||||
await page.getByLabel('text-field-serial_numbers').fill('15');
|
||||
await page
|
||||
.getByLabel('text-field-serial_numbers', { exact: true })
|
||||
.fill('15');
|
||||
await page.getByRole('button', { name: 'Submit' }).click();
|
||||
await page.getByText('Build output created').waitFor();
|
||||
|
||||
@@ -499,7 +508,9 @@ test('Build Order - Tracked Outputs', async ({ browser }) => {
|
||||
.getByRole('button', { name: 'action-button-add-build-output' })
|
||||
.click();
|
||||
await page.getByLabel('number-field-quantity').fill('1');
|
||||
await page.getByLabel('text-field-serial_numbers').fill('16');
|
||||
await page
|
||||
.getByLabel('text-field-serial_numbers', { exact: true })
|
||||
.fill('16');
|
||||
await page
|
||||
.locator('label')
|
||||
.filter({ hasText: 'Auto Allocate Serial' })
|
||||
@@ -560,7 +571,9 @@ test('Build Order - Duplicate', async ({ browser }) => {
|
||||
await page.getByLabel('action-menu-build-order-actions-duplicate').click();
|
||||
|
||||
// Ensure a new reference is suggested
|
||||
await expect(page.getByLabel('text-field-reference')).not.toBeEmpty();
|
||||
await expect(
|
||||
page.getByLabel('text-field-reference', { exact: true })
|
||||
).not.toBeEmpty();
|
||||
|
||||
// Submit the duplicate request and ensure it completes
|
||||
await page.getByRole('button', { name: 'Submit' }).isEnabled();
|
||||
|
||||
@@ -30,8 +30,10 @@ test('Company', async ({ browser }) => {
|
||||
await page.getByLabel('action-menu-company-actions').click();
|
||||
await page.getByLabel('action-menu-company-actions-edit').click();
|
||||
|
||||
await page.getByLabel('text-field-name').fill('');
|
||||
await page.getByLabel('text-field-website').fill('invalid-website');
|
||||
await page.getByLabel('text-field-name', { exact: true }).fill('');
|
||||
await page
|
||||
.getByLabel('text-field-website', { exact: true })
|
||||
.fill('invalid-website');
|
||||
await page.getByRole('button', { name: 'Submit' }).click();
|
||||
|
||||
await page.getByText('This field may not be blank.').waitFor();
|
||||
|
||||
@@ -142,14 +142,16 @@ test('Part - Editing', async ({ browser }) => {
|
||||
// Open part edit dialog
|
||||
await page.keyboard.press('Control+E');
|
||||
|
||||
const keywords = await page.getByLabel('text-field-keywords').inputValue();
|
||||
const keywords = await page
|
||||
.getByLabel('text-field-keywords', { exact: true })
|
||||
.inputValue();
|
||||
await page
|
||||
.getByLabel('text-field-keywords')
|
||||
.getByLabel('text-field-keywords', { exact: true })
|
||||
.fill(keywords ? '' : 'table furniture');
|
||||
|
||||
// Test URL validation
|
||||
await page
|
||||
.getByRole('textbox', { name: 'text-field-link' })
|
||||
.getByRole('textbox', { name: 'text-field-link', exact: true })
|
||||
.fill('htxp-??QQQ++');
|
||||
await page.waitForTimeout(200);
|
||||
await page.getByRole('button', { name: 'Submit' }).click();
|
||||
@@ -157,11 +159,15 @@ test('Part - Editing', async ({ browser }) => {
|
||||
|
||||
// Fill with an empty URL
|
||||
const description = await page
|
||||
.getByLabel('text-field-description')
|
||||
.getByLabel('text-field-description', { exact: true })
|
||||
.inputValue();
|
||||
|
||||
await page.getByRole('textbox', { name: 'text-field-link' }).fill('');
|
||||
await page.getByLabel('text-field-description').fill(`${description}+`);
|
||||
await page
|
||||
.getByRole('textbox', { name: 'text-field-link', exact: true })
|
||||
.fill('');
|
||||
await page
|
||||
.getByLabel('text-field-description', { exact: true })
|
||||
.fill(`${description}+`);
|
||||
await page.waitForTimeout(200);
|
||||
await page.getByRole('button', { name: 'Submit' }).click();
|
||||
await page.getByText('Item Updated').waitFor();
|
||||
@@ -462,8 +468,12 @@ test('Parts - Attachments', async ({ browser }) => {
|
||||
|
||||
// Submit a new external link
|
||||
await page.getByLabel('action-button-add-external-').click();
|
||||
await page.getByLabel('text-field-link').fill('https://www.google.com');
|
||||
await page.getByLabel('text-field-comment').fill('a sample comment');
|
||||
await page
|
||||
.getByLabel('text-field-link', { exact: true })
|
||||
.fill('https://www.google.com');
|
||||
await page
|
||||
.getByLabel('text-field-comment', { exact: true })
|
||||
.fill('a sample comment');
|
||||
|
||||
// Note: Text field values are debounced for 250ms
|
||||
await page.waitForTimeout(300);
|
||||
@@ -473,7 +483,9 @@ test('Parts - Attachments', async ({ browser }) => {
|
||||
|
||||
// Launch dialog to upload a file
|
||||
await page.getByLabel('action-button-add-attachment').click();
|
||||
await page.getByLabel('text-field-comment').fill('some comment');
|
||||
await page
|
||||
.getByLabel('text-field-comment', { exact: true })
|
||||
.fill('some comment');
|
||||
await page.getByRole('button', { name: 'Cancel' }).click();
|
||||
});
|
||||
|
||||
@@ -489,7 +501,9 @@ test('Parts - Parameters', async ({ browser }) => {
|
||||
await page.getByLabel('choice-field-data').click();
|
||||
await page.getByRole('option', { name: 'Green' }).click();
|
||||
|
||||
await page.getByLabel('text-field-note').fill('A custom note field');
|
||||
await page
|
||||
.getByLabel('text-field-note', { exact: true })
|
||||
.fill('A custom note field');
|
||||
|
||||
// Select the "polarized" parameter template (should create a "checkbox" field)
|
||||
await page.getByLabel('related-field-template').fill('Polarized');
|
||||
@@ -577,8 +591,8 @@ test('Parts - Notes', async ({ browser }) => {
|
||||
|
||||
// Use keyboard shortcut to "edit" the part
|
||||
await page.keyboard.press('Control+E');
|
||||
await page.getByLabel('text-field-name').waitFor();
|
||||
await page.getByLabel('text-field-description').waitFor();
|
||||
await page.getByLabel('text-field-name', { exact: true }).waitFor();
|
||||
await page.getByLabel('text-field-description', { exact: true }).waitFor();
|
||||
await page.getByLabel('related-field-category').waitFor();
|
||||
await page.getByRole('button', { name: 'Cancel' }).click();
|
||||
|
||||
|
||||
@@ -169,13 +169,15 @@ test('Purchase Orders - General', async ({ browser }) => {
|
||||
.click();
|
||||
await page.getByRole('menuitem', { name: 'Edit' }).click();
|
||||
|
||||
await page.getByLabel('text-field-title').waitFor();
|
||||
await page.getByLabel('text-field-line2').waitFor();
|
||||
await page.getByLabel('text-field-title', { exact: true }).waitFor();
|
||||
await page.getByLabel('text-field-line2', { exact: true }).waitFor();
|
||||
|
||||
// Read the current value of the cell, to ensure we always *change* it!
|
||||
const value = await page.getByLabel('text-field-line2').inputValue();
|
||||
const value = await page
|
||||
.getByLabel('text-field-line2', { exact: true })
|
||||
.inputValue();
|
||||
await page
|
||||
.getByLabel('text-field-line2')
|
||||
.getByLabel('text-field-line2', { exact: true })
|
||||
.fill(value == 'old' ? 'new' : 'old');
|
||||
|
||||
await page.getByRole('button', { name: 'Submit' }).isEnabled();
|
||||
@@ -344,9 +346,13 @@ test('Purchase Orders - Receive Items', async ({ browser }) => {
|
||||
await page.getByLabel('action-button-change-status').click();
|
||||
await page.getByLabel('action-button-add-note').click();
|
||||
|
||||
await page.getByLabel('text-field-batch_code').fill('my-batch-code');
|
||||
await page.getByLabel('text-field-packaging').fill('bucket');
|
||||
await page.getByLabel('text-field-note').fill('The quick brown fox');
|
||||
await page
|
||||
.getByLabel('text-field-batch_code', { exact: true })
|
||||
.fill('my-batch-code');
|
||||
await page.getByLabel('text-field-packaging', { exact: true }).fill('bucket');
|
||||
await page
|
||||
.getByLabel('text-field-note', { exact: true })
|
||||
.fill('The quick brown fox');
|
||||
await page.getByLabel('choice-field-status').click();
|
||||
await page.getByRole('option', { name: 'Destroyed' }).click();
|
||||
|
||||
@@ -371,7 +377,9 @@ test('Purchase Orders - Duplicate', async ({ browser }) => {
|
||||
await page.getByLabel('action-menu-order-actions-duplicate').click();
|
||||
|
||||
// Ensure a new reference is suggested
|
||||
await expect(page.getByLabel('text-field-reference')).not.toBeEmpty();
|
||||
await expect(
|
||||
page.getByLabel('text-field-reference', { exact: true })
|
||||
).not.toBeEmpty();
|
||||
|
||||
// Submit the duplicate request and ensure it completes
|
||||
await page.getByRole('button', { name: 'Submit' }).isEnabled();
|
||||
|
||||
@@ -120,8 +120,12 @@ test('Sales Orders - Shipments', async ({ browser }) => {
|
||||
|
||||
// Create a new shipment
|
||||
await page.getByLabel('action-button-add-shipment').click();
|
||||
await page.getByLabel('text-field-tracking_number').fill('1234567890');
|
||||
await page.getByLabel('text-field-invoice_number').fill('9876543210');
|
||||
await page
|
||||
.getByLabel('text-field-tracking_number', { exact: true })
|
||||
.fill('1234567890');
|
||||
await page
|
||||
.getByLabel('text-field-invoice_number', { exact: true })
|
||||
.fill('9876543210');
|
||||
await page.getByRole('button', { name: 'Submit' }).click();
|
||||
|
||||
// Expected field error
|
||||
@@ -140,7 +144,7 @@ test('Sales Orders - Shipments', async ({ browser }) => {
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
let tracking_number = await page
|
||||
.getByLabel('text-field-tracking_number')
|
||||
.getByLabel('text-field-tracking_number', { exact: true })
|
||||
.inputValue();
|
||||
|
||||
if (!tracking_number) {
|
||||
@@ -154,7 +158,9 @@ test('Sales Orders - Shipments', async ({ browser }) => {
|
||||
}
|
||||
|
||||
// Change the tracking number
|
||||
await page.getByLabel('text-field-tracking_number').fill(tracking_number);
|
||||
await page
|
||||
.getByLabel('text-field-tracking_number', { exact: true })
|
||||
.fill(tracking_number);
|
||||
await page.waitForTimeout(250);
|
||||
await page.getByRole('button', { name: 'Submit' }).click();
|
||||
|
||||
@@ -217,7 +223,9 @@ test('Sales Orders - Duplicate', async ({ browser }) => {
|
||||
await page.getByLabel('action-menu-order-actions-duplicate').click();
|
||||
|
||||
// Ensure a new reference is suggested
|
||||
await expect(page.getByLabel('text-field-reference')).not.toBeEmpty();
|
||||
await expect(
|
||||
page.getByLabel('text-field-reference', { exact: true })
|
||||
).not.toBeEmpty();
|
||||
|
||||
// Submit the duplicate request and ensure it completes
|
||||
await page.getByRole('button', { name: 'Submit' }).isEnabled();
|
||||
|
||||
@@ -130,7 +130,9 @@ test('Stock - Serial Numbers', async ({ browser }) => {
|
||||
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('text-field-serial_numbers', { exact: true })
|
||||
.fill('200-250');
|
||||
await page.getByLabel('number-field-quantity').fill('10');
|
||||
|
||||
// Add delay to account to field debounce
|
||||
@@ -171,7 +173,7 @@ test('Stock - Serial Navigation', async ({ browser }) => {
|
||||
|
||||
await page.getByLabel('action-menu-stock-actions').click();
|
||||
await page.getByLabel('action-menu-stock-actions-search').click();
|
||||
await page.getByLabel('text-field-serial').fill('359');
|
||||
await page.getByLabel('text-field-serial', { exact: true }).fill('359');
|
||||
await page.getByRole('button', { name: 'Submit' }).click();
|
||||
|
||||
// Start at serial 359
|
||||
@@ -183,7 +185,7 @@ test('Stock - Serial Navigation', async ({ browser }) => {
|
||||
await page.getByText('358', { exact: true }).first().waitFor();
|
||||
|
||||
await page.getByLabel('action-button-find-serial').click();
|
||||
await page.getByLabel('text-field-serial').fill('200');
|
||||
await page.getByLabel('text-field-serial', { exact: true }).fill('200');
|
||||
await page.getByRole('button', { name: 'Submit' }).click();
|
||||
|
||||
await page.getByText('Serial Number: 200').waitFor();
|
||||
@@ -201,10 +203,15 @@ test('Stock - Serialize', async ({ browser }) => {
|
||||
|
||||
// Check for expected placeholder value
|
||||
await expect(
|
||||
page.getByRole('textbox', { name: 'text-field-serial_numbers' })
|
||||
).toHaveAttribute('placeholder', 'Next serial number: 365');
|
||||
page.getByRole('textbox', {
|
||||
name: 'text-field-serial_numbers',
|
||||
exact: true
|
||||
})
|
||||
).toHaveAttribute('placeholder', '365+');
|
||||
|
||||
await page.getByLabel('text-field-serial_numbers').fill('200-250');
|
||||
await page
|
||||
.getByLabel('text-field-serial_numbers', { exact: true })
|
||||
.fill('200-250');
|
||||
|
||||
await page.getByRole('button', { name: 'Submit' }).click();
|
||||
|
||||
@@ -212,7 +219,9 @@ test('Stock - Serialize', async ({ browser }) => {
|
||||
.getByText('Number of unique serial numbers (51) must match quantity (100)')
|
||||
.waitFor();
|
||||
|
||||
await page.getByLabel('text-field-serial_numbers').fill('1, 2, 3');
|
||||
await page
|
||||
.getByLabel('text-field-serial_numbers', { exact: true })
|
||||
.fill('1, 2, 3');
|
||||
await page.waitForTimeout(250);
|
||||
await page.getByRole('button', { name: 'Submit' }).click();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user