mirror of
https://github.com/inventree/InvenTree.git
synced 2025-06-16 12:05:53 +00:00
add tests
This commit is contained in:
@ -8,8 +8,7 @@ from django.urls import include, path, re_path, reverse
|
|||||||
|
|
||||||
from error_report.models import Error
|
from error_report.models import Error
|
||||||
|
|
||||||
from common.models import InvenTreeSetting
|
from InvenTree.unit_test import InvenTreeTestCase
|
||||||
from InvenTree.unit_test import InvenTreeAPITestCase, InvenTreeTestCase
|
|
||||||
from plugin import InvenTreePlugin
|
from plugin import InvenTreePlugin
|
||||||
from plugin.base.integration.PanelMixin import PanelMixin
|
from plugin.base.integration.PanelMixin import PanelMixin
|
||||||
from plugin.helpers import MixinNotImplementedError
|
from plugin.helpers import MixinNotImplementedError
|
||||||
@ -479,100 +478,3 @@ class PanelMixinTests(InvenTreeTestCase):
|
|||||||
|
|
||||||
plugin = Wrong()
|
plugin = Wrong()
|
||||||
plugin.get_custom_panels('abc', 'abc')
|
plugin.get_custom_panels('abc', 'abc')
|
||||||
|
|
||||||
|
|
||||||
class UserInterfaceMixinTests(InvenTreeAPITestCase):
|
|
||||||
"""Test the UserInterfaceMixin plugin mixin class."""
|
|
||||||
|
|
||||||
roles = 'all'
|
|
||||||
|
|
||||||
fixtures = ['part', 'category', 'location', 'stock']
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def setUpTestData(cls):
|
|
||||||
"""Set up the test case."""
|
|
||||||
super().setUpTestData()
|
|
||||||
|
|
||||||
# Ensure that the 'sampleui' plugin is installed and active
|
|
||||||
registry.set_plugin_state('sampleui', True)
|
|
||||||
|
|
||||||
# Ensure that UI plugins are enabled
|
|
||||||
InvenTreeSetting.set_setting('ENABLE_PLUGINS_INTERFACE', True, change_user=None)
|
|
||||||
|
|
||||||
def test_installed(self):
|
|
||||||
"""Test that the sample UI plugin is installed and active."""
|
|
||||||
plugin = registry.get_plugin('sampleui')
|
|
||||||
self.assertTrue(plugin.is_active())
|
|
||||||
|
|
||||||
plugins = registry.with_mixin('ui')
|
|
||||||
self.assertGreater(len(plugins), 0)
|
|
||||||
|
|
||||||
def test_panels(self):
|
|
||||||
"""Test that the sample UI plugin provides custom panels."""
|
|
||||||
from part.models import Part
|
|
||||||
|
|
||||||
plugin = registry.get_plugin('sampleui')
|
|
||||||
|
|
||||||
_part = Part.objects.first()
|
|
||||||
|
|
||||||
# Ensure that the part is active
|
|
||||||
_part.active = True
|
|
||||||
_part.save()
|
|
||||||
|
|
||||||
url = reverse('api-plugin-panel-list')
|
|
||||||
|
|
||||||
query_data = {'target_model': 'part', 'target_id': _part.pk}
|
|
||||||
|
|
||||||
# Enable *all* plugin settings
|
|
||||||
plugin.set_setting('ENABLE_PART_PANELS', True)
|
|
||||||
plugin.set_setting('ENABLE_PURCHASE_ORDER_PANELS', True)
|
|
||||||
plugin.set_setting('ENABLE_BROKEN_PANELS', True)
|
|
||||||
plugin.set_setting('ENABLE_DYNAMIC_PANEL', True)
|
|
||||||
|
|
||||||
# Request custom panel information for a part instance
|
|
||||||
response = self.get(url, data=query_data)
|
|
||||||
|
|
||||||
# There should be 4 active panels for the part by default
|
|
||||||
self.assertEqual(4, len(response.data))
|
|
||||||
|
|
||||||
_part.active = False
|
|
||||||
_part.save()
|
|
||||||
|
|
||||||
response = self.get(url, data=query_data)
|
|
||||||
|
|
||||||
# As the part is not active, only 3 panels left
|
|
||||||
self.assertEqual(3, len(response.data))
|
|
||||||
|
|
||||||
# Disable the "ENABLE_PART_PANELS" setting, and try again
|
|
||||||
plugin.set_setting('ENABLE_PART_PANELS', False)
|
|
||||||
|
|
||||||
response = self.get(url, data=query_data)
|
|
||||||
|
|
||||||
# There should still be 3 panels
|
|
||||||
self.assertEqual(3, len(response.data))
|
|
||||||
|
|
||||||
# Check for the correct panel names
|
|
||||||
self.assertEqual(response.data[0]['name'], 'sample_panel')
|
|
||||||
self.assertIn('content', response.data[0])
|
|
||||||
self.assertNotIn('source', response.data[0])
|
|
||||||
|
|
||||||
self.assertEqual(response.data[1]['name'], 'broken_panel')
|
|
||||||
self.assertEqual(response.data[1]['source'], '/this/does/not/exist.js')
|
|
||||||
self.assertNotIn('content', response.data[1])
|
|
||||||
|
|
||||||
self.assertEqual(response.data[2]['name'], 'dynamic_panel')
|
|
||||||
self.assertEqual(response.data[2]['source'], '/static/plugin/sample_panel.js')
|
|
||||||
self.assertNotIn('content', response.data[2])
|
|
||||||
|
|
||||||
# Next, disable the global setting for UI integration
|
|
||||||
InvenTreeSetting.set_setting(
|
|
||||||
'ENABLE_PLUGINS_INTERFACE', False, change_user=None
|
|
||||||
)
|
|
||||||
|
|
||||||
response = self.get(url, data=query_data)
|
|
||||||
|
|
||||||
# There should be no panels available
|
|
||||||
self.assertEqual(0, len(response.data))
|
|
||||||
|
|
||||||
# Set the setting back to True for subsequent tests
|
|
||||||
InvenTreeSetting.set_setting('ENABLE_PLUGINS_INTERFACE', True, change_user=None)
|
|
||||||
|
@ -69,11 +69,9 @@ class PluginUIFeatureList(APIView):
|
|||||||
feature, request.query_params, request
|
feature, request.query_params, request
|
||||||
)
|
)
|
||||||
|
|
||||||
if not plugin_features or type(plugin_features) is not list:
|
if plugin_features and type(plugin_features) is list:
|
||||||
continue
|
for _feature in plugin_features:
|
||||||
|
features.append(_feature)
|
||||||
for _feature in plugin_features:
|
|
||||||
features.append(_feature)
|
|
||||||
|
|
||||||
return Response(
|
return Response(
|
||||||
UIPluginSerializers.PluginUIFeatureSerializer(features, many=True).data
|
UIPluginSerializers.PluginUIFeatureSerializer(features, many=True).data
|
||||||
|
157
src/backend/InvenTree/plugin/base/ui/tests.py
Normal file
157
src/backend/InvenTree/plugin/base/ui/tests.py
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
"""Unit tests for base mixins for plugins."""
|
||||||
|
|
||||||
|
from django.urls import reverse
|
||||||
|
|
||||||
|
from common.models import InvenTreeSetting
|
||||||
|
from InvenTree.unit_test import InvenTreeAPITestCase
|
||||||
|
from plugin.registry import registry
|
||||||
|
|
||||||
|
|
||||||
|
class UserInterfaceMixinTests(InvenTreeAPITestCase):
|
||||||
|
"""Test the UserInterfaceMixin plugin mixin class."""
|
||||||
|
|
||||||
|
roles = 'all'
|
||||||
|
|
||||||
|
fixtures = ['part', 'category', 'location', 'stock']
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setUpTestData(cls):
|
||||||
|
"""Set up the test case."""
|
||||||
|
super().setUpTestData()
|
||||||
|
|
||||||
|
# Ensure that the 'sampleui' plugin is installed and active
|
||||||
|
registry.set_plugin_state('sampleui', True)
|
||||||
|
|
||||||
|
# Ensure that UI plugins are enabled
|
||||||
|
InvenTreeSetting.set_setting('ENABLE_PLUGINS_INTERFACE', True, change_user=None)
|
||||||
|
|
||||||
|
def test_installed(self):
|
||||||
|
"""Test that the sample UI plugin is installed and active."""
|
||||||
|
plugin = registry.get_plugin('sampleui')
|
||||||
|
self.assertTrue(plugin.is_active())
|
||||||
|
|
||||||
|
plugins = registry.with_mixin('ui')
|
||||||
|
self.assertGreater(len(plugins), 0)
|
||||||
|
|
||||||
|
def test_panels(self):
|
||||||
|
"""Test that the sample UI plugin provides custom panels."""
|
||||||
|
from part.models import Part
|
||||||
|
|
||||||
|
plugin = registry.get_plugin('sampleui')
|
||||||
|
|
||||||
|
_part = Part.objects.first()
|
||||||
|
|
||||||
|
# Ensure that the part is active
|
||||||
|
_part.active = True
|
||||||
|
_part.save()
|
||||||
|
|
||||||
|
url = reverse('api-plugin-panel-list')
|
||||||
|
|
||||||
|
query_data = {'target_model': 'part', 'target_id': _part.pk}
|
||||||
|
|
||||||
|
# Enable *all* plugin settings
|
||||||
|
plugin.set_setting('ENABLE_PART_PANELS', True)
|
||||||
|
plugin.set_setting('ENABLE_PURCHASE_ORDER_PANELS', True)
|
||||||
|
plugin.set_setting('ENABLE_BROKEN_PANELS', True)
|
||||||
|
plugin.set_setting('ENABLE_DYNAMIC_PANEL', True)
|
||||||
|
|
||||||
|
# Request custom panel information for a part instance
|
||||||
|
response = self.get(url, data=query_data)
|
||||||
|
|
||||||
|
# There should be 4 active panels for the part by default
|
||||||
|
self.assertEqual(4, len(response.data))
|
||||||
|
|
||||||
|
_part.active = False
|
||||||
|
_part.save()
|
||||||
|
|
||||||
|
response = self.get(url, data=query_data)
|
||||||
|
|
||||||
|
# As the part is not active, only 3 panels left
|
||||||
|
self.assertEqual(3, len(response.data))
|
||||||
|
|
||||||
|
# Disable the "ENABLE_PART_PANELS" setting, and try again
|
||||||
|
plugin.set_setting('ENABLE_PART_PANELS', False)
|
||||||
|
|
||||||
|
response = self.get(url, data=query_data)
|
||||||
|
|
||||||
|
# There should still be 3 panels
|
||||||
|
self.assertEqual(3, len(response.data))
|
||||||
|
|
||||||
|
# Check for the correct panel names
|
||||||
|
self.assertEqual(response.data[0]['name'], 'sample_panel')
|
||||||
|
self.assertIn('content', response.data[0])
|
||||||
|
self.assertNotIn('source', response.data[0])
|
||||||
|
|
||||||
|
self.assertEqual(response.data[1]['name'], 'broken_panel')
|
||||||
|
self.assertEqual(response.data[1]['source'], '/this/does/not/exist.js')
|
||||||
|
self.assertNotIn('content', response.data[1])
|
||||||
|
|
||||||
|
self.assertEqual(response.data[2]['name'], 'dynamic_panel')
|
||||||
|
self.assertEqual(response.data[2]['source'], '/static/plugin/sample_panel.js')
|
||||||
|
self.assertNotIn('content', response.data[2])
|
||||||
|
|
||||||
|
# Next, disable the global setting for UI integration
|
||||||
|
InvenTreeSetting.set_setting(
|
||||||
|
'ENABLE_PLUGINS_INTERFACE', False, change_user=None
|
||||||
|
)
|
||||||
|
|
||||||
|
response = self.get(url, data=query_data)
|
||||||
|
|
||||||
|
# There should be no panels available
|
||||||
|
self.assertEqual(0, len(response.data))
|
||||||
|
|
||||||
|
# Set the setting back to True for subsequent tests
|
||||||
|
InvenTreeSetting.set_setting('ENABLE_PLUGINS_INTERFACE', True, change_user=None)
|
||||||
|
|
||||||
|
def test_ui_features(self):
|
||||||
|
"""Test that the sample UI plugin provides custom features."""
|
||||||
|
template_editor_url = reverse(
|
||||||
|
'api-plugin-ui-feature-list', kwargs={'feature': 'template_editor'}
|
||||||
|
)
|
||||||
|
template_preview_url = reverse(
|
||||||
|
'api-plugin-ui-feature-list', kwargs={'feature': 'template_preview'}
|
||||||
|
)
|
||||||
|
|
||||||
|
query_data_label = {'template_type': 'labeltemplate', 'template_model': 'part'}
|
||||||
|
query_data_report = {
|
||||||
|
'template_type': 'reporttemplate',
|
||||||
|
'template_model': 'part',
|
||||||
|
}
|
||||||
|
|
||||||
|
# Request custom template editor information
|
||||||
|
response = self.get(template_editor_url, data=query_data_label)
|
||||||
|
self.assertEqual(1, len(response.data))
|
||||||
|
|
||||||
|
response = self.get(template_editor_url, data=query_data_report)
|
||||||
|
self.assertEqual(0, len(response.data))
|
||||||
|
|
||||||
|
response = self.get(template_preview_url, data=query_data_report)
|
||||||
|
self.assertEqual(1, len(response.data))
|
||||||
|
|
||||||
|
# Check for the correct feature details here
|
||||||
|
self.assertEqual(response.data[0]['feature_type'], 'template_preview')
|
||||||
|
self.assertDictEqual(
|
||||||
|
response.data[0]['options'],
|
||||||
|
{
|
||||||
|
'key': 'sample-template-preview',
|
||||||
|
'title': 'Sample Template Preview',
|
||||||
|
'icon': 'category',
|
||||||
|
},
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
response.data[0]['source'],
|
||||||
|
'/static/plugin/sample_template.js:getTemplatePreview',
|
||||||
|
)
|
||||||
|
|
||||||
|
# Next, disable the global setting for UI integration
|
||||||
|
InvenTreeSetting.set_setting(
|
||||||
|
'ENABLE_PLUGINS_INTERFACE', False, change_user=None
|
||||||
|
)
|
||||||
|
|
||||||
|
response = self.get(template_editor_url, data=query_data_label)
|
||||||
|
|
||||||
|
# There should be no features available
|
||||||
|
self.assertEqual(0, len(response.data))
|
||||||
|
|
||||||
|
# Set the setting back to True for subsequent tests
|
||||||
|
InvenTreeSetting.set_setting('ENABLE_PLUGINS_INTERFACE', True, change_user=None)
|
@ -2,6 +2,7 @@ export function getTemplateEditor({ featureContext, pluginContext }) {
|
|||||||
const { ref } = featureContext;
|
const { ref } = featureContext;
|
||||||
console.log("Template editor feature was called with", featureContext, pluginContext);
|
console.log("Template editor feature was called with", featureContext, pluginContext);
|
||||||
const t = document.createElement("textarea");
|
const t = document.createElement("textarea");
|
||||||
|
t.id = 'sample-template-editor-textarea';
|
||||||
t.rows = 25;
|
t.rows = 25;
|
||||||
t.cols = 60;
|
t.cols = 60;
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { test } from './baseFixtures.js';
|
import { expect, test } from './baseFixtures.js';
|
||||||
import { baseUrl } from './defaults.js';
|
import { baseUrl } from './defaults.js';
|
||||||
import { doQuickLogin } from './login.js';
|
import { doQuickLogin } from './login.js';
|
||||||
|
|
||||||
@ -104,5 +104,33 @@ test('PUI - Report Editing', async ({ page }) => {
|
|||||||
|
|
||||||
await page.getByText('The preview has been updated').waitFor();
|
await page.getByText('The preview has been updated').waitFor();
|
||||||
|
|
||||||
|
// Test plugin provided editors
|
||||||
|
await page.getByRole('tab', { name: 'Sample Template Editor' }).click();
|
||||||
|
const textarea = page.locator('#sample-template-editor-textarea');
|
||||||
|
const textareaValue = await textarea.inputValue();
|
||||||
|
expect(textareaValue).toContain(
|
||||||
|
`<img class='qr' alt="{% trans 'QR Code' %}" src='{% qrcode qr_data %}'>`
|
||||||
|
);
|
||||||
|
textarea.fill(textareaValue + '\nHello world');
|
||||||
|
|
||||||
|
// Switch back and forth to see if the changed contents get correctly passed between the hooks
|
||||||
|
await page.getByRole('tab', { name: 'Code', exact: true }).click();
|
||||||
|
await page.getByRole('tab', { name: 'Sample Template Editor' }).click();
|
||||||
|
const newTextareaValue = await page
|
||||||
|
.locator('#sample-template-editor-textarea')
|
||||||
|
.inputValue();
|
||||||
|
expect(newTextareaValue).toMatch(/\nHello world$/);
|
||||||
|
|
||||||
|
// Test plugin provided previews
|
||||||
|
await page.getByRole('tab', { name: 'Sample Template Preview' }).click();
|
||||||
|
await page.getByRole('heading', { name: 'Hello world' }).waitFor();
|
||||||
|
const consoleLogPromise = page.waitForEvent('console');
|
||||||
|
await page
|
||||||
|
.getByLabel('split-button-preview-options', { exact: true })
|
||||||
|
.click();
|
||||||
|
const msg = (await consoleLogPromise).args();
|
||||||
|
expect(await msg[0].jsonValue()).toBe('updatePreview');
|
||||||
|
expect((await msg[1].jsonValue())[0]).toBe(newTextareaValue);
|
||||||
|
|
||||||
await page.context().close();
|
await page.context().close();
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user