admin: add test duplication (#75172) #155

Merged
vdeniaud merged 1 commits from wip/75172-testdef-pouvoir-dupliquer-un-tes into main 2023-03-28 11:42:03 +02:00
4 changed files with 83 additions and 10 deletions

View File

@ -550,3 +550,43 @@ def test_tests_run_order(pub):
assert resp.text.count('Success!') == 1
assert resp.text.count('Empty value for field') == 1
assert resp.text.index('Failing test') < resp.text.index('Passing test')
def test_tests_duplicate(pub):
user = create_superuser(pub)
formdef = FormDef()
formdef.name = 'test title'
formdef.fields = [fields.StringField(id='1', varname='test field', label='Test', type='string')]
formdef.store()
formdata = formdef.data_class()()
formdata.just_created()
formdata.receipt_time = datetime.datetime(2021, 1, 1, 0, 0).timetuple()
formdata.data['1'] = 'abcdefg'
formdata.user_id = user.id
formdata.store()
testdef = TestDef.create_from_formdata(formdef, formdata)
testdef.name = 'First test'
testdef.store()
app = login(get_app(pub))
assert TestDef.count() == 1
resp = app.get('/backoffice/forms/1/tests/%s/' % testdef.id)
resp = resp.click('Duplicate')
resp = resp.form.submit().follow()
assert 'First test (copy)' in resp.text
assert 'abcdefg' in resp.text
assert TestDef.count() == 2
resp = app.get('/backoffice/forms/1/tests/%s/' % testdef.id)
resp = resp.click('Duplicate')
resp = resp.form.submit().follow()
assert 'First test (copy 2)' in resp.text
assert 'abcdefg' in resp.text
assert TestDef.count() == 3

View File

@ -101,7 +101,7 @@ class TestEditPage(FormBackofficeEditPage):
class TestPage(FormBackOfficeStatusPage):
_q_extra_exports = ['delete', 'export', 'edit', ('edit-data', 'edit_data')]
_q_extra_exports = ['delete', 'export', 'edit', ('edit-data', 'edit_data'), 'duplicate']
def __init__(self, component, objectdef):
try:
@ -214,6 +214,38 @@ class TestPage(FormBackOfficeStatusPage):
self.testdef.store()
return redirect('.')
def duplicate(self):
form = Form(enctype='multipart/form-data')
name_widget = form.add(StringWidget, 'name', title=_('Name'), required=True, size=30)
form.add_submit('submit', _('Submit'))
form.add_submit('cancel', _('Cancel'))
if form.get_widget('cancel').parse():
return redirect('.')
if not form.is_submitted():
original_name = self.testdef.name
new_name = '%s %s' % (original_name, _('(copy)'))
names = [x.name for x in TestDef.select_for_objectdef(self.formdef)]
no = 2
while new_name in names:
new_name = _('%(name)s (copy %(no)d)') % {'name': original_name, 'no': no}
no += 1
name_widget.set_value(new_name)
if not form.is_submitted() or form.has_errors():
html_top('duplicate_test', title=_('Duplicate test'))
r = TemplateIO(html=True)
get_response().breadcrumb.append(('duplicate', _('Duplicate')))
r += htmltext('<h2>%s</h2>') % _('Duplicate test')
r += form.render()
return r.getvalue()
self.testdef.id = None
self.testdef.slug = None
self.testdef.name = form.get_widget('name').parse()
self.testdef.store()
return redirect(self.testdef.get_admin_url())
class TestsDirectory(Directory):
_q_exports = ['', 'new', ('import', 'p_import'), 'results']
@ -233,9 +265,7 @@ class TestsDirectory(Directory):
def _q_index(self):
context = {
'testdefs': TestDef.select(
[Equal('object_type', self.objectdef.get_table_name()), Equal('object_id', self.objectdef.id)]
),
'testdefs': TestDef.select_for_objectdef(self.objectdef),
'formdata': self.objectdef.data_class().select([StrictNotEqual('status', 'draft')]),
'has_deprecated_fields': any(
x.type in ('table', 'table-select', 'tablerows', 'ranked-items')
@ -336,9 +366,7 @@ class TestResultPage(Directory):
return super()._q_traverse(path)
def _q_index(self):
testdefs = TestDef.select(
[Equal('object_type', self.objectdef.get_table_name()), Equal('object_id', self.objectdef.id)]
)
testdefs = TestDef.select_for_objectdef(self.objectdef)
testdefs_by_id = {x.id: x for x in testdefs}
for test in self.test_result.results:
if test['id'] in testdefs_by_id:
@ -413,9 +441,7 @@ class TestsAfterJob(AfterJob):
@staticmethod
def run_tests(objectdef, reason):
testdefs = TestDef.select(
[Equal('object_type', objectdef.get_table_name()), Equal('object_id', objectdef.id)]
)
testdefs = TestDef.select_for_objectdef(objectdef)
if not testdefs:
return

View File

@ -3,6 +3,7 @@
<ul id="sidebar-actions">
<li><a rel="popup" href="edit">{% trans "Options" %}</a></li>
<li><a href="inspect">{% trans "Inspect" %}</a></li>
<li><a href="duplicate">{% trans "Duplicate" %}</a></li>
<li><a href="export">{% trans "Export" %}</a></li>
<li><a rel="popup" href="delete">{% trans "Delete" %}</a></li>
</ul>

View File

@ -70,6 +70,12 @@ class TestDef(sql.TestDef):
i += 1
super().store(*args, **kwargs)
@classmethod
def select_for_objectdef(cls, objectdef):
return cls.select(
[Equal('object_type', objectdef.get_table_name()), Equal('object_id', objectdef.id)]
)
@classmethod
def create_from_formdata(cls, formdef, formdata):
testdef = cls()