Skip to content

Commit

Permalink
Merge 21617a2 into 5be30ab
Browse files Browse the repository at this point in the history
  • Loading branch information
atodorov committed May 9, 2020
2 parents 5be30ab + 21617a2 commit acd70c1
Show file tree
Hide file tree
Showing 11 changed files with 58 additions and 101 deletions.
2 changes: 1 addition & 1 deletion tcms/bugs/views.py
Expand Up @@ -73,7 +73,7 @@ def get_form_kwargs(self):
return kwargs

def get_form(self, form_class=None):
form = super().get_form()
form = super().get_form(form_class)
# clear fields which are set dynamically via JavaScript
form.populate(self.request.POST.get('product', -1))
return form
Expand Down
4 changes: 2 additions & 2 deletions tcms/testcases/views.py
Expand Up @@ -54,7 +54,7 @@ class NewCaseView(CreateView):
template_name = 'testcases/mutable.html'

def get_form(self, form_class=None):
form = super().get_form()
form = super().get_form(form_class)
# clear fields which are set dynamically via JavaScript
form.populate(self.request.POST.get('product', -1))
return form
Expand Down Expand Up @@ -323,7 +323,7 @@ def get_context_data(self, **kwargs):
return context

def get_form(self, form_class=None):
form = super().get_form()
form = super().get_form(form_class)
if self.request.POST.get('product'):
form.populate(product_id=self.request.POST['product'])
else:
Expand Down
11 changes: 2 additions & 9 deletions tcms/testplans/forms.py
Expand Up @@ -77,15 +77,8 @@ class ClonePlanForm(forms.Form):
empty_label=None,
)

copy_testcases = forms.BooleanField(
help_text='Unchecking will create a link to selected plans',
required=False
)
set_parent = forms.BooleanField(
help_text='Check it to set the source plan as parent of new cloned '
'plan.',
required=False
)
copy_testcases = forms.BooleanField(required=False)
set_parent = forms.BooleanField(required=False)

def populate(self, product_pk):
if product_pk:
Expand Down
10 changes: 6 additions & 4 deletions tcms/testplans/templates/testplans/clone.html
Expand Up @@ -6,8 +6,8 @@

{% block contents %}
<div class="container-fluid container-cards-pf">
<form class="form-horizontal" method="post" action="{% url "plans-clone" %}">
<input type="hidden" name="plan" value="{{ test_plan.pk }}">
<form class="form-horizontal" method="post" action="{% url "plans-clone" object.pk %}">
{% csrf_token %}

<div class="form-group">
<label class="col-md-1 col-lg-1" for="id_name">{% trans "Name" %}</label>
Expand Down Expand Up @@ -53,14 +53,16 @@
<div class="form-group">
<label class="col-md-1 col-lg-1" for="id_copy_testcases">{% trans "Clone TCs" %}</label>
<div class="col-md-3 col-lg-3">
<input class="bootstrap-switch" id="id_copy_testcases" name="copy_testcases" type="checkbox">
<input class="bootstrap-switch" id="id_copy_testcases" name="copy_testcases"
type="checkbox" {% if form.copy_testcases.value %}checked{% endif %}>
<p class="help-block">{% trans "Clone or link existing TCs into new TP" %}</p>
</div>


<label class="col-md-1 col-lg-1" for="id_set_parent">{% trans "Parent TP" %}</label>
<div class="col-md-3 col-lg-3">
<input class="bootstrap-switch" id="id_set_parent" name="set_parent" type="checkbox">
<input class="bootstrap-switch" id="id_set_parent" name="set_parent"
type="checkbox" {% if form.set_parent.value %}checked{% endif %}>
<p class="help-block">{% trans "Set the source TP as parent of new TP" %}</p>
</div>
</div>
Expand Down
36 changes: 8 additions & 28 deletions tcms/testplans/tests/tests.py
Expand Up @@ -134,7 +134,7 @@ class TestCloneView(BasePlanCase):

@classmethod
def setUpTestData(cls):
super(TestCloneView, cls).setUpTestData()
super().setUpTestData()

cls.another_plan = TestPlanFactory(
name='Another plan for test',
Expand Down Expand Up @@ -173,31 +173,13 @@ def setUpTestData(cls):
cls.plan_tester.set_password('password')
cls.plan_tester.save()
user_should_have_perm(cls.plan_tester, 'testplans.add_testplan')
cls.plan_clone_url = reverse('plans-clone')

def test_refuse_if_missing_a_plan(self):
self.client.login( # nosec:B106:hardcoded_password_funcarg
username=self.plan_tester.username,
password='password')

data_missing_plan = {} # No plan is passed
response = self.client.post(self.plan_clone_url, data_missing_plan, follow=True)
self.assertContains(response, _('TestPlan is required'))

def test_refuse_if_given_nonexisting_plan(self):
self.client.login( # nosec:B106:hardcoded_password_funcarg
username=self.plan_tester.username,
password='password')

response = self.client.post(self.plan_clone_url, {'plan': 99999}, follow=True)
self.assertEqual(HTTPStatus.NOT_FOUND, response.status_code)

def test_open_clone_page_to_clone_one_plan(self):
self.client.login( # nosec:B106:hardcoded_password_funcarg
username=self.plan_tester.username,
password='password')

response = self.client.post(self.plan_clone_url, {'plan': self.plan.pk})
response = self.client.get(reverse('plans-clone', args=[self.plan.pk]))

self.assertContains(
response,
Expand Down Expand Up @@ -250,7 +232,6 @@ def _verify_options(self, original_plan, cloned_plan, copy_cases):
def test_clone_a_plan_with_default_options(self):
post_data = {
'name': self.third_plan.make_cloned_name(),
'plan': self.third_plan.pk,
'product': self.product.pk,
'version': self.version.pk,
'set_parent': 'on',
Expand All @@ -259,7 +240,8 @@ def test_clone_a_plan_with_default_options(self):
self.client.login( # nosec:B106:hardcoded_password_funcarg
username=self.plan_tester.username,
password='password')
response = self.client.post(self.plan_clone_url, post_data)
response = self.client.post(reverse('plans-clone', args=[self.third_plan.pk]),
post_data)

cloned_plan = TestPlan.objects.get(name=self.third_plan.make_cloned_name())

Expand All @@ -273,35 +255,33 @@ def test_clone_a_plan_with_default_options(self):
def test_clone_a_plan_by_copying_cases(self):
post_data = {
'name': self.totally_new_plan.make_cloned_name(),
'plan': self.totally_new_plan.pk,
'product': self.product.pk,
'version': self.version.pk,
'set_parent': 'on',
'submit': 'Clone',

'copy_testcases': 'on',
}
self.client.login( # nosec:B106:hardcoded_password_funcarg
username=self.plan_tester.username,
password='password')
self.client.post(self.plan_clone_url, post_data)
self.client.post(reverse('plans-clone', args=[self.totally_new_plan.pk]),
post_data)
cloned_plan = TestPlan.objects.get(name=self.totally_new_plan.make_cloned_name())
self.verify_cloned_plan(self.totally_new_plan, cloned_plan, copy_cases=True)

def test_clone_a_plan_by_setting_me_to_copied_cases_author_default_tester(self):
post_data = {
'name': self.totally_new_plan.make_cloned_name(),
'plan': self.totally_new_plan.pk,
'product': self.product.pk,
'version': self.version.pk,
'set_parent': 'on',
'submit': 'Clone',

'copy_testcases': 'on',
}
self.client.login( # nosec:B106:hardcoded_password_funcarg
username=self.plan_tester.username,
password='password')
self.client.post(self.plan_clone_url, post_data)
self.client.post(reverse('plans-clone', args=[self.totally_new_plan.pk]),
post_data)
cloned_plan = TestPlan.objects.get(name=self.totally_new_plan.make_cloned_name())
self.verify_cloned_plan(self.totally_new_plan, cloned_plan, copy_cases=True)
4 changes: 4 additions & 0 deletions tcms/testplans/urls/plan_urls.py → tcms/testplans/urls.py
Expand Up @@ -11,4 +11,8 @@
name='test_plan_url'),

url(r'^(?P<pk>\d+)/edit/$', views.Edit.as_view(), name='plan-edit'),
url(r'^(?P<pk>\d+)/clone/$', views.Clone.as_view(), name='plans-clone'),

url(r'^search/$', views.SearchTestPlanView.as_view(), name='plans-search'),
url(r'^new/$', views.NewTestPlanView.as_view(), name='plans-new'),
]
4 changes: 0 additions & 4 deletions tcms/testplans/urls/__init__.py

This file was deleted.

11 changes: 0 additions & 11 deletions tcms/testplans/urls/plans_urls.py

This file was deleted.

72 changes: 33 additions & 39 deletions tcms/testplans/views.py
@@ -1,18 +1,16 @@
# -*- coding: utf-8 -*-

from django.contrib import messages
from django.contrib.auth.decorators import permission_required
from django.db.models import Count
from django.http import (HttpResponsePermanentRedirect,
HttpResponseRedirect)
from django.shortcuts import get_object_or_404, render
from django.test import modify_settings
from django.urls import reverse
from django.utils.decorators import method_decorator
from django.utils.translation import gettext_lazy as _
from django.views.generic import DetailView, View
from django.views.generic import DetailView
from django.views.generic.base import TemplateView
from django.views.generic.edit import CreateView, UpdateView
from django.views.generic.edit import CreateView, FormView, UpdateView
from uuslug import slugify

from tcms.core.response import ModifySettingsTemplateResponse
Expand All @@ -27,7 +25,7 @@ class NewTestPlanView(CreateView):
template_name = 'testplans/mutable.html'

def get_form(self, form_class=None):
form = super().get_form()
form = super().get_form(form_class)
# clear fields which are set dynamically via JavaScript
form.populate(self.request.POST.get('product', -1))
return form
Expand Down Expand Up @@ -62,7 +60,7 @@ class Edit(UpdateView):
template_name = 'testplans/mutable.html'

def get_form(self, form_class=None):
form = super().get_form()
form = super().get_form(form_class)
if self.request.POST.get('product'):
form.populate(product_id=self.request.POST['product'])
else:
Expand Down Expand Up @@ -138,9 +136,7 @@ def render_to_response(self, context, **response_kwargs):
),
(
_('Clone'),
# todo: URL accepts POST, need to refactor to use GET+POST
# e.g. plans/3/clone/
reverse('plans-clone')
reverse('plans-clone', args=[self.object.pk])
),
(
_('History'),
Expand Down Expand Up @@ -175,41 +171,39 @@ def get(self, request, *args, **kwargs):


@method_decorator(permission_required('testplans.add_testplan'), name='dispatch')
class Clone(View):
http_method_names = ['post']
class Clone(FormView):
template_name = 'testplans/clone.html'
form_class = ClonePlanForm
object = None

def post(self, request):
if 'plan' not in request.POST:
messages.add_message(request,
messages.ERROR,
_('TestPlan is required'))
# redirect back where we came from
return HttpResponseRedirect(request.META.get('HTTP_REFERER', '/'))

plan_id = request.POST.get('plan', 0)
test_plan = get_object_or_404(TestPlan, pk=int(plan_id))
def get(self, request, *args, **kwargs):
self.object = TestPlan.objects.get(pk=kwargs['pk'])
return super().get(request, *args, **kwargs)

post_data = request.POST.copy()
if not request.POST.get('name'):
post_data['name'] = test_plan.make_cloned_name()
def post(self, request, *args, **kwargs):
self.object = TestPlan.objects.get(pk=kwargs['pk'])
return super().post(request, *args, **kwargs)

form = ClonePlanForm(post_data)
form.populate(product_pk=request.POST.get('product'))
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['object'] = self.object
return context

# if required values are missing we are still going to show
# the form below, otherwise clone & redirect
if form.is_valid():
form.cleaned_data['new_author'] = request.user
cloned_plan = test_plan.clone(**form.cleaned_data)
def get_form(self, form_class=None):
form = super().get_form(form_class)
form.populate(self.object.product_id)
return form

return HttpResponseRedirect(
reverse('test_plan_url_short', args=[cloned_plan.pk]))
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['initial']['name'] = self.object.make_cloned_name()
kwargs['initial']['product'] = self.object.product
kwargs['initial']['version'] = self.object.product_version
return kwargs

# form wasn't valid
context_data = {
'test_plan': test_plan,
'form': form,
}
def form_valid(self, form):
form.cleaned_data['new_author'] = self.request.user
cloned_plan = self.object.clone(**form.cleaned_data)

return render(request, self.template_name, context_data)
return HttpResponseRedirect(
reverse('test_plan_url_short', args=[cloned_plan.pk]))
2 changes: 1 addition & 1 deletion tcms/testruns/views.py
Expand Up @@ -278,7 +278,7 @@ def get_context_data(self, **kwargs):
return context

def get_form(self, form_class=None):
form = super().get_form()
form = super().get_form(form_class)
form.populate(self.object.plan.product_id)

return form
Expand Down
3 changes: 1 addition & 2 deletions tcms/urls.py
Expand Up @@ -37,8 +37,7 @@
url(r'^accounts/', include(auth_urls)),

# Testplans zone
url(r'^plan/', include(testplans_urls.plan_urls)),
url(r'^plans/', include(testplans_urls.plans_urls)),
url(r'^plan/', include(testplans_urls)),

# Testcases zone
url(r'^case/', include(testcases_urls.case_urls)),
Expand Down

0 comments on commit acd70c1

Please sign in to comment.