2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-04-28 03:26:45 +00:00
InvenTree/InvenTree/plugin/base/label/test_label_mixin.py
Oliver b9fd263899
Docker improvements (#3042)
* Simplified dockerfile

- Changed from alpine to python:slim
- Removed some database libs (because we *connect* to a db, not host it)

* - Add gettext as required package
- Only create inventree user as part of production build (leave admin access for dev build)

* Tweaks for tasks.py

* Fix user permissions (drop to inventree user)

* Drop to the 'inventree' user level as part of init.sh

- As we have mounted volumes at 'run time' we need to ensure that the inventree user has correct permissions!
- Ref: https://stackoverflow.com/questions/39397548/how-to-give-non-root-user-in-docker-container-access-to-a-volume-mounted-on-the

* Adjust user setup

- Only drop to non-root user as part of "production" build
- Mounted external volumes make it tricky when in the dev build
- Might want to revisit this later on

* More dockerfile changes

- reduce required system packages
-

* Add new docker github workflow

* Print some more debug

* GITHUB_BASE_REF

* Add gnupg to base requirements

* Improve debug output during testing

* Refactoring updates for label printing API

- Update weasyprint version to 55.0
- Generate labels as pdf files
- Provide filename to label printing plugin
- Additional unit testing
- Improve extraction of some hidden debug data during TESTING
- Fix a spelling mistake (notifaction -> notification)

* Working on github action

* More testing

* Add requirement for pdf2image

* Fix label printing plugin and update unit testing

* Add required packages for CI

* Move docker files to the top level directory

- This allows us to build the production image directly from soure
- Don't need to re-download the source code from github
- Note: The docker install guide will need to be updated!

* Fix for docker ci file

* Print GIT SHA

* Bake git information into the production image

* Add some exta docstrings to dockerfile

* Simplify version check script

* Extract git commit info

* Extract docker tag from check_version.py

* Newline

* More work on the docker workflow

* Dockerfile fixes

- Directory / path issues

* Dockerfile fixes

- Directory / path issues

* Ignore certain steps on a pull request

* Add poppler-utils to CI

* Consolidate version check into existing CI file

* Don't run docker workflow on pull request

* Pass docker image tag through to the build

Also check .j2k files

* Add supervisord.conf example file back in

* Remove --no-cache-dir option from pip install
2022-05-29 09:40:37 +10:00

228 lines
7.2 KiB
Python

"""Unit tests for the label printing mixin"""
import os
from django.apps import apps
from django.urls import reverse
from PIL import Image
from common.models import InvenTreeSetting
from InvenTree.api_tester import InvenTreeAPITestCase
from label.models import PartLabel, StockItemLabel, StockLocationLabel
from part.models import Part
from plugin.base.label.mixins import LabelPrintingMixin
from plugin.helpers import MixinNotImplementedError
from plugin.plugin import InvenTreePlugin
from plugin.registry import registry
from stock.models import StockItem, StockLocation
class LabelMixinTests(InvenTreeAPITestCase):
"""Test that the Label mixin operates correctly"""
fixtures = [
'category',
'part',
'location',
'stock',
]
roles = 'all'
def do_activate_plugin(self):
"""Activate the 'samplelabel' plugin"""
config = registry.get_plugin('samplelabel').plugin_config()
config.active = True
config.save()
def do_url(self, parts, plugin_ref, label, url_name: str = 'api-part-label-print', url_single: str = 'part', invalid: bool = False):
"""Generate an URL to print a label"""
# Construct URL
kwargs = {}
if label:
kwargs["pk"] = label.pk
url = reverse(url_name, kwargs=kwargs)
# Append part filters
if not parts:
pass
elif len(parts) == 1:
url += f'?{url_single}={parts[0].pk}'
elif len(parts) > 1:
url += '?' + '&'.join([f'{url_single}s={item.pk}' for item in parts])
# Append an invalid item
if invalid:
url += f'&{url_single}{"s" if len(parts) > 1 else ""}=abc'
# Append plugin reference
if plugin_ref:
url += f'&plugin={plugin_ref}'
return url
def test_wrong_implementation(self):
"""Test that a wrong implementation raises an error"""
class WrongPlugin(LabelPrintingMixin, InvenTreePlugin):
pass
with self.assertRaises(MixinNotImplementedError):
plugin = WrongPlugin()
plugin.print_label(filename='test')
def test_installed(self):
"""Test that the sample printing plugin is installed"""
# Get all label plugins
plugins = registry.with_mixin('labels')
self.assertEqual(len(plugins), 1)
# But, it is not 'active'
plugins = registry.with_mixin('labels', active=True)
self.assertEqual(len(plugins), 0)
def test_api(self):
"""Test that we can filter the API endpoint by mixin"""
url = reverse('api-plugin-list')
# Try POST (disallowed)
response = self.client.post(url, {})
self.assertEqual(response.status_code, 405)
response = self.client.get(
url,
{
'mixin': 'labels',
'active': True,
}
)
# No results matching this query!
self.assertEqual(len(response.data), 0)
# What about inactive?
response = self.client.get(
url,
{
'mixin': 'labels',
'active': False,
}
)
self.assertEqual(len(response.data), 0)
self.do_activate_plugin()
# Should be available via the API now
response = self.client.get(
url,
{
'mixin': 'labels',
'active': True,
}
)
self.assertEqual(len(response.data), 1)
data = response.data[0]
self.assertEqual(data['key'], 'samplelabel')
def test_printing_process(self):
"""Test that a label can be printed"""
# Ensure the labels were created
apps.get_app_config('label').create_labels()
# Lookup references
part = Part.objects.first()
plugin_ref = 'samplelabel'
label = PartLabel.objects.first()
url = self.do_url([part], plugin_ref, label)
# Non-exsisting plugin
response = self.get(f'{url}123', expected_code=404)
self.assertIn(f'Plugin \'{plugin_ref}123\' not found', str(response.content, 'utf8'))
# Inactive plugin
response = self.get(url, expected_code=400)
self.assertIn(f'Plugin \'{plugin_ref}\' is not enabled', str(response.content, 'utf8'))
# Active plugin
self.do_activate_plugin()
# Print one part
self.get(url, expected_code=200)
# Print multiple parts
self.get(self.do_url(Part.objects.all()[:2], plugin_ref, label), expected_code=200)
# Print multiple parts without a plugin
self.get(self.do_url(Part.objects.all()[:2], None, label), expected_code=200)
# Print multiple parts without a plugin in debug mode
InvenTreeSetting.set_setting('REPORT_DEBUG_MODE', True, None)
response = self.get(self.do_url(Part.objects.all()[:2], None, label), expected_code=200)
self.assertIn('@page', str(response.content))
# Print no part
self.get(self.do_url(None, plugin_ref, label), expected_code=400)
# Test that the labels have been printed
# The sample labelling plugin simply prints to file
self.assertTrue(os.path.exists('label.pdf'))
# Read the raw .pdf data - ensure it contains some sensible information
with open('label.pdf', 'rb') as f:
pdf_data = str(f.read())
self.assertIn('WeasyPrint', pdf_data)
# Check that the .png file has already been created
self.assertTrue(os.path.exists('label.png'))
# And that it is a valid image file
Image.open('label.png')
def test_printing_endpoints(self):
"""Cover the endpoints not covered by `test_printing_process`"""
plugin_ref = 'samplelabel'
# Activate the label components
apps.get_app_config('label').create_labels()
self.do_activate_plugin()
def run_print_test(label, qs, url_name, url_single):
"""Run tests on single and multiple page printing
Args:
label (_type_): class of the label
qs (_type_): class of the base queryset
url_name (_type_): url for endpoints
url_single (_type_): item lookup reference
"""
label = label.objects.first()
qs = qs.objects.all()
# List endpoint
self.get(self.do_url(None, None, None, f'{url_name}-list', url_single), expected_code=200)
# List endpoint with filter
self.get(self.do_url(qs[:2], None, None, f'{url_name}-list', url_single, invalid=True), expected_code=200)
# Single page printing
self.get(self.do_url(qs[:1], plugin_ref, label, f'{url_name}-print', url_single), expected_code=200)
# Multi page printing
self.get(self.do_url(qs[:2], plugin_ref, label, f'{url_name}-print', url_single), expected_code=200)
# Test StockItemLabels
run_print_test(StockItemLabel, StockItem, 'api-stockitem-label', 'item')
# Test StockLocationLabels
run_print_test(StockLocationLabel, StockLocation, 'api-stocklocation-label', 'location')
# Test PartLabels
run_print_test(PartLabel, Part, 'api-part-label', 'part')