diff --git a/InvenTree/report/apps.py b/InvenTree/report/apps.py index 43c52b1997..21b3cc380e 100644 --- a/InvenTree/report/apps.py +++ b/InvenTree/report/apps.py @@ -19,7 +19,7 @@ class ReportConfig(AppConfig): This function is called whenever the report app is loaded """ - if canAppAccessDatabase(): + if canAppAccessDatabase(allow_test=True): self.create_default_test_reports() self.create_default_build_reports() diff --git a/InvenTree/report/tests.py b/InvenTree/report/tests.py index a2b5079b33..704f98fed0 100644 --- a/InvenTree/report/tests.py +++ b/InvenTree/report/tests.py @@ -1,2 +1,245 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals + +import os +import shutil + +from django.http.response import StreamingHttpResponse +from django.urls import reverse +from django.conf import settings + +from InvenTree.api_tester import InvenTreeAPITestCase + +import report.models as report_models +from common.models import InvenTreeUserSetting +from stock.models import StockItem +from build.models import Build + + +class ReportTest(InvenTreeAPITestCase): + + fixtures = [ + 'category', + 'part', + 'company', + 'location', + 'supplier_part', + 'stock', + 'stock_tests', + 'bom', + 'build', + ] + + model = None + list_url = None + detail_url = None + print_url = None + + def setUp(self): + super().setUp() + + def copyReportTemplate(self, filename, description): + """ + Copy the provided report template into the required media directory + """ + + src_dir = os.path.join( + os.path.dirname(os.path.realpath(__file__)), + 'templates', + 'report' + ) + + template_dir = os.path.join( + 'report', + 'inventree', + self.model.getSubdir(), + ) + + dst_dir = os.path.join( + settings.MEDIA_ROOT, + template_dir + ) + + if not os.path.exists(dst_dir): + os.makedirs(dst_dir, exist_ok=True) + + src_file = os.path.join(src_dir, filename) + dst_file = os.path.join(dst_dir, filename) + + if not os.path.exists(dst_file): + shutil.copyfile(src_file, dst_file) + + # Convert to an "internal" filename + db_filename = os.path.join( + template_dir, + filename + ) + + # Create a database entry for this report template! + self.model.objects.create( + name=os.path.splitext(filename)[0], + description=description, + template=db_filename, + enabled=True + ) + + def test_list_endpoint(self): + """ + Test that the LIST endpoint works for each report + """ + + if not self.list_url: + return + + url = reverse(self.list_url) + + response = self.get(url) + self.assertEqual(response.status_code, 200) + + reports = self.model.objects.all() + + n = len(reports) + + # API endpoint must return correct number of reports + self.assertEqual(len(response.data), n) + + # Filter by "enabled" status + response = self.get(url, {'enabled': True}) + self.assertEqual(len(response.data), n) + + response = self.get(url, {'enabled': False}) + self.assertEqual(len(response.data), 0) + + # Disable each report + for report in reports: + report.enabled = False + report.save() + + # Filter by "enabled" status + response = self.get(url, {'enabled': True}) + self.assertEqual(len(response.data), 0) + + response = self.get(url, {'enabled': False}) + self.assertEqual(len(response.data), n) + + +class TestReportTest(ReportTest): + + model = report_models.TestReport + + list_url = 'api-stockitem-testreport-list' + detail_url = 'api-stockitem-testreport-detail' + print_url = 'api-stockitem-testreport-print' + + def setUp(self): + + self.copyReportTemplate('inventree_test_report.html', 'stock item test report') + + return super().setUp() + + def test_print(self): + """ + Printing tests for the TestReport + """ + + report = self.model.objects.first() + + url = reverse(self.print_url, kwargs={'pk': report.pk}) + + # Try to print without providing a valid StockItem + response = self.get(url, expected_code=400) + + # Try to print with an invalid StockItem + response = self.get(url, {'item': 9999}, expected_code=400) + + # Now print with a valid StockItem + item = StockItem.objects.first() + + response = self.get(url, {'item': item.pk}) + + # Response should be a StreamingHttpResponse (PDF file) + self.assertEqual(type(response), StreamingHttpResponse) + + headers = response.headers + + self.assertEqual(headers['Content-Type'], 'application/pdf') + + +class BuildReportTest(ReportTest): + + model = report_models.BuildReport + + list_url = 'api-build-report-list' + detail_url = 'api-build-report-detail' + print_url = 'api-build-report-print' + + def setUp(self): + + self.copyReportTemplate('inventree_build_order.html', 'build order template') + + return super().setUp() + + def test_print(self): + """ + Printing tests for the BuildReport + """ + + report = self.model.objects.first() + + url = reverse(self.print_url, kwargs={'pk': report.pk}) + + # Try to print without providing a valid BuildOrder + response = self.get(url, expected_code=400) + + # Try to print with an invalid BuildOrder + response = self.get(url, {'build': 9999}, expected_code=400) + + # Now print with a valid BuildOrder + + build = Build.objects.first() + + response = self.get(url, {'build': build.pk}) + + self.assertEqual(type(response), StreamingHttpResponse) + + headers = response.headers + + self.assertEqual(headers['Content-Type'], 'application/pdf') + self.assertEqual(headers['Content-Disposition'], 'attachment; filename="report.pdf"') + + # Now, set the download type to be "inline" + inline = InvenTreeUserSetting.get_setting_object('REPORT_INLINE', self.user) + inline.value = True + inline.save() + + response = self.get(url, {'build': 1}) + headers = response.headers + self.assertEqual(headers['Content-Type'], 'application/pdf') + self.assertEqual(headers['Content-Disposition'], 'inline; filename="report.pdf"') + + +class BOMReportTest(ReportTest): + + model = report_models.BillOfMaterialsReport + + list_url = 'api-bom-report-list' + detail_url = 'api-bom-report-detail' + print_url = 'api-bom-report-print' + + +class POReportTest(ReportTest): + + model = report_models.PurchaseOrderReport + + list_url = 'api-po-report-list' + detail_url = 'api-po-report-detail' + print_url = 'api-po-report-print' + + +class SOReportTest(ReportTest): + + model = report_models.SalesOrderReport + + list_url = 'api-so-report-list' + detail_url = 'api-so-report-detail' + print_url = 'api-so-report-print' diff --git a/InvenTree/report/views.py b/InvenTree/report/views.py deleted file mode 100644 index a2b5079b33..0000000000 --- a/InvenTree/report/views.py +++ /dev/null @@ -1,2 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals