From 6389493c33f09005a1e92ec61db774ee74361289 Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 13 Mar 2024 12:36:06 +1100 Subject: [PATCH] Test key fix (#6685) * Fix for generateTestKey - Check for zero-length key * Ensure test template name would generate valid key * Add unit test * Improve generateTestKey method - Allow for non-latin chars * Update generateTestKey - Improve check for valid char --- InvenTree/InvenTree/helpers.py | 21 +++++++++++++++++---- InvenTree/part/models.py | 11 ++++++++++- InvenTree/part/test_part.py | 23 +++++++++++++++++++++++ 3 files changed, 50 insertions(+), 5 deletions(-) diff --git a/InvenTree/InvenTree/helpers.py b/InvenTree/InvenTree/helpers.py index d43a462f92..20fca9cf8f 100644 --- a/InvenTree/InvenTree/helpers.py +++ b/InvenTree/InvenTree/helpers.py @@ -87,11 +87,24 @@ def generateTestKey(test_name: str) -> str: key = test_name.strip().lower() key = key.replace(' ', '') - # Remove any characters that cannot be used to represent a variable - key = re.sub(r'[^a-zA-Z0-9_]', '', key) + def valid_char(char: str): + """Determine if a particular character is valid for use in a test key.""" + if not char.isprintable(): + return False - # If the key starts with a digit, prefix with an underscore - if key[0].isdigit(): + if char.isidentifier(): + return True + + if char.isalnum(): + return True + + return False + + # Remove any characters that cannot be used to represent a variable + key = ''.join([c for c in key if valid_char(c)]) + + # If the key starts with a non-identifier character, prefix with an underscore + if len(key) > 0 and not key[0].isidentifier(): key = '_' + key return key diff --git a/InvenTree/part/models.py b/InvenTree/part/models.py index c962ba3d81..b20eff7453 100644 --- a/InvenTree/part/models.py +++ b/InvenTree/part/models.py @@ -3428,6 +3428,13 @@ class PartTestTemplate(InvenTree.models.InvenTreeMetadataModel): self.key = helpers.generateTestKey(self.test_name) + if len(self.key) == 0: + raise ValidationError({ + 'test_name': _( + 'Invalid template name - must include at least one alphanumeric character' + ) + }) + self.validate_unique() super().clean() @@ -3445,7 +3452,9 @@ class PartTestTemplate(InvenTree.models.InvenTreeMetadataModel): if tests.exists(): raise ValidationError({ - 'test_name': _('Test with this name already exists for this part') + 'test_name': _( + 'Test template with the same key already exists for part' + ) }) super().validate_unique(exclude) diff --git a/InvenTree/part/test_part.py b/InvenTree/part/test_part.py index 98f9dc5410..369cada331 100644 --- a/InvenTree/part/test_part.py +++ b/InvenTree/part/test_part.py @@ -431,6 +431,29 @@ class TestTemplateTest(TestCase): self.assertEqual(variant.getTestTemplates().count(), n + 1) + def test_key_generation(self): + """Test the key generation method.""" + variant = Part.objects.get(pk=10004) + + invalid_names = ['', '+', '+++++++', ' ', '<>$&&&'] + + for name in invalid_names: + template = PartTestTemplate(part=variant, test_name=name) + with self.assertRaises(ValidationError): + template.clean() + + valid_names = [ + 'Собранный щит', + '!! 123 Собранный щит <><><> $$$$$ !!!', + '----hello world----', + 'Olá Mundo', + '我不懂中文', + ] + + for name in valid_names: + template = PartTestTemplate(part=variant, test_name=name) + template.clean() + class PartSettingsTest(InvenTreeTestCase): """Tests to ensure that the user-configurable default values work as expected.