testdef: add snapshots (#88755)
gitea/wcs/pipeline/head There was a failure building this commit
Details
gitea/wcs/pipeline/head There was a failure building this commit
Details
This commit is contained in:
parent
6090b32990
commit
25cec5404e
|
@ -363,6 +363,55 @@ def test_tests_status_page_image_field(pub):
|
|||
resp.follow(status=404)
|
||||
|
||||
|
||||
def test_tests_history_page(pub):
|
||||
user = create_superuser(pub)
|
||||
|
||||
formdef = FormDef()
|
||||
formdef.name = 'test title'
|
||||
formdef.fields = [fields.StringField(id='1', varname='test_field', label='Test Field')]
|
||||
formdef.store()
|
||||
|
||||
formdata = formdef.data_class()()
|
||||
formdata.just_created()
|
||||
formdata.receipt_time = make_aware(datetime.datetime(2021, 1, 1, 0, 0))
|
||||
formdata.data['1'] = 'This is a test'
|
||||
formdata.user_id = user.id
|
||||
formdata.store()
|
||||
|
||||
testdef = TestDef.create_from_formdata(formdef, formdata)
|
||||
testdef.name = 'First test'
|
||||
testdef.store()
|
||||
|
||||
testdef.name = 'Changed test'
|
||||
testdef.store()
|
||||
|
||||
app = login(get_app(pub))
|
||||
|
||||
resp = app.get('/backoffice/forms/1/tests/1/')
|
||||
resp = resp.click('History')
|
||||
assert [x.attrib['class'] for x in resp.pyquery.find('.snapshots-list tr')] == ['new-day', 'collapsed']
|
||||
|
||||
# export snapshot
|
||||
resp_export = resp.click('Export', index=1)
|
||||
assert resp_export.content_type == 'application/x-wcs-snapshot'
|
||||
assert '>First test<' in resp_export.text
|
||||
|
||||
assert TestDef.count() == 1
|
||||
|
||||
# view snapshot
|
||||
resp = resp.click('View', index=1)
|
||||
assert '<h2>First test</h2>' in resp.text
|
||||
|
||||
# restore as new
|
||||
resp = app.get('/backoffice/forms/1/tests/1/history/')
|
||||
resp = resp.click('Restore')
|
||||
resp.form['action'] = 'as-new'
|
||||
resp = resp.form.submit('submit').follow()
|
||||
|
||||
assert TestDef.count() == 2
|
||||
assert '<h2>First test</h2>' in resp.text
|
||||
|
||||
|
||||
def test_tests_edit(pub):
|
||||
create_superuser(pub)
|
||||
user = pub.user_class(name='test user')
|
||||
|
|
|
@ -28,6 +28,9 @@ from wcs.admin.workflow_tests import WorkflowTestsDirectory
|
|||
from wcs.api import posted_json_data_to_formdata_data
|
||||
from wcs.backoffice.management import FormBackofficeEditPage, FormBackOfficeStatusPage
|
||||
from wcs.backoffice.pagination import pagination_links
|
||||
from wcs.backoffice.snapshots import SnapshotsDirectory
|
||||
from wcs.carddef import CardDef
|
||||
from wcs.formdef import FormDef
|
||||
from wcs.forms.common import FormStatusPage
|
||||
from wcs.qommon import _, misc, template
|
||||
from wcs.qommon.afterjobs import AfterJob
|
||||
|
@ -148,13 +151,19 @@ class TestPage(FormBackOfficeStatusPage):
|
|||
'duplicate',
|
||||
('workflow', 'workflow_tests'),
|
||||
('webservice-responses', 'webservice_responses'),
|
||||
('history', 'snapshots_dir'),
|
||||
]
|
||||
|
||||
def __init__(self, component, objectdef):
|
||||
def __init__(self, component, objectdef=None, instance=None):
|
||||
try:
|
||||
self.testdef = TestDef.get(component)
|
||||
self.testdef = instance or TestDef.get(component)
|
||||
except KeyError:
|
||||
raise TraversalError()
|
||||
|
||||
if not objectdef:
|
||||
klass = FormDef if self.testdef.object_type == 'formdefs' else CardDef
|
||||
objectdef = klass.get(self.testdef.object_id)
|
||||
|
||||
self.testdef.formdef = objectdef
|
||||
|
||||
filled = self.testdef.build_formdata(objectdef, include_fields=True)
|
||||
|
@ -162,6 +171,7 @@ class TestPage(FormBackOfficeStatusPage):
|
|||
|
||||
self.workflow_tests = WorkflowTestsDirectory(self.testdef, self.formdef)
|
||||
self.webservice_responses = WebserviceResponseDirectory(self.testdef)
|
||||
self.snapshots_dir = SnapshotsDirectory(self.testdef)
|
||||
|
||||
@property
|
||||
def edit_data(self):
|
||||
|
@ -391,7 +401,7 @@ class TestsDirectory(Directory):
|
|||
if not creation_mode_widget or creation_mode_widget.parse() == 'empty':
|
||||
testdef = TestDef.create_from_formdata(self.objectdef, self.objectdef.data_class()())
|
||||
testdef.name = form.get_widget('name').parse()
|
||||
testdef.agent_id = get_session().user
|
||||
testdef.agent_id = str(get_session().user)
|
||||
testdef.store()
|
||||
return redirect(testdef.get_admin_url() + 'edit-data/')
|
||||
else:
|
||||
|
@ -404,7 +414,7 @@ class TestsDirectory(Directory):
|
|||
add_workflow_tests=bool(creation_mode_widget.parse() == 'formdata-wf'),
|
||||
)
|
||||
testdef.name = form.get_widget('name').parse()
|
||||
testdef.agent_id = get_session().user
|
||||
testdef.agent_id = str(get_session().user)
|
||||
testdef.store()
|
||||
return redirect(testdef.get_admin_url())
|
||||
|
||||
|
|
|
@ -52,7 +52,8 @@ class SnapshotsDirectory(Directory):
|
|||
templates=['wcs/backoffice/snapshots.html'],
|
||||
context={
|
||||
'view': self,
|
||||
'form_has_tests': bool(TestDef.select_for_objectdef(self.obj)),
|
||||
'form_has_tests': self.object_type in ('formdef', 'carddef')
|
||||
and bool(TestDef.select_for_objectdef(self.obj)),
|
||||
},
|
||||
)
|
||||
|
||||
|
@ -261,7 +262,7 @@ class SnapshotsDirectory(Directory):
|
|||
current_date = None
|
||||
snapshots = get_publisher().snapshot_class.select_object_history(self.obj)
|
||||
test_results = TestResult.select(
|
||||
[Equal('object_type', self.obj.get_table_name()), Equal('object_id', self.obj.id)]
|
||||
[Equal('object_type', self.obj.get_table_name()), Equal('object_id', str(self.obj.id))]
|
||||
)
|
||||
test_results_by_id = {x.id: x for x in test_results}
|
||||
day_snapshot = None
|
||||
|
|
|
@ -578,6 +578,7 @@ class WcsPublisher(QommonPublisher):
|
|||
from wcs.data_sources import NamedDataSource
|
||||
from wcs.formdef import FormDef
|
||||
from wcs.mail_templates import MailTemplate
|
||||
from wcs.testdef import TestDef
|
||||
from wcs.workflows import Workflow
|
||||
from wcs.wscalls import NamedWsCall
|
||||
|
||||
|
@ -597,6 +598,7 @@ class WcsPublisher(QommonPublisher):
|
|||
MailTemplateCategory,
|
||||
CommentTemplateCategory,
|
||||
DataSourceCategory,
|
||||
TestDef,
|
||||
):
|
||||
if klass.xml_root_node == object_type:
|
||||
return klass
|
||||
|
|
|
@ -3640,12 +3640,12 @@ class Snapshot(SqlMixin, wcs.snapshots.Snapshot):
|
|||
@classmethod
|
||||
def select_object_history(cls, obj, clause=None):
|
||||
return cls.select(
|
||||
[Equal('object_type', obj.xml_root_node), Equal('object_id', obj.id)] + (clause or []),
|
||||
[Equal('object_type', obj.xml_root_node), Equal('object_id', str(obj.id))] + (clause or []),
|
||||
order_by='-timestamp',
|
||||
)
|
||||
|
||||
def is_from_object(self, obj):
|
||||
return self.object_type == obj.xml_root_node and self.object_id == obj.id
|
||||
return self.object_type == obj.xml_root_node and self.object_id == str(obj.id)
|
||||
|
||||
@classmethod
|
||||
def _row2ob(cls, row, **kwargs):
|
||||
|
@ -3676,7 +3676,7 @@ class Snapshot(SqlMixin, wcs.snapshots.Snapshot):
|
|||
)
|
||||
cur.execute(
|
||||
sql_statement,
|
||||
{'object_type': object_type, 'object_id': object_id, 'max_timestamp': max_timestamp},
|
||||
{'object_type': object_type, 'object_id': str(object_id), 'max_timestamp': max_timestamp},
|
||||
)
|
||||
row = cur.fetchone()
|
||||
cur.close()
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
<h3>{% trans "Navigation" %}</h3>
|
||||
<ul class="sidebar--buttons">
|
||||
<li><a class="button button-paragraph" rel="popup" href="edit">{% trans "Options" %}</a></li>
|
||||
<li><a class="button button-paragraph" href="history/">{% trans "History" %}</a></li>
|
||||
<li><a class="button button-paragraph" href="webservice-responses/">{% trans "Webservice responses" %}</a></li>
|
||||
<li><a class="button button-paragraph" href="inspect">{% trans "Inspect" %}</a></li>
|
||||
</ul>
|
||||
|
|
|
@ -60,6 +60,7 @@ class TestDefXmlProxy(XmlStorableObject):
|
|||
xml_root_node = 'testdef'
|
||||
_names = 'testdef'
|
||||
readonly = True
|
||||
backoffice_class = 'wcs.admin.tests.TestPage'
|
||||
|
||||
# prevent pytest from trying to collect this class
|
||||
__test__ = False
|
||||
|
@ -74,7 +75,7 @@ class TestDefXmlProxy(XmlStorableObject):
|
|||
'boolean': 'bool',
|
||||
'jsonb': 'jsonb',
|
||||
}
|
||||
excluded_fields = ['id', 'object_type', 'object_id']
|
||||
excluded_fields = ['id']
|
||||
extra_fields = [
|
||||
('_webservice_responses', 'webservice_responses'),
|
||||
('workflow_tests', 'workflow_tests'),
|
||||
|
@ -111,6 +112,7 @@ class TestDefXmlProxy(XmlStorableObject):
|
|||
|
||||
class TestDef(sql.TestDef):
|
||||
_names = 'testdef'
|
||||
xml_root_node = TestDefXmlProxy.xml_root_node
|
||||
|
||||
name = ''
|
||||
object_type = None # (formdef, carddef, etc.)
|
||||
|
@ -131,10 +133,14 @@ class TestDef(sql.TestDef):
|
|||
'tablerows',
|
||||
'ranked-items',
|
||||
)
|
||||
backoffice_class = 'wcs.admin.tests.TestPage'
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def get_table_name(self):
|
||||
return self.xml_root_node
|
||||
|
||||
@property
|
||||
def workflow_tests(self):
|
||||
from wcs.workflow_tests import WorkflowTests
|
||||
|
@ -159,8 +165,8 @@ class TestDef(sql.TestDef):
|
|||
objects_dir = 'forms' if self.object_type == 'formdefs' else 'cards'
|
||||
return '%s/%s/%s/tests/%s/' % (base_url, objects_dir, self.object_id, self.id)
|
||||
|
||||
def store(self, *args, **kwargs):
|
||||
super().store(*args, **kwargs)
|
||||
def store(self, comment=None):
|
||||
super().store()
|
||||
|
||||
self.workflow_tests.testdef_id = self.id
|
||||
self.workflow_tests.testdef = self
|
||||
|
@ -172,6 +178,9 @@ class TestDef(sql.TestDef):
|
|||
response.testdef_id = self.id
|
||||
response.store()
|
||||
|
||||
if get_publisher().snapshot_class:
|
||||
get_publisher().snapshot_class.snap(instance=self, comment=comment)
|
||||
|
||||
@classmethod
|
||||
def remove_object(cls, id):
|
||||
super().remove_object(id)
|
||||
|
@ -524,7 +533,7 @@ class TestDef(sql.TestDef):
|
|||
def export_to_xml(self, include_id=False):
|
||||
self._webservice_responses = self.get_webservice_responses()
|
||||
|
||||
testdef_xml = TestDefXmlProxy()
|
||||
testdef_xml = TestDefXmlProxy(id=str(self.id))
|
||||
for field, dummy in TestDefXmlProxy.XML_NODES: # pylint: disable=not-an-iterable
|
||||
setattr(testdef_xml, field, getattr(self, field))
|
||||
|
||||
|
@ -539,11 +548,14 @@ class TestDef(sql.TestDef):
|
|||
return cls.import_from_xml_tree(tree, formdef, include_id=include_id)
|
||||
|
||||
@classmethod
|
||||
def import_from_xml_tree(cls, tree, formdef, include_id=False):
|
||||
testdef = TestDef.create_from_formdata(formdef, formdef.data_class()())
|
||||
def import_from_xml_tree(cls, tree, formdef=None, include_id=False, **kwargs):
|
||||
testdef = TestDef.create_from_formdata(formdef, formdef.data_class()()) if formdef else TestDef()
|
||||
|
||||
testdef_xml = TestDefXmlProxy.import_from_xml_tree(tree, include_id)
|
||||
for field, dummy in TestDefXmlProxy.XML_NODES: # pylint: disable=not-an-iterable
|
||||
if formdef and field in ('object_type', 'object_id'):
|
||||
continue
|
||||
|
||||
if hasattr(testdef_xml, field):
|
||||
setattr(testdef, field, getattr(testdef_xml, field))
|
||||
|
||||
|
|
Loading…
Reference in New Issue