# -*- 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'))