InvenTree/InvenTree/plugin/samples/integration/test_validation_sample.py
Oliver 2b9816d1a3
[Plugin] Enhanced custom validation (#6410)
* Use registry.get_plugin()

- Instead of registry.plugins.get()
- get_plugin checks registry hash
- performs registry reload if necessary

* Add PluginValidationMixin class

- Allows the entire model to be validated via plugins
- Called on model.full_clean()
- Called on model.save()

* Update Validation sample plugin

* Fix for InvenTreeTree models

* Refactor build.models

- Expose models to plugin validation

* Update stock.models

* Update more models

- common.models
- company.models

* Update more models

- label.models
- order.models
- part.models

* More model updates

* Update docs

* Fix for potential plugin edge case

- plugin slug is globally unique
- do not use get_or_create with two lookup fields
- will throw an IntegrityError if you change the name of a plugin

* Inherit DiffMixin into PluginValidationMixin

- Allows us to pass model diffs through to validation
- Plugins can validate based on what has *changed*

* Update documentation

* Add get_plugin_config helper function

* Bug fix

* Bug fix

* Update plugin hash when calling set_plugin_state

* Working on unit testing

* More unit testing

* Move get_plugin_config into registry.py

* Move extract_int into InvenTree.helpers

* Fix log formatting

* Update model definitions

- Ensure there are no changes to the migrations

* Comment out format line

* Fix access to get_plugin_config

* Fix tests for SimpleActionPlugin

* More unit test fixes
2024-02-06 22:00:22 +11:00

116 lines
3.4 KiB
Python

"""Unit tests for the SampleValidatorPlugin class."""
from django.core.exceptions import ValidationError
import part.models
from InvenTree.unit_test import InvenTreeTestCase
from plugin.registry import registry
class SampleValidatorPluginTest(InvenTreeTestCase):
"""Tests for the SampleValidatonPlugin class."""
fixtures = ['category', 'location']
def setUp(self):
"""Set up the test environment."""
cat = part.models.PartCategory.objects.first()
self.part = part.models.Part.objects.create(
name='TestPart', category=cat, description='A test part', component=True
)
self.assembly = part.models.Part.objects.create(
name='TestAssembly',
category=cat,
description='A test assembly',
component=False,
assembly=True,
)
self.bom_item = part.models.BomItem.objects.create(
part=self.assembly, sub_part=self.part, quantity=1
)
def get_plugin(self):
"""Return the SampleValidatorPlugin instance."""
return registry.get_plugin('validator', active=True)
def enable_plugin(self, en: bool):
"""Enable or disable the SampleValidatorPlugin."""
registry.set_plugin_state('validator', en)
def test_validate_model_instance(self):
"""Test the validate_model_instance function."""
# First, ensure that the plugin is disabled
self.enable_plugin(False)
plg = self.get_plugin()
self.assertIsNone(plg)
# Set the BomItem quantity to a non-integer value
# This should pass, as the plugin is currently disabled
self.bom_item.quantity = 3.14159
self.bom_item.save()
# Next, check that we can make a part instance description shorter
prt = part.models.Part.objects.first()
prt.description = prt.description[:-1]
prt.save()
# Now, enable the plugin
self.enable_plugin(True)
plg = self.get_plugin()
self.assertIsNotNone(plg)
plg.set_setting('BOM_ITEM_INTEGER', True)
self.bom_item.quantity = 3.14159
with self.assertRaises(ValidationError):
self.bom_item.save()
# Now, disable the plugin setting
plg.set_setting('BOM_ITEM_INTEGER', False)
self.bom_item.quantity = 3.14159
self.bom_item.save()
# Test that we *cannot* set a part description to a shorter value
prt.description = prt.description[:-1]
with self.assertRaises(ValidationError):
prt.save()
self.enable_plugin(False)
def test_validate_part_name(self):
"""Test the validate_part_name function."""
self.enable_plugin(True)
plg = self.get_plugin()
self.assertIsNotNone(plg)
# Set the part description short
self.part.description = 'x'
with self.assertRaises(ValidationError):
self.part.save()
self.enable_plugin(False)
self.part.save()
def test_validate_ipn(self):
"""Test the validate_ipn function."""
self.enable_plugin(True)
plg = self.get_plugin()
self.assertIsNotNone(plg)
self.part.IPN = 'LMNOP'
plg.set_setting('IPN_MUST_CONTAIN_Q', False)
self.part.save()
plg.set_setting('IPN_MUST_CONTAIN_Q', True)
with self.assertRaises(ValidationError):
self.part.save()
self.part.IPN = 'LMNOPQ'
self.part.save()