2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-13 02:25:38 +00:00

Playwright test

This commit is contained in:
Oliver Walters
2025-04-21 04:25:42 +00:00
parent 47e47b4bde
commit a63b23961e
10 changed files with 88 additions and 54 deletions

View File

@ -1,5 +1,14 @@
import { baseUrl } from './defaults';
/**
* Helper function to submit a form dialog.
* Includes a small delay to allow the form values to be debounced
*/
export const submitForm = async (page) => {
await page.waitForTimeout(250);
await page.getByRole('button', { name: 'Submit' }).click();
};
/**
* Open the filter drawer for the currently visible table
* @param page - The page object

View File

@ -6,7 +6,8 @@ import {
getRowFromCell,
loadTab,
navigate,
setTableChoiceFilter
setTableChoiceFilter,
submitForm
} from '../helpers.ts';
import { doCachedLogin } from '../login.ts';
@ -133,7 +134,7 @@ test('Build Order - Edit', async ({ browser }) => {
await page.getByLabel('date-field-start_date').fill('2026-09-09');
// Submit the form
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
// Expect error
await page.getByText('Errors exist for one or more form fields').waitFor();
@ -178,7 +179,7 @@ test('Build Order - Build Outputs', async ({ browser }) => {
await page.getByLabel('text-field-batch_code').fill('BATCH12345');
await page.getByLabel('related-field-location').click();
await page.getByText('Reel Storage').click();
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
// Should be an error as the number of serial numbers doesn't match the quantity
await page.getByText('Errors exist for one or more').waitFor();
@ -187,7 +188,7 @@ test('Build Order - Build Outputs', async ({ browser }) => {
// Fix the quantity
await page.getByLabel('number-field-quantity').fill('2');
await page.waitForTimeout(250);
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
// Check that new serial numbers have been created
await page
@ -204,7 +205,7 @@ test('Build Order - Build Outputs', async ({ browser }) => {
const row = await getRowFromCell(cell);
await row.getByLabel(/row-action-menu-/i).click();
await page.getByRole('menuitem', { name: 'Cancel' }).click();
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
await page.getByText('Build outputs have been cancelled').waitFor();
// Complete the other output
@ -215,7 +216,7 @@ test('Build Order - Build Outputs', async ({ browser }) => {
await page.getByLabel('related-field-location').click();
await page.getByText('Mechanical Lab').click();
await page.waitForTimeout(250);
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
await page.getByText('Build outputs have been completed').waitFor();
});
@ -365,7 +366,7 @@ test('Build Order - Duplicate', async ({ browser }) => {
// Submit the duplicate request and ensure it completes
await page.getByRole('button', { name: 'Submit' }).isEnabled();
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
await page.getByRole('tab', { name: 'Build Details' }).waitFor();
await page.getByRole('tab', { name: 'Build Details' }).click();

View File

@ -3,7 +3,8 @@ import {
clearTableFilters,
getRowFromCell,
loadTab,
navigate
navigate,
submitForm
} from '../helpers';
import { doCachedLogin } from '../login';
@ -113,6 +114,27 @@ test('Parts - BOM', async ({ browser }) => {
await page.getByRole('button', { name: 'Close' }).click();
});
test('Part - Editing', async ({ browser }) => {
const page = await doCachedLogin(browser, { url: 'part/104/details' });
await page.getByText('A square table - with blue paint').first().waitFor();
// Open part edit dialog
await page.keyboard.press('Control+E');
await page.getByLabel('text-field-keywords').fill('table furniture');
// Test URL validation
await page.getByLabel('text-field-link').fill('htxp-??QQQ++');
await submitForm(page);
await page.getByText('Enter a valid URL.').waitFor();
// Fill with an empty URL
await page.getByLabel('text-field-link').fill('');
await submitForm(page);
await page.getByText('Item Updated').waitFor();
});
test('Parts - Locking', async ({ browser }) => {
const page = await doCachedLogin(browser, { url: 'part/104/bom' });
await loadTab(page, 'Bill of Materials');

View File

@ -9,7 +9,8 @@ import {
loadTab,
navigate,
openFilterDrawer,
setTableChoiceFilter
setTableChoiceFilter,
submitForm
} from '../helpers.ts';
import { doCachedLogin } from '../login.ts';
@ -180,7 +181,7 @@ test('Purchase Orders - General', async ({ browser }) => {
await page.getByRole('button', { name: 'Submit' }).isEnabled();
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
await page.getByRole('tab', { name: 'Details' }).waitFor();
});
@ -289,7 +290,7 @@ test('Purchase Orders - Order Parts', async ({ browser }) => {
await page.getByLabel('action-button-add-to-selected').click();
await page.getByLabel('number-field-quantity').fill('100');
await page.waitForTimeout(250);
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
await page
.getByText('All selected parts added to a purchase order')
.waitFor();
@ -357,7 +358,7 @@ test('Purchase Orders - Receive Items', async ({ browser }) => {
// Short timeout to allow for debouncing
await page.waitForTimeout(200);
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
await page.getByText('Items received').waitFor();
await loadTab(page, 'Received Stock');
@ -380,7 +381,7 @@ test('Purchase Orders - Duplicate', async ({ browser }) => {
// Submit the duplicate request and ensure it completes
await page.getByRole('button', { name: 'Submit' }).isEnabled();
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
await page.getByRole('tab', { name: 'Order Details' }).waitFor();
await page.getByRole('tab', { name: 'Order Details' }).click();

View File

@ -4,7 +4,8 @@ import {
clearTableFilters,
globalSearch,
loadTab,
setTableChoiceFilter
setTableChoiceFilter,
submitForm
} from '../helpers.ts';
import { doCachedLogin } from '../login.ts';
@ -82,7 +83,7 @@ test('Sales Orders - Basic Tests', async ({ browser }) => {
await page.getByText('Selling stuff').first().waitFor();
await page.getByText('On Hold').first().waitFor();
await page.getByRole('button', { name: 'Issue Order' }).click();
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
// Order should now be "in progress"
await page.getByText('In Progress').first().waitFor();
@ -96,7 +97,7 @@ test('Sales Orders - Basic Tests', async ({ browser }) => {
// Mark the order as "on hold" again
await page.getByLabel('action-menu-order-actions-hold').click();
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
await page.getByText('On Hold').first().waitFor();
await page.getByRole('button', { name: 'Issue Order' }).waitFor();
@ -119,7 +120,7 @@ test('Sales Orders - Shipments', async ({ browser }) => {
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.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
// Expected field error
await page
@ -152,7 +153,7 @@ test('Sales Orders - Shipments', async ({ browser }) => {
// Change the tracking number
await page.getByLabel('text-field-tracking_number').fill(tracking_number);
await page.waitForTimeout(250);
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
// Click through to a particular shipment
await page.getByLabel('row-action-menu-0').click();
@ -216,7 +217,7 @@ test('Sales Orders - Duplicate', async ({ browser }) => {
// Submit the duplicate request and ensure it completes
await page.getByRole('button', { name: 'Submit' }).isEnabled();
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
await page.getByRole('tab', { name: 'Order Details' }).waitFor();
await page.getByRole('tab', { name: 'Order Details' }).click();

View File

@ -5,7 +5,8 @@ import {
loadTab,
navigate,
openFilterDrawer,
setTableChoiceFilter
setTableChoiceFilter,
submitForm
} from '../helpers.js';
import { doCachedLogin } from '../login.js';
@ -136,7 +137,7 @@ test('Stock - Serial Numbers', async ({ browser }) => {
// Add delay to account to field debounce
await page.waitForTimeout(250);
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
// Expected error messages
await page.getByText('Errors exist for one or more form fields').waitFor();
@ -148,7 +149,7 @@ test('Stock - Serial Numbers', async ({ browser }) => {
// Now, with correct quantity
await page.getByLabel('number-field-quantity').fill('51');
await page.waitForTimeout(250);
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
await page.waitForTimeout(250);
await page
@ -172,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.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
// Start at serial 359
await page.getByText('359', { exact: true }).first().waitFor();
@ -184,7 +185,7 @@ test('Stock - Serial Navigation', async ({ browser }) => {
await page.getByLabel('action-button-find-serial').click();
await page.getByLabel('text-field-serial').fill('200');
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
await page.getByText('Serial Number: 200').waitFor();
await page.getByText('200', { exact: true }).first().waitFor();
@ -201,7 +202,7 @@ test('Stock - Serialize', async ({ browser }) => {
await page.getByLabel('text-field-serial_numbers').fill('200-250');
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
await page
.getByText('Group range 200-250 exceeds allowed quantity')
.waitFor();
@ -251,7 +252,7 @@ test('Stock - Stock Actions', async ({ browser }) => {
await launchStockAction('add');
await page.getByLabel('number-field-quantity').fill('12');
await setStockStatus('Lost');
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
await page.getByText('Lost').first().waitFor();
await page.getByText('Unavailable').first().waitFor();
@ -261,7 +262,7 @@ test('Stock - Stock Actions', async ({ browser }) => {
await launchStockAction('remove');
await page.getByLabel('number-field-quantity').fill('99');
await setStockStatus('Damaged');
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
await page.getByText('36').first().waitFor();
await page.getByText('Damaged').first().waitFor();
@ -270,7 +271,7 @@ test('Stock - Stock Actions', async ({ browser }) => {
await launchStockAction('count');
await page.getByLabel('number-field-quantity').fill('123');
await setStockStatus('Incoming goods inspection');
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
await page.getByText('123').first().waitFor();
await page.getByText('Custom Status').first().waitFor();

View File

@ -1,6 +1,6 @@
/** Unit tests for form validation, rendering, etc */
import test from 'playwright/test';
import { navigate } from './helpers';
import { navigate, submitForm } from './helpers';
import { doCachedLogin } from './login';
test('Forms - Stock Item Validation', async ({ browser }) => {
@ -14,7 +14,7 @@ test('Forms - Stock Item Validation', async ({ browser }) => {
// Create new stock item form
await page.getByLabel('action-button-add-stock-item').click();
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
// Check for validation errors
await page.getByText('Form Error').waitFor();
@ -31,7 +31,7 @@ test('Forms - Stock Item Validation', async ({ browser }) => {
await page.getByLabel('number-field-quantity').fill('-1');
await page.getByLabel('related-field-part').click();
await page.getByRole('option', { name: /1551AGY/ }).click();
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
// Check for validation errors
await page.getByText('Errors exist for one or more form fields').waitFor();
@ -46,14 +46,14 @@ test('Forms - Stock Item Validation', async ({ browser }) => {
// Create the stock item
await page.getByLabel('number-field-quantity').fill('123');
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
// Edit the resulting stock item
await page.getByLabel('action-menu-stock-item-actions').click();
await page.getByLabel('action-menu-stock-item-actions-edit').click();
await page.getByLabel('number-field-purchase_price').fill('-1');
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
await page.getByText('Errors exist for one or more form fields').waitFor();
await page
.getByText('Ensure this value is greater than or equal to 0')
@ -68,7 +68,7 @@ test('Forms - Stock Item Validation', async ({ browser }) => {
// Correct the price
await page.getByLabel('number-field-purchase_price').fill('1.2345');
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
await page.getByText('Item Updated').waitFor();
// Ensure the stock item has been updated correctly
@ -89,7 +89,7 @@ test('Forms - Supplier Validation', async ({ browser }) => {
await page.getByLabel('action-button-add-company').click();
await page.getByLabel('text-field-website').fill('not-a-website');
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
// Check for validation errors
await page.getByText('Form Error').waitFor();
@ -111,7 +111,7 @@ test('Forms - Supplier Validation', async ({ browser }) => {
.getByLabel('text-field-website')
.fill('https://www.test-website.co.uk');
await page.getByLabel('text-field-name').fill(supplierName);
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
await page.getByText('A description').first().waitFor();
await page
@ -123,7 +123,7 @@ test('Forms - Supplier Validation', async ({ browser }) => {
await page.waitForURL('**/purchasing/index/**');
await page.getByLabel('action-button-add-company').click();
await page.getByLabel('text-field-name').fill(supplierName);
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
// Is prevented, due to uniqueness requirements
await page.getByText('Form Error').waitFor();

View File

@ -5,7 +5,8 @@ import {
clickOnRowMenu,
loadTab,
navigate,
setTableChoiceFilter
setTableChoiceFilter,
submitForm
} from './helpers.js';
import { doCachedLogin } from './login.js';
import { setPluginState, setSettingState } from './settings.js';
@ -45,14 +46,14 @@ test('Plugins - Settings', async ({ browser, request }) => {
await page
.getByLabel('number-field-value')
.fill(originalValue == '999' ? '1000' : '999');
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
await page.waitForTimeout(500);
// Change it back
await page.getByLabel('edit-setting-NUMERICAL_SETTING').click();
await page.getByLabel('number-field-value').fill(originalValue);
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
// Select supplier
await page.getByLabel('edit-setting-SELECT_COMPANY').click();
@ -81,7 +82,7 @@ test('Plugins - Functionality', async ({ browser }) => {
// Activate the plugin (unless already activated)
if ((await page.getByRole('menuitem', { name: 'Deactivate' }).count()) == 0) {
await page.getByRole('menuitem', { name: 'Activate' }).click();
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
await page.getByText('The plugin was activated').waitFor();
await page.waitForTimeout(250);
}
@ -89,7 +90,7 @@ test('Plugins - Functionality', async ({ browser }) => {
// Deactivate the plugin again
await clickOnRowMenu(cell);
await page.getByRole('menuitem', { name: 'Deactivate' }).click();
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
await page.getByText('The plugin was deactivated').waitFor();
});
@ -210,7 +211,7 @@ test('Plugins - Locate Item', async ({ browser, request }) => {
// "Locate" this item
await page.getByLabel('action-button-locate-item').click();
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
await page.getByText('Item location requested').waitFor();
// Show the location
@ -218,6 +219,6 @@ test('Plugins - Locate Item', async ({ browser, request }) => {
await page.waitForTimeout(500);
await page.getByLabel('action-button-locate-item').click();
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
await page.getByText('Item location requested').waitFor();
});

View File

@ -1,6 +1,6 @@
import { expect, test } from './baseFixtures.js';
import { apiUrl } from './defaults.js';
import { getRowFromCell, loadTab, navigate } from './helpers.js';
import { getRowFromCell, loadTab, navigate, submitForm } from './helpers.js';
import { doCachedLogin } from './login.js';
import { setSettingState } from './settings.js';
@ -149,8 +149,7 @@ test('Settings - Admin', async ({ browser }) => {
const newDescription = `${oldDescription} (edited)`;
await page.getByLabel('text-field-description').fill(newDescription);
await page.waitForTimeout(500);
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
// Edit second item - 'Box (Large)'
const boxCell = await page.getByRole('cell', {
@ -172,12 +171,11 @@ test('Settings - Admin', async ({ browser }) => {
await roomRow.getByLabel(/row-action-menu-/i).click();
await page.getByRole('menuitem', { name: 'Edit' }).click();
await page.getByLabel('text-field-name').fill('Room');
await page.waitForTimeout(500);
await page.waitForTimeout(200);
await page
.getByLabel('text-field-description')
.fill(newDescription.replaceAll(' (edited)', ''));
await page.waitForTimeout(500);
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
});
test('Settings - Admin - Barcode History', async ({ browser, request }) => {

View File

@ -1,5 +1,5 @@
import { test } from '../baseFixtures';
import { navigate } from '../helpers';
import { navigate, submitForm } from '../helpers';
import { doCachedLogin } from '../login';
test('PUI - Admin - Parameter', async ({ browser }) => {
@ -53,7 +53,7 @@ test('PUI - Admin - Parameter', async ({ browser }) => {
await page.getByLabel('action-button-add-selection-').click();
await page.getByLabel('text-field-name').fill('some list');
await page.getByLabel('text-field-description').fill('Listdescription');
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
await page.getByRole('cell', { name: 'some list' }).waitFor();
await page.waitForTimeout(200);
@ -74,7 +74,7 @@ test('PUI - Admin - Parameter', async ({ browser }) => {
.locator('div')
.first()
.click();
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
await page.getByRole('cell', { name: 'my custom parameter' }).click();
// Fill parameter
@ -99,5 +99,5 @@ test('PUI - Admin - Parameter', async ({ browser }) => {
.fill('my custom parameter');
await page.getByRole('option', { name: 'my custom parameter' }).click();
await page.getByLabel('choice-field-data').fill('2');
await page.getByRole('button', { name: 'Submit' }).click();
await submitForm(page);
});