2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-15 19:45:46 +00:00
Files
InvenTree/src/frontend/tests/pui_plugins.spec.ts
Oliver 11ab0203b1 [plugin] Auto issue orders (#9565)
* Add builtin plugin for auto-issuing orders

* Add plugin to auto-issue orders

* Add placeholder documentation

* Fix typo

* Adds image macro

- To replace img.html
- includes checking if file exists

* Fix tooltips

* More docs

* Adjust plugin settings filters

* docs

* More docs

* More docs

* Updates

* Less restrictive URL checking

* Refactor build order page

* Fix typo

* Allow 429

* Debug output

* More debug

* Construct assets dir

* Cleanup

* Update docs README

* Refactoring more pages

* Fix image link

* Fix SSO settings

* Add hook to check for missing settings

- Ensure that all settings are documented!

* Add missing user settings

* Update docstring

* Tweak SSO.md

* Image updates

* More updates

* Tweaks

* Exclude orders without a target_date

* Fix for issuing build orders

* Further refactoring

* Fixes

* Image refactoring

* More refactoring

* More refactoring

* Refactor app images

* Fix pathing issues

* Suppress some openapidocs warnings in logs

(much easier to debug docs build issues)

* Fix image reference

* Reduce error messages

* Fix image links

* Fix image links

* Reduce docs log output

* Ensure settings are loaded before displaying them

* Fix for UI test

* Fix unit test

* Test tweaks
2025-06-03 17:07:12 +10:00

227 lines
6.6 KiB
TypeScript

import test from 'playwright/test';
import {
clearTableFilters,
clickOnRowMenu,
loadTab,
navigate,
setTableChoiceFilter
} from './helpers.js';
import { doCachedLogin } from './login.js';
import { setPluginState, setSettingState } from './settings.js';
// Unit test for plugin settings
test('Plugins - Settings', async ({ browser, request }) => {
const page = await doCachedLogin(browser, {
username: 'admin',
password: 'inventree'
});
// Ensure that the SampleIntegration plugin is enabled
await setPluginState({
request,
plugin: 'sample',
state: true
});
// Navigate and select the plugin
await navigate(page, 'settings/admin/plugin/');
await clearTableFilters(page);
await page.getByLabel('table-search-input').fill('integration');
await page
.getByRole('row', { name: 'SampleIntegrationPlugin' })
.getByRole('paragraph')
.click();
await page.getByRole('button', { name: 'Plugin Information' }).click();
await page
.getByLabel('Plugin Detail -')
.getByRole('button', { name: 'Plugin Settings' })
.waitFor();
// Edit numerical value
await page.getByLabel('edit-setting-NUMERICAL_SETTING').click();
const originalValue = await page
.getByLabel('number-field-value')
.inputValue();
await page
.getByLabel('number-field-value')
.fill(originalValue == '999' ? '1000' : '999');
await page.getByRole('button', { name: 'Submit' }).click();
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();
// Select supplier
await page.getByLabel('edit-setting-SELECT_COMPANY').click();
await page.getByLabel('related-field-value').fill('mouser');
await page.getByText('Mouser Electronics').click();
});
// Test base plugin functionality
test('Plugins - Functionality', async ({ browser }) => {
// Navigate and select the plugin
const page = await doCachedLogin(browser, {
username: 'admin',
password: 'inventree',
url: 'settings/admin/plugin/'
});
// Filter plugins first
await clearTableFilters(page);
await setTableChoiceFilter(page, 'Sample', 'Yes');
await setTableChoiceFilter(page, 'Builtin', 'No');
// Activate the plugin
const cell = await page.getByText('Sample API Caller', { exact: true });
await clickOnRowMenu(cell);
// 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 page.getByText('The plugin was activated').waitFor();
await page.waitForTimeout(250);
}
// Deactivate the plugin again
await clickOnRowMenu(cell);
await page.getByRole('menuitem', { name: 'Deactivate' }).click();
await page.getByRole('button', { name: 'Submit' }).click();
await page.getByText('The plugin was deactivated').waitFor();
});
test('Plugins - Panels', async ({ browser, request }) => {
const page = await doCachedLogin(browser, {
username: 'admin',
password: 'inventree'
});
// Ensure that UI plugins are enabled
await setSettingState({
request,
setting: 'ENABLE_PLUGINS_INTERFACE',
value: true
});
await page.waitForTimeout(500);
// Ensure that the SampleUI plugin is enabled
await setPluginState({
request,
plugin: 'sampleui',
state: true
});
await page.waitForTimeout(500);
// Navigate to the "part" page
await navigate(page, 'part/69/');
// Ensure basic part tab is available
await loadTab(page, 'Part Details');
// Allow time for the plugin panels to load (they are loaded asynchronously)
await page.waitForLoadState('networkidle');
// Check out each of the plugin panels
await loadTab(page, 'Broken Panel');
await page.waitForTimeout(500);
await page.getByText('Error occurred while loading plugin content').waitFor();
await loadTab(page, 'Dynamic Panel');
await page.waitForTimeout(500);
await page.getByText('Instance ID: 69');
await page
.getByText('This panel has been dynamically rendered by the plugin system')
.waitFor();
await loadTab(page, 'Part Panel');
await page.waitForTimeout(500);
await page.getByText('This content has been rendered by a custom plugin');
// Disable the plugin, and ensure it is no longer visible
await setPluginState({
request,
plugin: 'sampleui',
state: false
});
});
/**
* Unit test for custom admin integration for plugins
*/
test('Plugins - Custom Admin', async ({ browser, request }) => {
const page = await doCachedLogin(browser, {
username: 'admin',
password: 'inventree'
});
// Ensure that the SampleUI plugin is enabled
await setPluginState({
request,
plugin: 'sampleui',
state: true
});
// Navigate to the "admin" page
await navigate(page, 'settings/admin/plugin/');
// Open the plugin drawer, and ensure that the custom admin elements are visible
await page.getByText('SampleUI').click();
await page.getByRole('button', { name: 'Plugin Information' }).click();
await page
.getByLabel('Plugin Detail')
.getByRole('button', { name: 'Plugin Settings' })
.click();
await page.getByRole('button', { name: 'Plugin Configuration' }).click();
// Check for expected custom elements
await page
.getByRole('heading', { name: 'Custom Plugin Configuration Content' })
.waitFor();
await page.getByText('apple: banana').waitFor();
await page.getByText('foo: bar').waitFor();
await page.getByText('hello: world').waitFor();
});
test('Plugins - Locate Item', async ({ browser, request }) => {
const page = await doCachedLogin(browser, {
username: 'admin',
password: 'inventree'
});
// Ensure that the sample location plugin is enabled
await setPluginState({
request,
plugin: 'samplelocate',
state: true
});
await page.waitForTimeout(500);
// Navigate to the "stock item" page
await navigate(page, 'stock/item/287/');
await page.waitForLoadState('networkidle');
// "Locate" this item
await page.getByLabel('action-button-locate-item').click();
await page.getByRole('button', { name: 'Submit' }).click();
await page.getByText('Item location requested').waitFor();
// Show the location
await page.getByLabel('breadcrumb-1-factory').click();
await page.waitForTimeout(500);
await page.getByLabel('action-button-locate-item').click();
await page.getByRole('button', { name: 'Submit' }).click();
await page.getByText('Item location requested').waitFor();
});