--- /dev/null
+# Copyright (C) 2024 The Meme Factory, Inc. http://www.karlpinc.com/
+
+# This file is part of ${component}.
+#
+# This program is free software: you can redistribute it and/or
+# modify it under the terms of the GNU Affero General Public License
+# as published by the Free Software Foundation, either version 3 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public
+# License along with this program. If not, see
+# <http://www.gnu.org/licenses/>.
+#
+
+# Karl O. Pinc <kop@karlpinc.com>
+
+import mako.lookup
+import mako.template
+import pytest
+import pgwui_core.constants
+import pgwui_server.pgwui_server
+import pgwui_develop.testing
+import pyramid.testing
+
+# A dict of "standard" settings
+pgwui_settings = {'dry_run': False,
+ '${component.lower()}':
+ {'menu_label': 'Test menu label'},
+ }
+config = pgwui_server.pgwui_server.pgwui_server_config(
+ {'pgwui': pgwui_settings,
+ 'session.secret': '1234567890123456789012345678901234567890'})
+# pgwui_upload_core.pgwui_upload_core.set_upload_response() copies the
+# particular upload settings to a name ('upload_settings') used by
+# pgwui_upload_core. So we need all the "upload core" settings under
+# that key. But this must happen after the config is checked for
+# validity since there is no 'upload_settings' component/setting.
+# All this is only necessary when testing templates that inherit
+# from pgwui_upload_core.templates/upload.mak, because that template
+# expects these values.
+config.get_settings()[
+ 'pgwui']['upload_settings'] = {'null': 'choice-yes',
+ 'trim': 'choice-yes',
+ 'file_format': 'csv',
+ 'literal_column_headings': 'choice-yes'
+ }
+request = pyramid.testing.DummyRequest()
+request.registry = config.registry
+
+stock_template_args = {
+ 'pgwui': config.get_settings()['pgwui'],
+ 'havecreds': False,
+ 'errors': [],
+ 'hosts': 'localhost',
+ 'db': 'template1',
+ 'user': '',
+ 'csrf_token': 'somecsrftoken',
+ 'filename': '',
+ 'db_changed': '',
+ 'csv_value': pgwui_core.constants.CSV,
+ 'tab_value': pgwui_core.constants.TAB,
+ 'csv_checked': pgwui_core.constants.CHECKED,
+ 'tab_checked': pgwui_core.constants.UNCHECKED,
+ 'upload_null': pgwui_core.constants.CHECKED,
+ 'null_rep': '',
+ 'trim_upload': pgwui_core.constants.CHECKED,
+ 'literal_col_headings': pgwui_core.constants.UNCHECKED,
+}
+
+# The templates to test
+TEMPLATES = ['${short_name}.mak']
+logged_in_args = pgwui_develop.testing.update_copy(
+ stock_template_args, {'havecreds': True})
+
+# Add the request to all the arguments.
+# (The request won't deepcopy, so we don't try.)
+stock_template_args['request'] = request
+logged_in_args['request'] = request
+
+# The variables with which to test each template
+TEMPLATE_ARGS = {
+ '${short_name}.mak':
+ [stock_template_args,
+ logged_in_args],
+}
+
+# Transform TEMPLATE_ARGS into something pytest can use with parametrize.
+parameter_args = []
+for tfile, values in iter(TEMPLATE_ARGS.items()):
+ for value in values:
+ parameter_args.append((tfile, value))
+
+# All imports are through asset paths, which become fully qualified paths.
+lookup_dirs = mako.lookup.TemplateLookup(directories=['/'])
+
+
+# Template rendering tests
+
+@pytest.mark.parametrize('tfile,values', parameter_args)
+def test_templates(tfile, values):
+ '''All the templates render without error
+ '''
+ template = mako.template.Template(
+ filename=f'src/${component.lower()}/templates/{tfile}',
+ lookup=lookup_dirs)
+ template.render(**values)
# See: https://pytest-cov.readthedocs.io/en/latest/plugins.html
+import copy
+import deepdiff
import pytest
import sys
# Test functions
#
-# ignore_depreciation_warnings()
+# update_copy()
#
+def test_update_copy():
+ '''Deep copies a dict, then updates the copy
+ '''
+ test_dict = {'outer': {'inner.key': 'inner value'},
+ 'outer.key': 'outer value'}
+ update_dict = {'updated_key': 'updated value',
+ 'outer.key': 'updated outer value'}
+ copied_dict = copy.deepcopy(test_dict)
+ copied_dict.update(update_dict)
+
+ result_dict = testing.update_copy(test_dict, update_dict)
+
+ # Shallow copy tests
+ assert result_dict != test_dict
+ assert result_dict == copied_dict
+
+ assert deepdiff.DeepDiff(
+ result_dict, copied_dict, threshold_to_diff_deeper=1.0) == {}
+ # Deep copy tests
+ copy2 = copy.deepcopy(test_dict)
+ copy2.update({'outer': {}})
+ assert result_dict != copy2
+ assert deepdiff.DeepDiff(
+ result_dict, copy2, threshold_to_diff_deeper=1.0) != {}
+
+
+#
+# ignore_depreciation_warnings()
+#
@pytest.mark.parametrize(
('ignore', 'warn_cnt'),
[pytest.param(