287 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			287 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # -*- coding: utf-8; -*-
 | |
| 
 | |
| import datetime
 | |
| from unittest.mock import patch, MagicMock
 | |
| 
 | |
| from wuttjamaican.reports import Report
 | |
| 
 | |
| import colander
 | |
| from pyramid.httpexceptions import HTTPNotFound
 | |
| 
 | |
| from wuttaweb.views import reports as mod
 | |
| from wuttaweb.testing import WebTestCase
 | |
| 
 | |
| 
 | |
| class SomeRandomReport(Report):
 | |
|     """
 | |
|     This report shows something random.
 | |
|     """
 | |
| 
 | |
|     report_key = "testing_some_random"
 | |
|     report_title = "Random Test Report"
 | |
| 
 | |
|     def add_params(self, schema):
 | |
| 
 | |
|         schema.add(
 | |
|             colander.SchemaNode(colander.String(), name="foo", missing=colander.null)
 | |
|         )
 | |
| 
 | |
|         schema.add(
 | |
|             colander.SchemaNode(
 | |
|                 colander.Date(), name="start_date", missing=colander.null
 | |
|             )
 | |
|         )
 | |
| 
 | |
|     def get_output_columns(self):
 | |
|         return ["foo"]
 | |
| 
 | |
|     def make_data(self, params, **kwargs):
 | |
|         return {
 | |
|             "output_title": "Testing Output",
 | |
|             "data": [{"foo": "bar"}],
 | |
|         }
 | |
| 
 | |
| 
 | |
| class TestReportViews(WebTestCase):
 | |
| 
 | |
|     def make_view(self):
 | |
|         return mod.ReportView(self.request)
 | |
| 
 | |
|     def test_includeme(self):
 | |
|         self.pyramid_config.include("wuttaweb.views.reports")
 | |
| 
 | |
|     def test_get_grid_data(self):
 | |
|         view = self.make_view()
 | |
|         providers = dict(self.app.providers)
 | |
|         providers["wuttatest"] = MagicMock(report_modules=["tests.views.test_reports"])
 | |
|         with patch.object(self.app, "providers", new=providers):
 | |
| 
 | |
|             data = view.get_grid_data()
 | |
|             self.assertIsInstance(data, list)
 | |
|             self.assertTrue(data)  # 1+ reports
 | |
| 
 | |
|     def test_normalize_report(self):
 | |
|         view = self.make_view()
 | |
|         report = SomeRandomReport(self.config)
 | |
|         normal = view.normalize_report(report)
 | |
|         help_text = normal.pop("help_text").strip()
 | |
|         self.assertEqual(help_text, "This report shows something random.")
 | |
|         self.assertEqual(
 | |
|             normal,
 | |
|             {
 | |
|                 "report_key": "testing_some_random",
 | |
|                 "report_title": "Random Test Report",
 | |
|             },
 | |
|         )
 | |
| 
 | |
|     def test_configure_grid(self):
 | |
|         view = self.make_view()
 | |
|         grid = view.make_model_grid()
 | |
|         self.assertIn("report_title", grid.searchable_columns)
 | |
|         self.assertIn("help_text", grid.searchable_columns)
 | |
| 
 | |
|     def test_get_instance(self):
 | |
|         view = self.make_view()
 | |
|         providers = {
 | |
|             "wuttatest": MagicMock(report_modules=["tests.views.test_reports"]),
 | |
|         }
 | |
|         with patch.object(self.app, "providers", new=providers):
 | |
| 
 | |
|             # normal
 | |
|             with patch.object(
 | |
|                 self.request, "matchdict", new={"report_key": "testing_some_random"}
 | |
|             ):
 | |
|                 report = view.get_instance()
 | |
|                 self.assertIsInstance(report, dict)
 | |
|                 self.assertEqual(report["report_key"], "testing_some_random")
 | |
|                 self.assertEqual(report["report_title"], "Random Test Report")
 | |
| 
 | |
|             # not found
 | |
|             with patch.object(
 | |
|                 self.request, "matchdict", new={"report_key": "this-should_notEXIST"}
 | |
|             ):
 | |
|                 self.assertRaises(HTTPNotFound, view.get_instance)
 | |
| 
 | |
|     def test_get_instance_title(self):
 | |
|         view = self.make_view()
 | |
|         result = view.get_instance_title({"report_title": "whatever"})
 | |
|         self.assertEqual(result, "whatever")
 | |
| 
 | |
|     def test_view(self):
 | |
|         self.pyramid_config.add_route("home", "/")
 | |
|         self.pyramid_config.add_route("login", "/auth/login")
 | |
|         self.pyramid_config.add_route("reports", "/reports/")
 | |
|         self.pyramid_config.add_route("reports.view", "/reports/{report_key}")
 | |
|         view = self.make_view()
 | |
|         providers = dict(self.app.providers)
 | |
|         providers["wuttatest"] = MagicMock(report_modules=["tests.views.test_reports"])
 | |
|         with patch.object(self.app, "providers", new=providers):
 | |
|             with patch.object(
 | |
|                 self.request, "matchdict", new={"report_key": "testing_some_random"}
 | |
|             ):
 | |
| 
 | |
|                 # initial view
 | |
|                 response = view.view()
 | |
|                 self.assertEqual(response.status_code, 200)
 | |
|                 # nb. there's a button in there somewhere, but no output title
 | |
|                 self.assertIn("Run Report", response.text)
 | |
|                 self.assertNotIn("Testing Output", response.text)
 | |
| 
 | |
|                 # run the report
 | |
|                 with patch.object(
 | |
|                     self.request,
 | |
|                     "GET",
 | |
|                     new={
 | |
|                         "__start__": "start_date:mapping",
 | |
|                         "date": "2025-01-11",
 | |
|                         "__end__": "start_date",
 | |
|                     },
 | |
|                 ):
 | |
|                     response = view.view()
 | |
|                     self.assertEqual(response.status_code, 200)
 | |
|                     # nb. there's a button in there somewhere, *and* an output title
 | |
|                     self.assertIn("Run Report", response.text)
 | |
|                     self.assertIn("Testing Output", response.text)
 | |
| 
 | |
|     def test_configure_form(self):
 | |
|         view = self.make_view()
 | |
|         providers = dict(self.app.providers)
 | |
|         providers["wuttatest"] = MagicMock(report_modules=["tests.views.test_reports"])
 | |
|         with patch.object(self.app, "providers", new=providers):
 | |
| 
 | |
|             with patch.object(
 | |
|                 self.request, "matchdict", new={"report_key": "testing_some_random"}
 | |
|             ):
 | |
|                 report = view.get_instance()
 | |
|                 form = view.make_model_form(report)
 | |
|                 self.assertIn("help_text", form.readonly_fields)
 | |
|                 self.assertIn("foo", form)
 | |
| 
 | |
|     def test_normalize_columns(self):
 | |
|         view = self.make_view()
 | |
| 
 | |
|         columns = view.normalize_columns(["foo"])
 | |
|         self.assertEqual(
 | |
|             columns,
 | |
|             [
 | |
|                 {"name": "foo", "label": "foo"},
 | |
|             ],
 | |
|         )
 | |
| 
 | |
|         columns = view.normalize_columns([{"name": "foo"}])
 | |
|         self.assertEqual(
 | |
|             columns,
 | |
|             [
 | |
|                 {"name": "foo", "label": "foo"},
 | |
|             ],
 | |
|         )
 | |
| 
 | |
|         columns = view.normalize_columns([{"name": "foo", "label": "FOO"}])
 | |
|         self.assertEqual(
 | |
|             columns,
 | |
|             [
 | |
|                 {"name": "foo", "label": "FOO"},
 | |
|             ],
 | |
|         )
 | |
| 
 | |
|         columns = view.normalize_columns(
 | |
|             [{"name": "foo", "label": "FOO", "numeric": True}]
 | |
|         )
 | |
|         self.assertEqual(
 | |
|             columns,
 | |
|             [
 | |
|                 {"name": "foo", "label": "FOO", "numeric": True},
 | |
|             ],
 | |
|         )
 | |
| 
 | |
|     def test_run_report(self):
 | |
|         view = self.make_view()
 | |
|         providers = dict(self.app.providers)
 | |
|         providers["wuttatest"] = MagicMock(report_modules=["tests.views.test_reports"])
 | |
|         with patch.object(self.app, "providers", new=providers):
 | |
| 
 | |
|             with patch.object(
 | |
|                 self.request, "matchdict", new={"report_key": "testing_some_random"}
 | |
|             ):
 | |
|                 report = view.report_handler.get_report("testing_some_random")
 | |
|                 normal = view.normalize_report(report)
 | |
|                 form = view.make_model_form(normal)
 | |
| 
 | |
|                 # typical
 | |
|                 context = view.run_report(report, {"form": form})
 | |
|                 self.assertEqual(
 | |
|                     sorted(context["report_params"]), ["foo", "start_date"]
 | |
|                 )
 | |
|                 self.assertEqual(
 | |
|                     context["report_data"],
 | |
|                     {
 | |
|                         "output_title": "Testing Output",
 | |
|                         "data": [{"foo": "bar"}],
 | |
|                     },
 | |
|                 )
 | |
|                 self.assertIn("report_generated", context)
 | |
| 
 | |
|                 # invalid params
 | |
|                 with patch.object(self.request, "GET", new={"start_date": "NOT_GOOD"}):
 | |
|                     context = view.run_report(report, {"form": form})
 | |
|                     self.assertNotIn("report_params", context)
 | |
|                     self.assertNotIn("report_data", context)
 | |
|                     self.assertNotIn("report_generated", context)
 | |
| 
 | |
|                 # custom formatter
 | |
|                 with patch.object(report, "get_output_columns") as get_output_columns:
 | |
|                     get_output_columns.return_value = [
 | |
|                         "foo",
 | |
|                         {
 | |
|                             "name": "start_date",
 | |
|                             "formatter": lambda val: "FORMATTED VALUE",
 | |
|                         },
 | |
|                     ]
 | |
| 
 | |
|                     with patch.object(report, "make_data") as make_data:
 | |
|                         make_data.return_value = [
 | |
|                             {"foo": "bar", "start_date": datetime.date(2025, 1, 11)},
 | |
|                         ]
 | |
| 
 | |
|                         context = view.run_report(report, {"form": form})
 | |
|                         get_output_columns.assert_called_once_with()
 | |
|                         self.assertEqual(len(context["report_columns"]), 2)
 | |
|                         self.assertEqual(context["report_columns"][0]["name"], "foo")
 | |
|                         self.assertEqual(
 | |
|                             context["report_columns"][1]["name"], "start_date"
 | |
|                         )
 | |
|                         self.assertEqual(
 | |
|                             context["report_data"],
 | |
|                             {
 | |
|                                 "output_title": "Random Test Report",
 | |
|                                 "data": [
 | |
|                                     {"foo": "bar", "start_date": "FORMATTED VALUE"}
 | |
|                                 ],
 | |
|                             },
 | |
|                         )
 | |
| 
 | |
|     def test_download_data(self):
 | |
|         view = self.make_view()
 | |
|         providers = dict(self.app.providers)
 | |
|         providers["wuttatest"] = MagicMock(report_modules=["tests.views.test_reports"])
 | |
|         with patch.object(self.app, "providers", new=providers):
 | |
|             with patch.object(
 | |
|                 self.request, "matchdict", new={"report_key": "testing_some_random"}
 | |
|             ):
 | |
| 
 | |
|                 params, columns, data = view.get_download_data()
 | |
|                 self.assertEqual(params, {})
 | |
|                 self.assertEqual(columns, [{"name": "foo", "label": "foo"}])
 | |
|                 self.assertEqual(
 | |
|                     data,
 | |
|                     {
 | |
|                         "output_title": "Testing Output",
 | |
|                         "data": [{"foo": "bar"}],
 | |
|                     },
 | |
|                 )
 | |
| 
 | |
|     def test_download_path(self):
 | |
|         view = self.make_view()
 | |
|         data = {"output_title": "My Report"}
 | |
|         path = view.get_download_path(data, "csv")
 | |
|         self.assertTrue(path.endswith("My Report.csv"))
 |